(六)-map參數(shù)的學(xué)習(xí),如何用ffmpeg提取替換合并軌道流、壓制字幕
往期回顧。

對(duì)于mkv格式的影視劇,我們有時(shí)想著能不能把里面的字幕提取出來,研究學(xué)習(xí)等。從本地播放、存儲(chǔ)素材的角度來說,幾乎只要是質(zhì)量好的視頻、音頻、字幕都可以封裝進(jìn)mkv容器里,需要的時(shí)候又可以拿出來。這期就來說說怎么用ffmpeg實(shí)現(xiàn)這些。
一、字幕、軌道流的概念
字幕以及軌道流的概念是背景知識(shí),不局限于ffmpeg。
先講一下“壓制字幕”的概念。平常我們下資源或者找字幕的時(shí)候,看到諸如“外掛中字”“內(nèi)掛”“內(nèi)封”“內(nèi)嵌中英”等字眼,還有一些像“硬嵌”“硬壓”“軟壓”“硬字幕”“軟字幕”的說法,這都和壓制字幕有關(guān)。壓制字幕,簡(jiǎn)單理解就是用什么方法把字幕放進(jìn)視頻里,便于播放的時(shí)候一起看。
結(jié)合之前提到的字詞,通常我們壓制字幕指的是以下三種方式:字幕外掛、字幕內(nèi)掛、字幕內(nèi)嵌。
字幕外掛,指的是字幕作為一個(gè)獨(dú)立的文件隨著視頻文件一起配套傳輸。這樣我們?cè)谝曨l中看到的字幕,就是播放器在同時(shí)播放這個(gè)字幕文件的結(jié)果。如果沒有字幕文件,或者弄不見了,那視頻就沒字幕了。就像請(qǐng)了個(gè)翻譯官,如果翻譯官不在身邊,我們就不知道正在聊天的內(nèi)容是什么。一般只要字幕文件和視頻的命名相同,下載之后放一個(gè)文件夾里,播放時(shí)就會(huì)自動(dòng)加載字幕。這種方式最簡(jiǎn)單直白,方便我們研究學(xué)習(xí)字幕或者不要字幕,“啃生肉”。
字幕內(nèi)掛,或稱字幕內(nèi)封,是字幕文件“打包”進(jìn)視頻容器格式里,傳輸時(shí)只要一個(gè)視頻文件。這時(shí)所看到的字幕,也是播放器在同時(shí)播放字幕文件,不過它被視頻容器格式“裝”著,而不是獨(dú)立在外。通常用mkv容器格式進(jìn)行字幕內(nèi)掛,mp4格式也可以。這種方式就不會(huì)擔(dān)心弄不見字幕文件、字幕文件太多好亂的情況了。就像哪個(gè)書包裝哪本字典,我們不動(dòng)它它不會(huì)自己跑掉,就一直待著,打開書包就有。所以我們想要字幕文件的話也可以從中提取。本地存儲(chǔ)觀看來說up最推薦這種方式,不想看字幕還可以讓播放器關(guān)閉字幕,像彈幕的道理。
字幕內(nèi)嵌,就像鑲嵌一樣把字幕文件“印”在視頻上,有了字幕的視頻不包含也不再需要字幕文件。這種情況下看到的字幕就徹徹底底是視頻畫面的一部分了。這個(gè)有字幕的視頻,沒有字幕文件可以提取,我們也不能選擇不看字幕。如果制作視頻或者單純“烤肉”是為了上傳b站或其它視頻平臺(tái)來在線收看的話,都是采用字幕內(nèi)嵌。因?yàn)檫@種方式兼容廣泛性強(qiáng),特別利于傳輸,很多時(shí)候我們就是要字幕翻譯或者輔助觀看,又不考慮字幕文件。
三種方式各有優(yōu)缺點(diǎn)。現(xiàn)在好理解了,“硬嵌”“硬壓”“硬字幕”是做了字幕內(nèi)嵌,以字幕角度說就稱為內(nèi)嵌字幕;“內(nèi)封”“軟壓”“軟封”“軟字幕”是內(nèi)掛字幕;“外掛”就是外掛字幕了。
字幕文件格式有srt、ass、ssa、lrc、idx、sub、pgs等。這里分為兩類,一是文本類字幕,如srt、ass、ssa、lrc;二是位圖或者叫圖形類字幕,如idx、sub、pgs。通常我們見的用的文本類字幕比較多,尤其是srt和ass。圖形類字幕一般見于DVD碟片。
接著說說什么叫做“軌道流”。幾期以來我們一直說視頻有畫面、有聲音,現(xiàn)在還提到字幕。這里視頻的畫面就屬于“視頻流”;視頻的聲音、或者我們聽的音樂聲音本身就屬于“音頻流”;像下載到的字幕文件,一些mkv視頻里的內(nèi)掛字幕屬于“字幕流”。
注意,內(nèi)嵌字幕屬于視頻流,不是字幕流。
“軌道流”理解的要點(diǎn)在于,“軌道流”不是特指視頻容器格式所“裝”著的某一個(gè)視頻、音頻、字幕文件。因?yàn)楝F(xiàn)在像一個(gè)mp4視頻,一般就一個(gè)視頻畫面,一個(gè)音頻聲音,新人就可能會(huì)容易形成一種觀念,比如提到字幕流就默認(rèn)是哪個(gè)字幕文件。實(shí)際上一個(gè)視頻容器格式可以裝載多個(gè)視頻、音頻、字幕文件,例如以前的一些DVD影碟。當(dāng)然現(xiàn)在我們自己也可以這樣封裝。
以前DVD時(shí)代人們說放哪個(gè)視頻軌、音頻軌,有些就是指播放封裝的哪個(gè)視頻、音頻文件。像這樣對(duì)于所封裝的某個(gè)文件,我們稱之為軌道,例如第幾個(gè)視頻軌、音頻軌、字幕軌。視頻流指的是所有的視頻軌,音頻、字幕以此類推。(“-map”的學(xué)習(xí)需要這個(gè)的理解)
二、常用提取軌道流的參數(shù)
現(xiàn)在就好辦了,要學(xué)的就是相應(yīng)的參數(shù)及命令行。
“-vn”,“disable video,不使用視頻流、禁用視頻流輸出”。
“-an”,“disable audio,不使用音頻流、禁用音頻流輸出”。
“-sn”,“disable subtitle,不使用字幕流、禁用字幕流輸出”。
注意是“流”。意思是例如一旦用了“-vn”,那么所有視頻軌道、數(shù)據(jù)都不考慮了,輸出的肯定沒有任何視頻畫面,也沒有任何關(guān)于視頻流的數(shù)據(jù)。音頻、字幕同樣道理。
因此,我們可以利用這點(diǎn)來提取靜音的視頻,純音頻以及字幕(各自只有一軌的情況下)。命令行如下:
ffmpeg -i .\input.mp4 -vn -f mp3?.\OnlyAudio.mp3
ffmpeg -i .\input.mp4 -an -c:v copy .\NoAudio.mp4
ffmpeg -i .\input.mkv -c copy -sn .\NoSubtitle.mp4
ffmpeg -i .\input.mkv -vn -an -c:s copy .\output.srt
其它視頻、音頻、字幕容器格式同理。
這里有幾點(diǎn)注意事項(xiàng)。
①mp4容器格式一般封裝的音頻是aac編碼格式,且mp3容器格式也不支持aac編碼格式。
②對(duì)無任何處理保持原狀輸出的流,記得打上相應(yīng)的“copy”。
③事先看看字幕是什么容器格式,再?zèng)Q定是否用“-c:s copy”還是轉(zhuǎn)碼。
那合并軌道流也好說:
ffmpeg -i .\noaudio.mp4 -i .\input.aac -c copy .\output.mp4
ffmpeg -i .\input.mp4 -i .\input.ass -c copy -c:s copy .\output.mkv
第二條相當(dāng)于是字幕內(nèi)掛的操作了。
強(qiáng)調(diào)注意,“-c copy”只是對(duì)音視頻流的復(fù)制照抄處理,而且可以只對(duì)單獨(dú)的視頻或音頻流使用,但不包括字幕流。字幕流記得加上“-c:s copy”。
三、選定軌道流的參數(shù):-map
像影視番劇資源,有些有好幾軌的怎么辦呢?我們?nèi)f能的“-map”參數(shù)要大展身手了。說它萬能是因?yàn)?,提取、合并、替換軌道流靠它特別方便省工夫。
“-map”,set input stream mapping,設(shè)置所輸入的流需要指向哪個(gè)新的相應(yīng)的流。通俗理解就像購(gòu)物清單,我現(xiàn)在需要哪些東西,然后要買它們?cè)賮碜鍪裁础?/p>
“-map 0”表示選擇第一個(gè)輸入文件的包括視頻、音頻、字幕的所有流?!?map i”表示選擇第i+1個(gè)輸入文件的所有流。
"-map 0:0"表示選擇第一個(gè)輸入文件的第一個(gè)軌道流。注意并不確定是音頻還是視頻,只是說“第一個(gè)軌道流” ??捎?ffmpeg -i .\in.mkv 或 ffprobe .\in.mkv查看文件具體信息。
“-map i:v表示從第i+1個(gè)文件中選擇所有視頻流,以此為例,“-map i:a”就是選擇所有音頻流,“-map i:s”選擇所有字幕流。
至于哪一個(gè)軌道,“-map 0:v:0”表示選擇第1個(gè)輸入文件的第1個(gè)視頻軌。音頻、字幕以此類推。
比如,對(duì)于“ffmpeg -i .\in1.mp4 -i .\in2.flv -i .\in3.mkv?-map 0 -map 1:a -map 2:s:1”,“-map 0”就是選擇in1.mp4的所有流,“-map 1:a”選擇in2.flv的所有音頻流,“-map 2:s:1”選擇in3.mkv的第2個(gè)字幕軌。
好了,如此,提取相關(guān)的命令行就簡(jiǎn)潔明了:
ffmpeg -i .\input.mkv -map 0:s:0?-c:s copy .\output.ass
不同文件之間替換、合并軌道流,像這樣:
ffmpeg -i .\in1.mp4 -i .\in2.mp3 -map 0:v?-map 1:a -c:v copy -f mp4 .\out.mp4
ffmpeg -i .\in1.mkv?-i .\in2.mkv?-map 0:s:0?-map 1?-c?copy -c:s copy .\out.mkv
ffmpeg -i .\in1.mp4 -i .\in2.flv?-map?1:v?-map 0:a -c?copy .\out.mp4
注意,在“-map”選定之外的流不會(huì)被“-c”參數(shù)的copy所復(fù)制到。很好理解,“-map”要做的就是從輸入文件里選定一些流,至于其它流就像之前那樣禁用輸出。那現(xiàn)在ffmpeg運(yùn)行的就只有這些選定的流了,copy自然是復(fù)制這些吶。
當(dāng)輸入文件數(shù)或者單個(gè)文件的某個(gè)“軌道流”數(shù)較多的時(shí)候(比如大于2),若想要直接復(fù)制照抄軌道流,記得先加上“-map”參數(shù)將其選上。
四、如何內(nèi)嵌字幕
外掛字幕就不多說了,文件相同名字放一起就行。
內(nèi)掛字幕這里再來一次:
ffmpeg -i .\input.mp4 -i .\input.ass -c copy -c:s copy .\output.mkv
另外還有這樣一種做法:
ffmpeg -i .\input.mp4 -i .\input.srt?-c copy -c:s mov_text .\output.mp4
內(nèi)嵌字幕的話涉及到“濾鏡”這個(gè)我們還沒學(xué)過的東西,先用著,以后up會(huì)講的啦。命令行如下:
ffmpeg -i .\in.mp4?-b:v 2000k -vf subtitles=.\input.ass .\out.mp4
input.ass就是我們想要內(nèi)嵌進(jìn)視頻的字幕文件。
最后強(qiáng)調(diào)一下這個(gè)內(nèi)嵌字幕的命令行通常的兩種做法。一是像第一篇那樣先讓cmd轉(zhuǎn)到視頻和字幕文件所在的目錄下運(yùn)行,這樣對(duì)于input.ass,只需要打上字幕文件的文件名就可以,不需要加上目錄路徑。二是照常輸入,但特別注意需要像這樣書寫:
ffmpeg -i .\in.mp4?-vf subtitles="'d\:\\俺是文件夾名\\input.ass'"
即在原來的路徑上再加上“\”進(jìn)行轉(zhuǎn)義,除了一對(duì)雙引號(hào)還有一對(duì)單引號(hào),才能正常使用!

感謝你觀看到這里。