在 Serverless 架構的應用案例中,有這樣一個很是實在的應用:視頻的處理。html
騰訊雲的函數計算平臺對這個領域的描述:python
視頻應用、社交應用等場景下,用戶上傳的圖片、音視頻的總量大、頻率高,對處理系統的實時性和併發能力都有較高的要求。例如:對於用戶上傳的視頻短片,咱們可使用多個雲函數對其分別處理,對應不一樣的清晰度(1080p、720p等),以知足不一樣場景下用戶的需求,適應移動網絡帶寬較小且不穩定的特性。git
在阿里雲的函數計算也有相關的描述:github
因此能夠看到視頻的壓縮/轉碼等操做,在Serverless架構下確實是一個很好的典型"應用"。那麼有了這樣的一個"典型"應用,咱們應該如何實現它呢?shell
在百科上能夠看到這樣的描述:express
FFmpeg是一套能夠用來記錄、轉換數字音頻、視頻,並能將其轉化爲流的開源計算機程序。採用LGPL或GPL許可證。它提供了錄製、轉換以及流化音視頻的完整解決方案。它包含了很是先進的音頻/視頻編解碼庫libavcodec,爲了保證高可移植性和編解碼質量,libavcodec裏不少code都是從頭開發的。
FFmpeg在Linux平臺下開發,但它一樣也能夠在其它操做系統環境中編譯運行,包括Windows、Mac OS X等。這個項目最先由Fabrice Bellard發起,2004年至2015年間由Michael Niedermayer主要負責維護。許多FFmpeg的開發人員都來自MPlayer項目,並且當前FFmpeg也是放在MPlayer項目組的服務器上。項目的名稱來自MPEG視頻編碼標準,前面的"FF"表明"Fast Forward"。瀏覽器
而在實際生產生活中,ffmpeg確實也是一個很是好的工具,咱們能夠經過這個工具來進行圖像的壓縮/轉碼等操做。服務器
經過ffmpeg的官網,咱們能夠看到不一樣的操做系統,有着不一樣的文件供咱們選擇:網絡
也就是說,咱們若是要在雲函數中使用這個模塊,那麼咱們就要有這樣一個模塊是在雲函數所在的環境下能夠運行起來的,根據雲函數的文檔能夠看到:架構
也就是說,咱們要有一個在CentOS操做系統下可使用的ffmpeg,接下來,咱們就準備這個文件:
wget http://www.ffmpeg.org/releases/ffmpeg-3.1.tar.gz
tar -zxvf ffmpeg-3.1.tar.gz && cd ffmpeg-3.1
./configure && make && make install
在進行./configure
操做的時候,可能出現yasm/nasm not found or too old. Use --disable-yasm for a crippledbuild
錯誤。
yasm是彙編編譯器,ffmpeg爲了提升效率使用了彙編指令,如MMX和SSE等。因此係統中未安裝yasm時,就會報錯誤,此時能夠安裝yasm編譯器來解決:
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar zxvf yasm-1.3.0.tar.gz && cd yasm-1.3.0
./configure && make && make install
完成ffmpeg的編譯安裝,能夠在當前目錄下看到生成了文件:ffmpeg
此時咱們保存這個文件便可在騰訊雲的雲函數中使用。
按照騰訊雲提供的時間架構圖,咱們能夠看到其推薦的是對象存儲觸發器觸發函數,也就是說咱們將視頻存儲到對象存儲中,而後經過對象存儲的相關觸發器觸發函數,進行視頻的處理,處理以後再回傳對象存儲的操做。
代碼實現:
import os import subprocess from qcloud_cos_v5 import CosConfig from qcloud_cos_v5 import CosS3Client secret_id = os.environ.get('secret_id') secret_key = os.environ.get('secret_key') region = os.environ.get('region') cosClient = CosS3Client(CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key)) # 移動ffmpeg到tmp目錄,而且賦予權限 with open("./ffmpeg", "rb") as rf: with open("/tmp/ffmpeg", "wb") as wf: wf.write(rf.read()) subprocess.run('chmod 755 /tmp/ffmpeg', shell=True) def main_handler(event, context): for record in event['Records']: bucket = record['cos']['cosBucket']['name'] + '-' + record['cos']['cosBucket']['appid'] key = "/".join(record['cos']['cosObject']['key'].split("/")[3:]) download_path = '/tmp/{}'.format(key.split('/')[-1]) upload_path = '/tmp/new_mp4-{}'.format(key.split('/')[-1]) # 下載圖片 print("key", key) response = cosClient.get_object(Bucket=bucket, Key=key) response['Body'].get_stream_to_file(download_path) # 執行ffmpeg指令壓縮視頻 child = subprocess.run('/tmp/ffmpeg -i %s -r 10 -b:a 32k %s'%(download_path, upload_path), stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=True) # 上傳圖片 cosClient.put_object_from_local_file( Bucket=bucket, LocalFilePath=upload_path, Key="/new_mp4/" + key.split('/')[-1] )
這裏的主要操做就是在容器創建的時候,或者說是函數冷啓動的時候,將ffmpeg複製到可執行目錄,而且設置其權限爲755
。
完成以後能夠進行serverless.yaml
的編寫:
MyVideo: component: "@serverless/tencent-scf" inputs: name: MyVideo codeUri: ./ handler: index.main_handler runtime: Python3.6 region: ap-guangzhou memorySize: 128 timeout: 200 environment: variables: secret_id: 用戶密鑰id secret_key: 用戶密鑰key region: ap-guangzhou events: - cos: name: video-1256773370.cos.ap-guangzhou.myqcloud.com parameters: bucket: video-1256773370.cos.ap-guangzhou.myqcloud.com filter: prefix: source/ events: cos:ObjectCreated:* enable: true
部署完成以後,咱們將一個測試的MP4文件上傳到對應的存儲的source/
文件夾中:
稍等片刻,咱們能夠看到目標文件夾出現了對應的視頻:
能夠看到兩個視頻文件的差距。
固然,這裏僅僅是經過/tmp/ffmpeg -i 原視頻 -r 10 -b:a 32k 生成視頻
來進行視頻壓縮,除此以外,咱們還可使用ffmpeg進行額外的操做(如下內容來源於canmeng的博客):
ffmpeg -ss 00:00:00 -t 00:00:30 -i test.mp4 -vcodec copy -acodec copy output.mp4
-ss 指定從什麼時間開始
-t 指定須要截取多長時間
-i 指定輸入文件
這個命令就是從00秒開始裁剪到00+30=30秒結束,總共30秒的視頻。這個命令執行很快,由於只是原始數據的拷貝,中間沒有什麼編碼和解碼的過程。執行這個命令後你能獲得output.mp4這個輸出文件。你能夠用視頻播放軟件播放這個視頻看看。
可能有些視頻裁剪後的效果,如指望一致,00秒開始,30秒結束,總共30秒的視頻,可是有些視頻裁剪後你會發現可能開始和結束都不是很準確,有多是從00秒開始,33秒結束。這是爲何呢?
由於這些視頻裏30秒處地方恰好不是關鍵幀,而ffmpeg會在你輸入的時間點附近圓整到最接近的關鍵幀處,而後作接下來的事情。若是你不懂什麼是關鍵幀,不要緊,這也不影響你使用這個命令。
合併視頻
//截取從頭開始的30s ffmpeg -ss 00:00:00 -t 00:00:30 -i keyoutput.mp4 -vcodec copy -acodec copy split.mp4 //截取從30s開始的30s ffmpeg -ss 00:00:30 -t 00:00:30 -i keyoutput.mp4 -vcodec copy -acodec copy split1.mp4 //進行視頻的合併 ffmpeg -f concat -i list.txt -c copy concat.mp4
在list.txt文件中,對要合併的視頻片斷進行了描述。
內容以下
file ./split.mp4 file ./split1.mp4
更多經常使用命令:
ffmpeg -i in.mp4 -filter:v "crop=in_w:in_h-40" -c:a copy out.mp4 // 去掉視頻中的音頻 ffmpeg -i input.mp4 -vcodec copy -an output.mp4 // -an: 去掉音頻;-vcodec:視頻選項,通常後面加copy表示拷貝 // 提取視頻中的音頻 ffmpeg -i input.mp4 -acodec copy -vn output.mp3 // -vn: 去掉視頻;-acodec: 音頻選項, 通常後面加copy表示拷貝 // 音視頻合成 ffmpeg -y –i input.mp4 –i input.mp3 –vcodec copy –acodec copy output.mp4 // -y 覆蓋輸出文件 //剪切視頻 ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -vcodec copy -acodec copy output.mp4 // -ss 開始時間; -t 持續時間 // 視頻截圖 ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg // -s 設置分辨率; -f 強迫採用格式fmt; // 視頻分解爲圖片 ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg // -r 指定截屏頻率 // 將圖片合成視頻 ffmpeg -f image2 -i image%d.jpg output.mp4 //視頻拼接 ffmpeg -f concat -i filelist.txt -c copy output.mp4 // 將視頻轉爲gif ffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif // -pix_fmt 指定編碼 // 將視頻前30幀轉爲gif ffmpeg -i input.mp4 -vframes 30 -f gif output.gif // 旋轉視頻 ffmpeg -i input.mp4 -vf rotate=PI/2 output.mp4 // 縮放視頻 ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4 // iw 是輸入的寬度, iw/2就是一半;-1 爲保持寬高比 //視頻變速 ffmpeg -i input.mp4 -filter:v setpts=0.5*PTS output.mp4 //音頻變速 ffmpeg -i input.mp3 -filter:a atempo=2.0 output.mp3 //音視頻同時變速,可是音視頻爲互倒關係 ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mp4 // 視頻添加水印 ffmpeg -i input.mp4 -i logo.jpg -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy output.mp4 // main_w-overlay_w-10 視頻的寬度-水印的寬度-水印邊距; // 截取視頻局部 ffmpeg -i in.mp4 -filter:v "crop=out_w:out_h:x:y" out.mp4 // 截取部分視頻,從[80,60]的位置開始,截取寬200,高100的視頻 ffmpeg -i in.mp4 -filter:v "crop=80:60:200:100" -c:a copy out.mp4 // 截取右下角的四分之一 ffmpeg -i in.mp4 -filter:v "crop=in_w/2:in_h/2:in_w/2:in_h/2" -c:a copy out.mp4 // 截去底部40像素高度 ffmpeg -i in.mp4 -filter:v "crop=in_w:in_h-40" -c:a copy out.mp4
參數說明:
-vcodec xvid 使用xvid壓縮
-s 320×240 指定分辨率
-r fps 設置幀頻 缺省25
-b <比特率> 指定壓縮比特
-acodec aac 設定聲音編碼
-ac <數值> 設定聲道數,1就是單聲道,2就是立體聲
-ar <採樣率> 設定聲音採樣率,PSP只認24000
-ab <比特率> 設定聲音比特率
-vol <百分比> 設定音量
-y 覆蓋輸出文件
-t duration 設置紀錄時間 hh:mm:ss[.xxx]格式的記錄時間也支持
-ss position 搜索到指定的時間 [-]hh:mm:ss[.xxx]的格式也支持
-title string 設置標題
-author string 設置做者
-copyright string 設置版權
-hq 激活高質量設置
-aspect aspect 設置橫縱比 4:3 16:9 或 1.3333 1.7777
-croptop size 設置頂部切除帶大小 像素單位
-cropbottom size -cropleft size -cropright size
-padtop size 設置頂部補齊的大小 像素單位
-padbottom size -padleft size -padright size -padcolor color 設置補齊條顏色(hex,6個16進制的數,紅:綠:蘭排列,好比 000000表明黑色)
-bt tolerance 設置視頻碼率容忍度kbit/s
-maxrate bitrate設置最大視頻碼率容忍度
-minrate bitreate 設置最小視頻碼率容忍度
-bufsize size 設置碼率控制緩衝區大小
-vcodec codec 強制使用codec編解碼方式。 若是用copy表示原始編解碼數據必須被拷貝
-sameq 使用一樣視頻質量做爲源(VBR)
-pass n 選擇處理遍數(1或者2)。兩遍編碼很是有用。第一遍生成統計信息,第二遍生成精確的請求的碼率
-passlogfile file 選擇兩遍的紀錄文件名爲file
-map file:stream 設置輸入流映射
-debug 打印特定調試信息
Serverless架構在作一些同步的業務是有很不錯效果的,同時Serverless架構在異步的一些流程上,也是有很棒的表現,不管是經過Serverless架構作大數據的分析實現MapReduce,仍是作圖像的壓縮、水印和格式轉換,抑或本文分享的視頻相關的處理。
經過Serverless架構,咱們還能夠挖掘更多領域的應用,例如經過Serverless架構作一個Word/PPT轉PDF的工具等。Serverless架構的行業應用,領域應用,須要更多人提供更多的實踐。
咱們誠邀您來體驗最便捷的 Serverless 開發和部署方式。在試用期內,相關聯的產品及服務均提供免費資源和專業的技術支持,幫助您的業務快速、便捷地實現 Serverless!
3 秒你能作什麼?喝一口水,看一封郵件,仍是 —— 部署一個完整的 Serverless 應用?
複製連接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express
3 秒極速部署,當即體驗史上最快的 Serverless HTTP 實戰開發!
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您能夠在 最佳實踐 裏體驗更多關於 Serverless 應用的開發!