对于音频、视频等多媒体资源,七牛云也提供了丰富的处理指令,包含但不限于以下指令:
- 音视频元信息(avinfo)
- 基本音视频处理(avthumb)
- 视频截图(vframe)
- 视频水印(vwatermark)
- 音视频切片(avthumb/m3u8/segment)
- 私有M3U8(pm3u8)
本篇从获取音视频元信息入手,顺序讲解各个处理指令。
■ 获取音视频元信息
使用avinfo接口可以非常方便地获取一个音视频资源的相关元信息:
http://<Bucket>.qiniudn.com/<Key>?avinfo
或
http://<Domain>/<Key>?avinfo
以美剧《黑名单》第1季第12集的预告片(flv资源)为例,在浏览器中打开如下URL:
http://qiniu-developer.u.qiniudn.com/samples/黑名单-S01E12.flv?avinfo
将返回一个JSON格式组织的元信息对象:
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"codec_type": "video",
"codec_time_base": "1001/60000",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 1280,
"height": 720,
...省略过长内容...
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "Advanced Audio Coding",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 2,
...省略过长内容...
}
],
"format": {
"nb_streams": 2,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime/MPEG-4/Motion JPEG 2000 format",
"start_time": "0.000000",
"duration": "29.070000",
"size": "8702170",
"bit_rate": "2394818",
"tags": {
"major_brand": "mp42",
"minor_version": "0",
"compatible_brands": "isommp42",
"creation_time": "2014-01-13 08:43:21"
}
}
}
可以看到音频、视频和封装格式信息被准确地描述出来。
■ 基本音视频处理
avthumb接口支持的基本音视频处理包括:
- 转换编码(如h264转x264,mp3转aac);
- 转换封装格式(如flv转mp4)
- 截取片段;
- 修改编码码率;
- 修改分辨率。
以前文的flv资源为例,若只想简单地转码为mp4格式,可以使用如下URL达成目的:
http://qiniu-developer.u.qiniudn.com/samples/黑名单-S01E12.flv?avthumb/mp4
接收到这样的请求后,七牛云将对指定资源执行实时转码操作,缓存结果后将新资源返回给请求端。点击查看转码效果。
注意:
- avthumb接口是同步接口,如原资源过大,将导致访问端超时返回,强烈建议使用预转持久化处理接口或触发持久化处理接口进行预处理,加快访问速度;
- 为加快访问速度,转码后的结果还将被七牛云缓存起来,不计入存储空间,节省计算资源,过期失效后会重新触发计算。
■ 预转持久化处理
上传时,通过在上传策略中指定persistentOps字段的值,可以触发七牛云对上传资源进行指定的数据处理。还可以同时指定persistentNotifyUrl字段的值,以便将持久化处理结果及时通知给业务端处理。
以前文的flv资源为例,若想预先转换成mp4格式并持久存储结果(计入存储空间),可以使用以下两个Ruby程序来完成。
- [简易HTTP服务器] 接收预转持久化处理的结果,并将状态信息打印到终端上:
#!/usr/bin/env ruby
# encoding : utf-8
# persistent_notify_server.rb
require 'json'
require 'xmlrpc/httpserver'
class PersistentNotifyHandler
@@count = 0
public
def ip_auth_handler(io)
# 任何请求都允许处理
return true
end # ip_auth_handler
def request_handler(request, response)
# 读取请求报文
body = request.data.read_nonblock(65536)
# 重新格式化JSON对象
json = JSON.generate(
JSON.parse(body),
{
indent: ' ',
object_nl: "\n",
array_nl: "\n",
}
)
# 输出
puts json
# 计数
@@count += 1
# 构造响应报文(可选)
response.body = 'OK'
end # request_handler
def self.count()
return @@count
end # self.count
end # PersistentNotifyHandler
svr = HttpServer.new(
PersistentNotifyHandler.new(), # 请求处理器
9090, # 端口
'0.0.0.0' # 监听IP
)
svr.start
while (PersistentNotifyHandler.count() == 0)
puts 'waiting for notification...'
sleep(60)
end
svr.shutdown
- [HTTP客户端] 上传flv文件并触发预转持久化处理:
#!/usr/bin/env ruby
# encoding : utf-8
# put_flv_file.rb
require 'json'
require 'net/http'
require 'base64'
require 'openssl'
# 根据传入参数,构造一个上传策略(触发预转持久化处理)
def put_policy(bucket, expires, persistentOps, persistentNotifyUrl)
# 生成一个Hash对象
put_policy = Hash.new()
# 仅指定目标存储空间,即“新增资源”语意:
# 资源不存在则创建
# 资源已存在,且与上传内容不一致则失败
put_policy['scope'] = "#{bucket}"
# 计算授权有效期截止时间,UNIX时间戳格式
put_policy['deadline'] = (Time.now() + expires).tv_sec()
# 指定预转持久化处理的指令
put_policy['persistentOps'] = persistentOps
# 指定预转持久化处理的结果通知URL
put_policy['persistentNotifyUrl'] = persistentNotifyUrl
# 序列化为JSON字符串
return JSON.generate(put_policy)
end # put_policy
# 根据传入的上传策略,生成对应的上传授权凭证
def upload_token(access_key, secret_key, put_policy)
# 对上传策略做UrlSafe-Base64编码
encoded_put_policy = Base64.urlsafe_encode64(put_policy)
# 使用SHA1作为HASH函数,生成签名
sign = OpenSSL::HMAC.digest(
'sha1',
secret_key,
encoded_put_policy
)
# 对签名做UrlSafe-Base64编码
encoded_sign = Base64.urlsafe_encode64(sign)
# 拼出上传授权凭证,以“:”作为分隔符
return "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
end # upload_token
BUCKET = 'qiniu-ts-demo' # 使用时请更换成真实的存储空间名
EXPIRES = 3600
ACCESS_KEY = 'MY_ACCESS_KEY' # 使用时请更换成真实的AccessKey
SECRET_KEY = 'MY_SECRET_KEY' # 使用时请更换成真实的SecretKey
PERSISTENT_OPS = 'avthumb/mp4' # 持久化处理指令
PERSISTENT_NOTIFY_URL = 'http://fake.com:9090' # 使用时请更换成真实的域名和端口
# 生成上传授权凭证
upload_token = upload_token(
ACCESS_KEY,
SECRET_KEY,
put_policy(
BUCKET,
EXPIRES,
PERSISTENT_OPS,
PERSISTENT_NOTIFY_URL
)
)
# 指定请求报文中的各个参数
file_name = '黑名单-S01E12.flv' # 使用时请更换成真实的文件
file_content = File.open(file_name, 'rb') do |fh|
fh.read()
end
puts 'file size is %s' % file_content.size
boundary = 'a-string-never-exists-in-the-uploading-file'
# 生成请求报文体
req_body = <<HTTP_BODY
--#{boundary}
Content-Disposition: form-data; name="token"
#{upload_token}
--#{boundary}
Content-Disposition: form-data; name="key"
#{file_name}
--#{boundary}
Content-Disposition: form-data; name="file"; filename="#{file_name}"
Content-Type: video/x-flv
Content-Transfer-Encoding: binary
HTTP_BODY
# 转换换行符
req_body.gsub!(/\n/, "\r\n")
req_body = req_body.force_encoding('ASCII-8BIT') + file_content + "\r\n--#{boundary}--\r\n"
# 生成Headers
req_headers = Hash.new()
req_headers['Host'] = "up.qiniu.com"
req_headers['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
req_headers['Content-Length'] = "#{req_body.size}"
# 发送请求
http_client = Net::HTTP.new('up.qiniu.com', 80)
resp = http_client.post(
'/',
req_body,
req_headers
)
# 解析响应
puts "HTTP Code=#{resp.code}"
puts "HTTP Msg=#{resp.msg}"
puts "HTTP Body=#{resp.body()}"
先启动服务器,然后执行上传程序,等待一段时间后便可收到预转成功的通知结果:
[Mon Jan 20 19:10:19 2014] HttpServer 0.0.0.0:9090 client:39573 115.238.138.231<115.238.138.231> connect
{
"id":"16i99r7gjlrc8r9213",
"code":0,
"desc":"The fop was completed successfully",
"items":[
{
"cmd":"avthumb/mp4",
"code":0,
"desc":"The fop was completed successfully",
"error":"",
"hash":"lpqijRaQ4c_CPoKDL1bLWK7TUoI3",
"key":"UAA-4hndfVc5V6DJX0EvslAUBBI=/ll8spobyuu_F112ZWyG6Va4qk4Ch"
}
]
}
[Mon Jan 20 19:10:19 2014] HttpServer 0.0.0.0:9090 client:39573 disconnect
[Mon Jan 20 19:10:52 2014] HttpServer 0.0.0.0:9090 stop
其中,Key字段给出持久化的mp4资源的名字,即可以通过如下URL访问转换好的mp4视频:
http://qiniu-ts-demo.qiniudn.com/UAA-4hndfVc5V6DJX0EvslAUBBI=/ll8spobyuu_F112ZWyG6Va4qk4Ch
点击查看转码效果。
■ 咱们行进到哪儿了?
通过三个实例,初步讲解了音视频处理的基本接口(avinfo/avthumb),读者应该有能力自行编程实现上传与触发预转持久化处理。
七牛云存储 © 2014 署名-非商业性使用-禁止演绎
允许自由转载,请注明作者及出处。