關於七牛雲視訊開發api

呂建奎發表於2016-04-15
作者:樑濤
連結:http://zhuanlan.zhihu.com/p/19659738
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

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

本篇從獲取音視訊元資訊入手,順序講解各個處理指令。

■ 獲取音視訊元資訊

使用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程式來完成。


1. [簡易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

2. [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

點選檢視轉碼效果

相關文章