利用FFmpeg制作视频序列
前言
本文介紹了利用FFmpeg進行視頻測試序列制作的方法。所謂測試序列就是將若干個不同場景的視頻片段,按照不同的分辨率、碼率、編碼方法等進行處理,然后拼接成一條長視頻,供測試者打分。一般包括以下幾個步驟:視頻截取、采樣/編碼/轉碼、黑幀/灰幀制作、視頻拼接、視音頻融合等。
- 前言
- 一視頻截取
- 二采樣和編碼
- 三黑幀灰幀的制作
- 四視頻拼接
- 1 先音視頻片段融合再拼接
- 2 先視音頻片段分別拼接得到長視頻和長音頻再將二者融合
- 后記
一、視頻截取
截取視頻之前,一般要先獲取原始高清視頻,可以到Youtube、Gopro等網站下載,商用的話請注意版權問題,或者可以自己錄制視頻。然后瀏覽獲取到的視頻,確定要截取的片段后,可利用FFmpeg截取。比如要截取名為input.mp4的視頻1分20秒至1分40秒的片段,命令如下:
ffmpeg -i %input_path%\input.mp4 -ss 00:01:20 -t 00:00:20 %output_path%\output.mp4上述命令中,-i為輸入的文件,-ss 即為起始時間,-t為截取長度,這兩個時間可以用 hh:mm:ss 的格式,也可以直接用秒,如 00:01:20 可寫成 80。另外,時間還可以精確到毫秒級,比如可以截取20.358秒的長度,雖然實際截出來不會那么精確。
二、采樣和編碼
截取出來的視頻片段,若想重新編碼到其他分辨率、碼率的話,一般要先轉為YUV格式(此后會丟失音頻,因為yuv不存儲音頻),因為YUV格式是把每一幀的圖像用亮度和色度分開表示的格式,所以壓縮時容易去掉色度的數據;之后將原始yuv采樣到目標分辨率,接著對yuv進行x264編碼得到.264文件,最后將.264文件封裝成MP4等格式。各步驟命令大致如下:
MP4轉YUV:
對YUV采樣(假設原始分辨率為3840x1920,目標分辨率為1920x960):
ffmpeg -s 3840x1920 -i %input_path%\input_3840x1920.yuv -s 1920x960 %output_path%\output_1920x960.yuv其中-s依次為原始分辨率和目標分辨率。
對采樣后的YUV進行x264編碼(應先下載x264源碼編譯得到x264.exe):
.264文件封裝為MP4:
ffmpeg -i %input_path%\input.264 %output_path%\output.mp4至此,可將各視頻素材編碼到目標分辨率和碼率。編碼器可替換成其他,x264是我本次項目用的。
三、黑幀/灰幀的制作
制作視頻測試序列時,測試片段之間應該留有10秒左右時間間隙給測試者打分,此時一般使用黑幀或者灰幀過渡,目前行業內逐漸使用灰幀代替黑幀。黑幀的話,可以截取電影片段,或者自己錄制,方法比較多。灰幀不好找,所以一般使用代碼產生若干幀YUV,然后根據所需長度、分辨率、幀率等編碼得到灰幀視頻。無論黑幀/灰幀,無論何種方法,建議務必保證它們的質量足夠好,不然可能無法拼接,或者能拼接但在解碼播放時出問題。我一開始拿的兩個短黑幀視頻拼出一個10秒長的,拿去拼接時經常出問題,浪費了不少精力。
從YUV編碼得到一個灰幀視頻后,可以利用這個視頻來轉換得到其他分辨率的,沒必要對原YUV采樣幾次,畢竟灰幀的質量要求沒有測試片段高。ts格式視頻轉分辨率命令如下,其他格式亦可依樣畫葫蘆:
其中,-s是目標分辨率,-vcodec copy 意為使用原視頻的編碼方式,一般不更改編碼方式的話,都最好附上這個參數,能夠避免不少意外。去掉-vcodec copy 也能轉分辨率,輸出的文件也能正常播放,但拿去拼接的時候會出錯。
四、視頻拼接
用來拼接到同一序列的視頻片段們,分辨率最好是一樣的,幀率不必一樣,碼率隨意。ffmpeg拼接視頻之前,需要把視頻轉為.ts格式。拼接有兩條思路:一是先將個視頻片段與其對應的音頻融合再拼接,二是將視頻片段和音頻片段分別拼接,再將得到的長視頻序列和長音頻序列融合。
4.1 先音視頻片段融合再拼接
先從截取得到的有聲MP4視頻片段中提取音頻:
ffmpeg -i input.mp4 -vn -acodec copy output.aac其中,-vn意為屏蔽視頻信息,只獲取音頻;-acodec copy意為復制原音頻的編碼方式。(ps,若要提取視頻,命令為:ffmpeg -i input.mp4 -an -vcodec copy output.mp4 )
接著將音視頻片段融合產生可用來拼接的.ts文件:
最后,將前面得到的有聲ts視頻和灰幀ts視頻 gray.ts 拼接成一條長視頻:
ffmpeg -i "concat:%path1%\video1.ts|%gray_path%\gray.ts|%path2%\video2.ts|%gray_path%\gray.ts|... ...|%pathN%\videoN.ts|%gray_path%\gray.ts" -vcodec copy -acodec copy -bsf:a aac_adtstoasc %output_path%\output.mp4其中,-vcodec copy 意為復制原視頻編碼方式, -acodec copy 意為復制原音頻編碼方式,-bsf:a aac_adtstoasc 是一個bitstream filter,不加的話,會提示無法音視頻融合。
至此,一個有聲的視頻測試序列就完成了!
4.2 先視音頻片段分別拼接得到長視頻和長音頻,再將二者融合
視頻片段拼接:
ffmpeg -i "concat:%path1%\video1.ts|%gray_path%\gray.ts|%path2%\video2.ts|%gray_path%\gray.ts|... ...|%pathN%\videoN.ts|%gray_path%\gray.ts" -vcodec copy %output_path%\output.mp4在進行音頻片段拼接之前,需要先獲取靜音音頻,時長等于灰幀時長。一般可以用軟件產生,比如用cool edit pro,產生靜音pcm,然后把pcm轉為aac。FFmpeg也能完成音頻拼接,命令格式和視頻拼接相似,但是在我的實驗過程中,ffmpeg拼接出來的長音頻會比各音頻片段相加的總和還長,總長度為15分鐘整的音頻片段們,拼接后長度為15分8秒!和視頻融合后,音視頻嚴重不同步。所以我后來使用的是另一個軟件:音頻編輯專家。效果良好,而且能自動統一各片段的音量,很不錯的功能。
之后長視頻和長音頻融合,可以使用ffmpeg實現:
也可以使用MP4box實現,軟件 YAMB 中有交互界面可以方便高效地實現。這個軟件的其他功能也相當實用。
在上述兩種拼接方法中,第一種方法的優點是音視頻同步非常好,而且只需拼接一次,比較省事。第二種方法的好處是思路簡單,成功率高。我是在嘗試第一種方法失敗,而且折騰數日無果后,才退而求其次采用第二種方法。不過現在想來應該是我當時使用的黑幀視頻質量太差,或者是黑幀轉分辨率編碼時沒加上-vcodec copy之類的參數。我實驗室的師姐向來都用的第一種方法,一直沒什么問題。
后記
我是在研二師兄師姐們忙于找工作,無暇兼顧項目工作之時,接手了這個任務。此時的我本科剛畢業,對批處理只有朦朧印象,對視頻編碼也知之甚少,對FFmpeg則是一無所知。一周左右的時間里,我匆忙學習了批處理,照著前人的實現方法寫批處理文件調用ffmpeg去實現。遇到許多問題,有些原始MP4文件頭無法被FFmpeg識別,截取不了;有個別YUV文件無法使用ffmpeg進行下采樣;轉碼后視頻長度變化;來自于同一片段的音視頻長度不相等;拼接后音視頻不同步,等。嘗遍了各種失敗的方法,個中艱苦,非三言兩語所能道明。不過現在想來,覺得幾天前的自己太傻,這么簡單的任務應該兩天能做完。這大概也是一種進步吧,快樂。細心很重要,批處理簡單實用,FFmpeg極其強大。
總結
以上是生活随笔為你收集整理的利用FFmpeg制作视频序列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jetson TX1 学习1 GPIO
- 下一篇: 基于stm32的遥控小船(一)L298N