流的操作(二)如何選擇流?


轉發自白狼棧:查看原文

流的操作(一)視頻轉音頻引發的血案一文中我們了解到,流的選擇,實際有兩種方式,一種是ffmpeg自動選擇,一種是設置參數手動選擇。

對於自動選擇,ffmpeg默認選擇規則如下:

  1. 視頻流:默認選擇分辨率最高的流
  2. 音頻流:默認選擇通道最多的流
  3. 字幕流:默認選擇第一個字幕編碼器支持的字幕流

對於視頻流和音頻流,如果分辨率相等或者通道相等則以第一個為准,數據流和附件流不支持自動選擇,需要手動選擇。

自動選擇的情況下,ffmpeg每種類型只會選擇一路,舉個例子

ffmpeg -i r3.mp4 -hide_banner 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'r3.mp4': 
... 
Duration: 00:00:58.54, start: 0.000000, bitrate: 1998 kb/s 
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 544x960, 1732 kb/s, 29.83 fps, 29.83 tbr, 11456 tbn, 59.67 tbc (default) 
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 129 kb/s (default) 
Stream #0:2(und): Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)

 

注:Stream #0:0,第一個0表示第一個輸入文件,第二個0表示第一個輸入文件的第一路流

如果我們直接對 r3.mp4 轉碼操作,你會發現輸出的視頻只保留了一路視頻和一路音頻。

1、ffmpeg -i r3.mp4 tmp-r3.mp4 
2、ffmpeg -i tmp-r3.mp4 
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 544x960, 1684 kb/s, 29.83 fps, 29.83 tbr, 11456 tbn, 59.67 tbc (default) 
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 129 kb/s (default)

 

這就是ffmpeg自動選擇的結果。

如果想要輸入視頻的Stream #0:2這路音頻流,就只能手動指定了。

流的手動模式,使用 -map 參數操作,-map 非常重要,后面我們還會反復使用它。它表示我們需要從輸入文件中選擇哪些流到輸出文件。

語法規則:

-map [-]input_file_index[:stream_type_specifier][:stream_index]

 

  1. 中括號[]表示可選,input_file_index 之前的 - 表示反選,即可以剔除某一路流。
  2. input_file_index 指的是某個輸入文件,我們可以用下標0表示第一個輸入文件,1表示第二個輸入文件,以此類推;
  3. stream_type_specifier (可選)指的是指定輸入文件的某路流的類型,我們用 a、v、s、d、t分別表示音頻流、視頻流、字幕流、數據流和附件流;
  4. stream_index(可選)指的是具體的某個類型的某路流。

我們仍然以案例一的素材視頻為例(沒有下載的可以點擊這里下載

如果我們以r1ori.mp4為輸入,想得到r3.mp4的結果,即多了一路音頻流且是mp3格式的,怎么做?

ffmpeg -i r1ori.mp4 -map 0:v -map 0:a:0 -map 0:a:0 -c:v copy -c:a:0 copy -c:a:1 libmp3lame -y r3.mp4
注意輸出代碼段Stream mapping這一段
Stream mapping: 
Stream #0:0 -> #0:0 (copy) 
Stream #0:1 -> #0:1 (copy) 
Stream #0:1 -> #0:2 (aac (native) -> mp3 (libmp3lame))

 

簡單分析下

  1. 因為只有一個輸入文件,所以-map的第一個參數都是0
  2. -map 0:v 表示選擇輸入文件的所有視頻流(這里視頻流只有一個)到輸出,-c:v copy表示復制所有的視頻流,即你看到的 Stream #0:0 -> #0:0 (copy)
  3. -map 0:a:0 我們寫了兩遍,第一個表示選擇輸入文件的第一個音頻流到輸出,第二個仍然表示選擇輸入文件的第一個音頻流到輸出,相當於輸出了兩路音頻流
  4. -map 0:v -map 0:a:0 -map 0:a:0 連起來也有關系,表示要按照我們選擇的這三路順序輸出
  5. -c:a:0 copy 針對第一個音頻流進行復制,不重新編碼,即 Stream #0:1 -> #0:1 (copy); -c:a:1 libmp3lame 針對第二個音頻流使用libmp3lame編碼器重新編碼,即輸出過程中的 Stream #0:1 -> #0:2 (aac (native) -> mp3 (libmp3lame))

后面我們還會大量使用-map命令,所以上面這段分析,務必要理解清楚。

上面的命令同樣等價於

ffmpeg -i r1ori.mp4 -map 0:0 -map 0:1 -map 0:1 -c:v copy -c:a:0 copy -c:a:1 libmp3lame -y r3.mp4

 

-map 0:v 這里等價於 -map 0:0,-map 0:a:0 等價於-map 0:1,這是因為在r1ori.mp4中#0:0就是視頻流,#0:1就是音頻流

ffmpeg -i r1ori.mp4 
... 
Stream #0:0(und): Video: h264 
Stream #0:1(und): Audio 
...

 

注意:-map的參數,針對的是輸入流,因為是我們想要從輸入流中選擇流到輸出;-c選項的參數,針對的並不再是輸入流了,-c的參數針對的是-map選擇的流,即輸出流。

除此之外,下面我們再看幾個簡單的例子,你可以在看結果之前嘗試下

1、復制輸入文件的所有流到輸出,輸出結果可就不止只有兩路流了

ffmpeg -i r3.mp4 -map 0 -c copy output.mp4

 

2、把輸入文件的三路流分別拆開,輸出三個文件

ffmpeg -y -i r3.mp4 -map 0:v -c:v copy output-silent.mp4 \
-map 0:a:0 -c:a copy output-audio.aac \
-map 0:a:1 -c:a copy output-audio.mp3

 

我們還可以設置一些選項,比如可以設置r3.mp4的兩路音頻流有不同的碼率。

ffmpeg -i r3.mp4 -b:a:0 32k -b:a:1 64k -map 0 -y r4.mp4

 

-map 0 是必須的,不然輸出結果並不會輸出兩路音頻流。

對於音視頻流還有很多選項設置,具體你可以查閱官方文檔了解,你也可以在我們平時練習中多查閱資料,奠定基礎。

最后,我們還有一種最最常見的操作——結合濾鏡使用。

比如把原視頻 r3.mp4 等比例縮放一倍

ffmpeg -i r3.mp4 -vf scale=272:480 -y filter.mp4

 

我們也可以手動選擇流處理

ffmpeg -i r3.mp4 -filter_complex "[0]scale=272:480[out]" -map 0:a -map "[out]" -y filter.mp4

 

上面這兩條命令你可能很難理解,關於濾鏡,大家先有個印象,下面文章我們再作詳細介紹。

流的操作我們就介紹到這里,大家在練習中碰到各種莫名其妙的問題,盡管留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM