Current section
Files
Jump to
Current section
Files
lib/aliyun_api/vod/cli.ex
defmodule AliyunAPI.VOD do
import AliyunAPI, only: [url_encode: 1]
require Logger
@doc """
url: https://help.aliyun.com/document_detail/55619.html
## opts
* :`title`
* :`image_type` 图片类型。
取值范围:
- default(默认)
- cover(封面)
- watermark(水印)
* :`image_ext` png, jpg, jpeg
* :`tags` 数组
"""
def create_upload_image(opts \\ []) do
arguments =
"CreateUploadImage"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"Title" => opts[:title],
"ImageType" => opts[:image_type] || "default",
"ImageExt" => opts[:image_ext] || "png",
"Tags" => _normalize_params_tags(opts[:app], opts)
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response(fn body ->
response_data = Jason.decode!(body, keys: :atoms)
%{
RequestId: response_data[:RequestId],
ImageId: response_data[:ImageId],
UploadAddress: response_data[:UploadAddress] |> _decode_data(),
UploadAuth: response_data[:UploadAuth] |> _decode_data()
}
end)
end
@doc """
url: https://help.aliyun.com/document_detail/55408.html
## opts
* :`video_id`
"""
def refresh_upload_video(opts \\ []) do
arguments =
"RefreshUploadVideo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => opts[:video_id]
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response(fn body ->
response_data = Jason.decode!(body, keys: :atoms)
%{
RequestId: response_data[:RequestId],
VideoId: response_data[:VideoId],
UploadAddress: response_data[:UploadAddress] |> _decode_data(),
UploadAuth: response_data[:UploadAuth] |> _decode_data()
}
end)
end
@doc """
url: https://help.aliyun.com/document_detail/55407.html
## opts
* :`title` [必须]
* :`file_name` [必须]
* :`file_size`
* :`description`
* :`cover_url`
* :`category_id`
* :`tags`
* :`template_group_id`
* :`user_data`
* :`storage_location` 存储地址。当不为空时,会使用该指定的存储地址上传视频文件。可在 点播控制台 > 存储管理 里查看存储地址。
"""
def create_upload_video(opts \\ []) do
arguments =
"CreateUploadVideo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"Title" => opts[:title],
"FileName" => opts[:file_name],
"FileSize" => opts[:file_size],
"Description" => opts[:description],
"CoverURL" => opts[:cover_url],
"CateId" => _normalize_params_category_id(opts[:app], opts),
"Tags" => _normalize_params_tags(opts[:app], opts),
"TemplateGroupId" => opts[:template_group_id],
"UserData" => (opts[:user_data] || %{}) |> Jason.encode!(),
"StorageLocation" => opts[:storage_location]
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response(fn body ->
response_data = Jason.decode!(body, keys: :atoms)
%{
RequestId: response_data[:RequestId],
VideoId: response_data[:VideoId],
UploadAddress: response_data[:UploadAddress] |> _decode_data(),
UploadAuth: response_data[:UploadAuth] |> _decode_data()
}
end)
end
@doc """
https://help.aliyun.com/document_detail/56124.html
通过视频ID直接获取媒体文件(支持视频和音频)的播放地址。
## video_id
## opts
* :`formats`
* :`auth_timeout`
* :`stream_type`
* :`definition`
* :`result_type`
- Single(每种清晰度和格式只返回一路最新转码完成的流) [默认]
- Multiple(每种清晰度和格式返回所有转码完成的流)
* :`output_type`
* :`play_config`
"""
def get_play_info(video_id, opts \\ []) do
arguments =
"GetPlayInfo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"AuthTimeout" => opts[:auth_timeout],
"StreamType" => opts[:stream_type],
"Definition" => opts[:definition],
"ResultType" => opts[:result_type] || "Single",
"OutputType" => opts[:output_type],
"PlayConfig" => (opts[:play_config] || %{}) |> Jason.encode!()
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/52833.html
获取视频播放时所需的播放凭证。
## video_id
## opts
* :`auth_info_timeout`
* :`play_config`
"""
def get_video_play_auth(video_id, opts \\ []) do
arguments =
"GetVideoPlayAuth"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"AuthInfoTimeout" => opts[:auth_info_timeout],
"PlayConfig" => (opts[:play_config] || %{}) |> Jason.encode!()
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/86044.html
搜索媒体信息(视频、音频等)。
## opts
* :`search_type`
搜索数据类型。取值范围:
- video(视频,默认值)
- audio(音频)
- image(图片)
* :`fields`
* :`match`
* :`scroll_token`
* :`page`
* :`limit`
* :`sort_by`
* :`status`
状态码的文档:https://help.aliyun.com/document_detail/52839.html
"""
def search_media(opts \\ []) do
status =
opts[:status]
|> AliyunAPI.to_array(uniq: true)
|> Enum.map(fn status ->
"'#{status}'"
end)
match = opts[:match] |> to_string()
match =
cond do
Enum.any?(status) && String.length(match) == 0 ->
"Status in (#{Enum.join(status, ", ")})"
Enum.any?(status) && String.length(match) > 0 ->
match <> " and " <> "Status in (#{Enum.join(status, ", ")})"
true ->
match
end
arguments =
"SearchMedia"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"SearchType" => opts[:search_type],
"Fields" => opts[:fields] |> AliyunAPI.to_array(uniq: true) |> Enum.join(","),
"Match" => match,
"ScrollToken" => opts[:scroll_token],
"PageNo" => opts[:page] || 1,
"PageSize" => opts[:limit] || 10,
"SortBy" => "CreationTime:#{if opts[:sort_by] == :asc, do: "Asc", else: "Desc"}"
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/52835.html
通过视频ID获取视频的基本信息,包括视频标题、描述、时长、封面URL、状态、创建时间、大小、截图、分类和标签等。
## video_id
## opts
"""
def get_video_info(video_id, opts \\ []) do
arguments =
"GetVideoInfo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/52836.html
修改视频信息
## video_id
## opts
* :`title`
* :`description`
* :`cover_url`
* :`category_id`
* :`tags`
"""
def update_video_info(video_id, opts \\ []) do
arguments =
"UpdateVideoInfo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"Title" => opts[:title],
"Description" => opts[:description],
"CoverURL" => opts[:cover_url],
"CateId" => _normalize_params_category_id(opts[:app], opts),
"Tags" => _normalize_params_tags(opts[:app], opts)
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/52837
删除视频
* :`video_ids`
"""
def delete_video(app, video_ids \\ []) do
arguments =
"DeleteVideo"
|> _format_arguments(app)
|> Map.merge(%{
"VideoIds" => video_ids |> AliyunAPI.to_array(uniq: true) |> Enum.join(",")
})
|> _normalize_params(app, "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(app) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
defdelegate get_videos(opts \\ []), to: __MODULE__, as: :get_video_list
@doc """
https://help.aliyun.com/document_detail/52838.html
获取视频信息列表
## opts
* :`status`
视频状态。默认获取所有视频,多个用逗号分隔,如:Uploading,Normal。取值范围:
- Uploading(上传中)
- UploadSucc(上传完成)
- Transcoding(转码中)
- TranscodeFail(转码失败)
- Checking(审核中)
- Blocked(屏蔽)
- Normal(正常)
* :start_time
* :end_time
* :category_id
* :page
* :limit
* :sort_by
"""
def get_video_list(opts \\ []) do
arguments =
"GetVideoList"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"Status" => opts[:status],
"StartTime" => opts[:start_time] |> _format_time(),
"EndTime" => opts[:end_time] |> _format_time(),
"CateId" => _normalize_params_category_id(opts[:app], opts),
"PageNo" => opts[:page] || 1,
"PageSize" => opts[:limit] || 10,
"SortBy" => "CreationTime:#{if opts[:sort_by] == :asc, do: "Asc", else: "Desc"}"
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/68570.html
提交转码作业
## video_id
## template_group_id
## opts
* :`encrypt_config`
"""
def submit_transcode_jobs(video_id, template_group_id, opts \\ []) do
arguments =
"SubmitTranscodeJobs"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"TemplateGroupId" => template_group_id,
"EncryptConfig" => opts[:encrypt_config]
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/62130.html
删除媒体流
## video_id
## job_ids
"""
def delete_stream(video_id, job_ids, opts \\ []) do
arguments =
"DeleteStream"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"JobIds" => job_ids |> AliyunAPI.to_array(uniq: true) |> Enum.join(",")
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/59624.html
获取视频源文件地址。
## video_id
## opts
* :`auth_timeout`
* :`output_type`
* :`addition_type`
"""
def get_mezzanine_info(video_id, opts \\ []) do
arguments =
"GetMezzanineInfo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoId" => video_id,
"AuthTimeout" => opts[:auth_timeout],
"AdditionType" => opts[:addition_type],
"OutputType" => opts[:output_type]
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/86042.html
通过视频ID列表获取多个视频的基本信息,包括视频标题、描述、时长、封面URL、状态、创建时间、大小、截图、分类和标签等。
## video_ids
"""
def get_video_infos(video_ids, opts \\ []) do
arguments =
"GetVideoInfos"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoIds" => video_ids |> AliyunAPI.to_array(uniq: true) |> Enum.join(",")
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/93109.html
批量删除源文件
## video_ids
视频ID列表。一次最多支持20个视频ID,多个用逗号分隔。
## opts
* :`force` 强制删除源文件,默认取值为false。
注:当视频转码模式为不转码即分片或异步转码时,由于源文件会作为原画用于播放,默认不可删除该视频的源文件,若需要强制删除该视频的源文件,可将值置为true。
"""
def delete_mezzanines(video_ids, opts \\ []) do
arguments =
"DeleteMezzanines"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"VideoIds" => video_ids |> AliyunAPI.to_array(uniq: true) |> Enum.join(","),
"Force" => opts |> Keyword.get(:force, false)
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/89744.html
删除图片
## delete_image_type
图片类型。
* ImageURL,图片URL。
* ImageId,图片ID。
* VideoId, 视频图片。
## opts
* :image_urls
* :image_ids
* :video_id
* :image_type
"""
def delete_image(delete_image_type, opts \\ []) do
arguments =
"DeleteImage"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"DeleteImageType" => delete_image_type,
"ImageURLs" => opts[:image_urls] |> AliyunAPI.to_array(uniq: true) |> Enum.join(","),
"ImageIds" => opts[:image_ids] |> AliyunAPI.to_array(uniq: true) |> Enum.join(","),
"VideoId" => opts[:video_id],
"ImageType" => opts[:image_type]
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/89742.html
获取图片信息
## image_id
## opts
: auth_timeout
"""
def get_image_info(image_id, opts \\ []) do
arguments =
"GetImageInfo"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"ImageId" => image_id
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
@doc """
https://help.aliyun.com/document_detail/91004.html
批量修改视频信息
## update_contents
"""
def update_image_infos(update_contents, opts \\ []) do
arguments =
"UpdateImageInfos"
|> _format_arguments(opts[:app])
|> Map.merge(%{
"UpdateContent" =>
update_contents
|> Enum.map(fn content ->
%{
ImageId: content[:image_id],
Title: content[:title],
Description: content[:description],
Tags: _normalize_params_tags(opts[:app], content)
}
|> Enum.filter(fn {_key, value} ->
"#{value}" |> String.length() > 0
end)
|> Map.new()
end)
|> AliyunAPI.to_array(uniq: true)
|> Jason.encode!()
})
|> _normalize_params(opts[:app], "GET")
("http://" <> AliyunAPI.Env.vod_endpoint(opts[:app]) <> "/?#{URI.encode_query(arguments)}")
|> AliyunAPI.http_request(:get)
|> _parse_http_response()
end
defp _get_signature(arguments, app, method) do
args =
arguments
|> Enum.sort_by(fn {key, _} -> key end)
|> Enum.map(fn {key, val} -> {url_encode(key), url_encode(val)} end)
|> Enum.map(fn {key, val} -> "#{key}=#{val}" end)
|> Enum.join("&")
string_to_sign =
"#{String.upcase(method)}" <> "&" <> url_encode("/") <> "&" <> url_encode(args)
:sha
|> :crypto.hmac("#{AliyunAPI.Env.vod_access_key_secret(app)}&", string_to_sign)
|> Base.encode64()
end
defp _format_arguments(action, app) do
%{
"Format" => "JSON",
"Version" => AliyunAPI.Env.vod_version(app),
"SignatureMethod" => "HMAC-SHA1",
"SignatureNonce" => AliyunAPI.SecureRandom.uuid(),
"SignatureVersion" => AliyunAPI.Env.vod_signature_version(app),
"Action" => action,
"AccessKeyId" => AliyunAPI.Env.vod_access_key_id(app),
"Timestamp" => Timex.format!(Timex.now(), "%Y-%m-%dT%H:%M:%SZ", :strftime)
}
end
defp _decode_data(data) do
data |> :base64.decode() |> Jason.decode!(keys: :atoms)
end
defp _format_time(nil), do: ""
defp _format_time(""), do: ""
defp _format_time(%DateTime{} = time) do
time |> Timex.format!("%FT%TZ", :strftime)
end
defp _parse_http_response(http_response) do
_parse_http_response(http_response, fn body ->
Jason.decode!(body, keys: :atoms)
end)
end
defp _parse_http_response(
{:ok, %HTTPoison.Response{status_code: 200, body: body, headers: headers}},
success_fn
) do
{:ok, 200,
%{
data: success_fn.(body),
body: body,
headers: headers
}}
end
defp _parse_http_response(
{:ok, %HTTPoison.Response{status_code: status_code, body: body, headers: headers}},
_success_fn
) do
{:error, status_code,
%{
data: Jason.decode!(body, keys: :atoms),
body: body,
headers: headers
}}
end
defp _parse_http_response({:error, %HTTPoison.Error{reason: reason}}, _success_fn) do
{:error, reason}
end
defp _normalize_params(arguments, app, http_method) do
arguments = arguments |> AliyunAPI.filter_params()
signature = arguments |> _get_signature(app, http_method)
arguments |> Map.put("Signature", signature)
end
defp _normalize_params_tags(app, opts) do
(opts[:tags] || [])
|> AliyunAPI.to_array(uniq: true)
|> Enum.map(fn tag ->
cond do
is_atom(tag) ->
(AliyunAPI.Env.vod_tags(app) || %{})
|> Map.get(tag)
|> to_string()
true ->
tag |> to_string()
end
end)
|> Enum.uniq()
|> Enum.filter(fn tag ->
String.length(tag) > 0
end)
|> Enum.join(",")
end
defp _normalize_params_category_id(app, opts) do
category_id = opts[:category_id]
cond do
is_atom(category_id) ->
(AliyunAPI.Env.vod_categories(app) || %{})
|> Map.get(category_id)
|> to_string()
true ->
category_id |> to_string()
end
end
end