七牛雲試用指南-音視頻基本處理

對於音頻、視頻等多媒體資源,七牛雲也提供了豐富的處理指令,包含但不限於如下指令:html

本篇從獲取音視頻元信息入手,順序講解各個處理指令。編程

■ 獲取音視頻元信息

使用avinfo接口能夠很是方便地獲取一個音視頻資源的相關元信息:json

http://<Bucket>.qiniudn.com/<Key>?avinfo
或
http://<Domain>/<Key>?avinfo

以美劇《黑名單》第1季第12集的預告片(flv資源)爲例,在瀏覽器中打開以下URL:segmentfault

http://qiniu-developer.u.qiniudn.com/samples/黑名單-S01E12.flv?avinfo

將返回一個JSON格式組織的元信息對象:api

{
    "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
接收到這樣的請求後,七牛雲將對指定資源執行實時轉碼操做,緩存結果後將新資源返回給請求端。點擊查看轉碼效果ruby

注意:服務器

  • 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 署名-非商業性使用-禁止演繹

容許自由轉載,請註明做者及出處。

相關文章
相關標籤/搜索