七牛云试用指南-音视频基本处理

1606 查看

对于音频、视频等多媒体资源,七牛云也提供了丰富的处理指令,包含但不限于以下指令:

本篇从获取音视频元信息入手,顺序讲解各个处理指令。

■ 获取音视频元信息

使用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 署名-非商业性使用-禁止演绎

允许自由转载,请注明作者及出处。