引言
之前我們已經分享過很多關於音視頻處理的文章。其中最繞不開的就是ffmpg工具,這個命令行工具構建了當今大小智能設備音頻,視頻,圖片等多媒體文件處理的方方面面。
可是有很多讀者反映ffmpg入門門檻太高。面對英文的文檔幾乎無從下手,其涵蓋眾多流處理的指令根本就記不住。
那麼我們本著先難後易的精神,今天就從一行較為複雜的指令開始說起。文中將會給您分析每一個指令所代表的意義。把這行指令吃透了,摸清了,你可能真的就晉級了。
一行指令
雖然說是一行,但是根本寫不下或者一行看上去。比較凌亂。在命令行中我們可以使用空格加上右斜槓的方式,把一行指令拆分為多行,這樣比較直觀,也容易修改和定位。
大家看到了吧,這一行指令足足可以拆分為42個單元進行講解。
處理輸入
首先是指定待處理的文件:
ffmpeg -f rawvideo -pix_fmt yuv422p -s 720x486 -r 29.97 -i /tmp/vpipe
-i 選項之前的所有內容,都描述了輸入文件 /tmp/vpipe 中包含的內容。
在這種情況下,我們的輸入視頻是 yuv422p 格式的原始(未壓縮)幀數據,寬720像素,高486像素,幀速率為每秒29.97幀。
請注意,這些選項必須在 -i 選項之前。 如果這些選項中的任何一個在 -i 之後,則ffmpeg會認為它們屬於指定的下一個輸入文件。
-ar 48000 -f s16le -ac 2 -i /tmp/apipe
這一行,我們告訴 ffmpeg 輸入文件 /tmp/apipe 中的音頻是什麼樣的。 採樣率為每秒48000個樣本; 每個樣本都是帶符號的16位低端字節序,並且有2個音頻通道。
處理輸出
下一組選項描述了音頻和視頻的輸出格式。 這些選項中的順序並不重要,但希望對其進行邏輯分組,以便所有音頻選項寫在一起,而所有視頻選項寫在一起。
-vol 4096 -acodec libfaac -ac 2 -ab 192k -ar 44100 -async 1
-vol 選項表示將調整音頻電平。基準值為256。這裡可以使用使用512、1024、2048和4096等值來提高音量。
這幾個參數的設置,很大程度上取決於原始素材的質量,還有開發者的經驗。
上面我們指定使用 libfaac 編碼器輸出 AAC 音頻。後面的參數:
-ac 2通道-ab 比特率 192kps-ar 採樣頻率 44100 Hz最後一個選項 -async,指定使用音視頻同步方式1。該方法可以調整視頻和音頻軌道的開始,但是在軌道的整個過程中都不會做任何拉伸。
-vcodec libx264 -vpre default -threads 0 -croptop 6 -cropbottom 6 -cropleft 9 -cropright 9 -r 20 -g 45 -s 432x324 -b 1024k -bt 100k -deinterlace
上面這一段是視頻處理相關的,放在了一起。
使用 libx264 庫提供的H.264壓縮。 -vpre 選項意味著將使用默認的質量預設。需要注意的是,使用 libx264 進行編碼時,可以指定兩個-vpre選項。第一個是quality,第二個是要使用的配置文件(main,baseline等),默認設置為「 main」。
-threads 0 選項指示 ffmpeg 在編碼時使用最佳線程數。
-crop 開始的 top bottom left right 指令,指定在視頻畫面的邊框周圍,視頻裁去一部分,因為在源視頻的邊緣會出現一些噪點。
-r 選項指定輸出為每秒20幀。
-g 選項是「圖片組」(GOP)的大小,它是關鍵幀之間的幀數。 數量越少,輸出將具有更多的關鍵幀,這意味著如果客戶端出於某種原因丟棄數據包,它們將能夠更快地恢復。 這也會對文件大小產生不利影響。
-s 選項指定幀大小。
-b 選項指定所需的比特率。
-bt 選項為比特率容限。 ffmpeg會嘗試將視頻保持在所需的比特率附近,並且在容差值範圍內。
-deinterlace 由於源是NTSC隔行掃描視頻,因此我們將對視頻進行去隔行掃描。 如果不進行逐行掃描,則可以在數位化視頻中,看到「豎狀條紋」,十分影響觀感。
-y '/tmp/encoding-0001.mp4'
這一行指定了輸出文件名,-y 選項告訴 ffmpeg 如果目標文件存在,直接覆蓋。
追加輸出
現在,我們添加一些 RTP 格式的輸出流。 通過網絡將此 RTP 流推送到 Wowza 伺服器,該伺服器可以將 RTP 轉換為 RTMP 以便在客戶端中播放。
跟寫入 MPEG4 文件不同,RTP 要求將音頻和視頻分成兩個單獨的流。
-an-vcodec libx264 -vpre default -threads 0-croptop 6 -cropbottom 6 -cropleft 9 -cropright 9-r 20 -g 45 -s 432x324 -b 1024k -bt 100k-deinterlace-vglobal 1-f rtp rtp://127.0.0.1:9012
這一大堆選項,看起來是不是頭大?沒關係,原理都是一致的。我們逐行分析。
上面說了,我們把音頻和視頻分開寫,這樣便於講解。這一段,都是關於音頻的選項。大家看是不是與上一節講的十分相似。相同的部分就不過多贅述了,說說特殊的選項。
-an 選項告訴 ffmpeg 從輸出中刪除音頻流。
-vglobal 1選項表示 ffmpeg 在視頻流中使用 out-of-band 全局標頭。 這可以幫助一些播放器規範解釋視頻流。
-f 選項將輸出格式指定為「 rtp」,而非文件名。使用 URL 指示 ffmpeg 將 RTP 數據包推送地址。
接下來說音頻輸出。
-vn-vol 4096-acodec libfaac -ac 2 -ab 192k -ar 44100 -async 1 -flags +global_header -f rtp rtp://127.0.0.1:9014-newaudio
這一段選項,是不是上面都見過?
-vn 選項指示此輸出不包含視頻。
-flags + global_header 用於強制 ffmpeg 在其生成的 SDP 中分離出一些重要的音頻規範。在Wowza伺服器上使用 SDP 文件將 RTMP 流連接到 RTP 流; Wowza 需要了解所有音頻和視頻的信息,以便正確解析。
-f 選項指定 rtp 格式,並提供流推送的地址 URL。需要注意,埠號不同。 RTP 流通常使用兩個埠,並且兩個埠之間有一個開放埠。每個 RTP 埠之後的埠將用於 RTCP 接收方和發送方的通信。在示例中,我們使用 9013 和 9015。
-newaudio 恢復先前被 -an 選項過濾掉的音頻流。注意 -newaudio 是一個特殊選項;它僅修改緊接其之前的輸出。所以選項順序在這裡很關鍵。
追加 RTP 流
我們的第一個 RTP 流使用 1200 Kbps 的音頻和視頻組合。 讓我們再創建一個可供帶寬不足的用戶使用的流。
再添加一對輸出,一個是音頻,一個是視頻。
-an -vcodec libx264 -vpre default -threads 0-croptop 6 -cropbottom 6 -cropleft 9 -cropright 9-r 15 -g 45 -s 432x324 -b 256k -bt 50k-deinterlace-vglobal 1-f rtp rtp://127.0.0.1:9008-newvideo-vn-vol 4096-acodec libfaac -ac 1 -ab 64k -ar 44100-async 1-flags +global_header-f rtp rtp://127.0.0.1:9010-newaudio
第二組 RTP 輸出與第一組 RTP 輸出之間存在一些差異:
視頻幀率是15(-r 15)視頻比特率是256kbps,容差是50kbps(-b 256k -bt 50k)音頻為單聲道(-ac 1)音頻為64kbps(-ab 64k)RTP URL中的埠不同還應該注意,視頻 RTP 網址後面有一個 -newvideo 選項。 那是因為 -vn 選項標識之前的輸出僅是音頻。 使用 -newvideo 選項可將視頻流恢復到此輸出。 沒有這個選項,就沒有音頻(-an)和視頻(vn)。
寫在最後
經過一個個的分析,大家明白文章開頭那一行指令的功能了吧:就是把輸入文件拆解為一個 mp4 文件的輸出,和兩路 rtp 流輸出。
這麼複雜的功能,ffmpeg 準備了如此簡潔的實現方式,不可謂不強大!
Happy coding :_)
我是@程式設計師小助手,持續分享編程知識,歡迎關注。