(六)-map参数的学习,如何用ffmpeg提取替换合并轨道流、压制字幕
往期回顾。

对于mkv格式的影视剧,我们有时想着能不能把里面的字幕提取出来,研究学习等。从本地播放、存储素材的角度来说,几乎只要是质量好的视频、音频、字幕都可以封装进mkv容器里,需要的时候又可以拿出来。这期就来说说怎么用ffmpeg实现这些。
一、字幕、轨道流的概念
字幕以及轨道流的概念是背景知识,不局限于ffmpeg。
先讲一下“压制字幕”的概念。平常我们下资源或者找字幕的时候,看到诸如“外挂中字”“内挂”“内封”“内嵌中英”等字眼,还有一些像“硬嵌”“硬压”“软压”“硬字幕”“软字幕”的说法,这都和压制字幕有关。压制字幕,简单理解就是用什么方法把字幕放进视频里,便于播放的时候一起看。
结合之前提到的字词,通常我们压制字幕指的是以下三种方式:字幕外挂、字幕内挂、字幕内嵌。
字幕外挂,指的是字幕作为一个独立的文件随着视频文件一起配套传输。这样我们在视频中看到的字幕,就是播放器在同时播放这个字幕文件的结果。如果没有字幕文件,或者弄不见了,那视频就没字幕了。就像请了个翻译官,如果翻译官不在身边,我们就不知道正在聊天的内容是什么。一般只要字幕文件和视频的命名相同,下载之后放一个文件夹里,播放时就会自动加载字幕。这种方式最简单直白,方便我们研究学习字幕或者不要字幕,“啃生肉”。
字幕内挂,或称字幕内封,是字幕文件“打包”进视频容器格式里,传输时只要一个视频文件。这时所看到的字幕,也是播放器在同时播放字幕文件,不过它被视频容器格式“装”着,而不是独立在外。通常用mkv容器格式进行字幕内挂,mp4格式也可以。这种方式就不会担心弄不见字幕文件、字幕文件太多好乱的情况了。就像哪个书包装哪本字典,我们不动它它不会自己跑掉,就一直待着,打开书包就有。所以我们想要字幕文件的话也可以从中提取。本地存储观看来说up最推荐这种方式,不想看字幕还可以让播放器关闭字幕,像弹幕的道理。
字幕内嵌,就像镶嵌一样把字幕文件“印”在视频上,有了字幕的视频不包含也不再需要字幕文件。这种情况下看到的字幕就彻彻底底是视频画面的一部分了。这个有字幕的视频,没有字幕文件可以提取,我们也不能选择不看字幕。如果制作视频或者单纯“烤肉”是为了上传b站或其它视频平台来在线收看的话,都是采用字幕内嵌。因为这种方式兼容广泛性强,特别利于传输,很多时候我们就是要字幕翻译或者辅助观看,又不考虑字幕文件。
三种方式各有优缺点。现在好理解了,“硬嵌”“硬压”“硬字幕”是做了字幕内嵌,以字幕角度说就称为内嵌字幕;“内封”“软压”“软封”“软字幕”是内挂字幕;“外挂”就是外挂字幕了。
字幕文件格式有srt、ass、ssa、lrc、idx、sub、pgs等。这里分为两类,一是文本类字幕,如srt、ass、ssa、lrc;二是位图或者叫图形类字幕,如idx、sub、pgs。通常我们见的用的文本类字幕比较多,尤其是srt和ass。图形类字幕一般见于DVD碟片。
接着说说什么叫做“轨道流”。几期以来我们一直说视频有画面、有声音,现在还提到字幕。这里视频的画面就属于“视频流”;视频的声音、或者我们听的音乐声音本身就属于“音频流”;像下载到的字幕文件,一些mkv视频里的内挂字幕属于“字幕流”。
注意,内嵌字幕属于视频流,不是字幕流。
“轨道流”理解的要点在于,“轨道流”不是特指视频容器格式所“装”着的某一个视频、音频、字幕文件。因为现在像一个mp4视频,一般就一个视频画面,一个音频声音,新人就可能会容易形成一种观念,比如提到字幕流就默认是哪个字幕文件。实际上一个视频容器格式可以装载多个视频、音频、字幕文件,例如以前的一些DVD影碟。当然现在我们自己也可以这样封装。
以前DVD时代人们说放哪个视频轨、音频轨,有些就是指播放封装的哪个视频、音频文件。像这样对于所封装的某个文件,我们称之为轨道,例如第几个视频轨、音频轨、字幕轨。视频流指的是所有的视频轨,音频、字幕以此类推。(“-map”的学习需要这个的理解)
二、常用提取轨道流的参数
现在就好办了,要学的就是相应的参数及命令行。
“-vn”,“disable video,不使用视频流、禁用视频流输出”。
“-an”,“disable audio,不使用音频流、禁用音频流输出”。
“-sn”,“disable subtitle,不使用字幕流、禁用字幕流输出”。
注意是“流”。意思是例如一旦用了“-vn”,那么所有视频轨道、数据都不考虑了,输出的肯定没有任何视频画面,也没有任何关于视频流的数据。音频、字幕同样道理。
因此,我们可以利用这点来提取静音的视频,纯音频以及字幕(各自只有一轨的情况下)。命令行如下:
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
其它视频、音频、字幕容器格式同理。
这里有几点注意事项。
①mp4容器格式一般封装的音频是aac编码格式,且mp3容器格式也不支持aac编码格式。
②对无任何处理保持原状输出的流,记得打上相应的“copy”。
③事先看看字幕是什么容器格式,再决定是否用“-c:s copy”还是转码。
那合并轨道流也好说:
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
第二条相当于是字幕内挂的操作了。
强调注意,“-c copy”只是对音视频流的复制照抄处理,而且可以只对单独的视频或音频流使用,但不包括字幕流。字幕流记得加上“-c:s copy”。
三、选定轨道流的参数:-map
像影视番剧资源,有些有好几轨的怎么办呢?我们万能的“-map”参数要大展身手了。说它万能是因为,提取、合并、替换轨道流靠它特别方便省工夫。
“-map”,set input stream mapping,设置所输入的流需要指向哪个新的相应的流。通俗理解就像购物清单,我现在需要哪些东西,然后要买它们再来做什么。
“-map 0”表示选择第一个输入文件的包括视频、音频、字幕的所有流。“-map i”表示选择第i+1个输入文件的所有流。
"-map 0:0"表示选择第一个输入文件的第一个轨道流。注意并不确定是音频还是视频,只是说“第一个轨道流” 。可用 ffmpeg -i .\in.mkv 或 ffprobe .\in.mkv查看文件具体信息。
“-map i:v表示从第i+1个文件中选择所有视频流,以此为例,“-map i:a”就是选择所有音频流,“-map i:s”选择所有字幕流。
至于哪一个轨道,“-map 0:v:0”表示选择第1个输入文件的第1个视频轨。音频、字幕以此类推。
比如,对于“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个字幕轨。
好了,如此,提取相关的命令行就简洁明了:
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”选定之外的流不会被“-c”参数的copy所复制到。很好理解,“-map”要做的就是从输入文件里选定一些流,至于其它流就像之前那样禁用输出。那现在ffmpeg运行的就只有这些选定的流了,copy自然是复制这些呐。
当输入文件数或者单个文件的某个“轨道流”数较多的时候(比如大于2),若想要直接复制照抄轨道流,记得先加上“-map”参数将其选上。
四、如何内嵌字幕
外挂字幕就不多说了,文件相同名字放一起就行。
内挂字幕这里再来一次:
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
内嵌字幕的话涉及到“滤镜”这个我们还没学过的东西,先用着,以后up会讲的啦。命令行如下:
ffmpeg -i .\in.mp4 -b:v 2000k -vf subtitles=.\input.ass .\out.mp4
input.ass就是我们想要内嵌进视频的字幕文件。
最后强调一下这个内嵌字幕的命令行通常的两种做法。一是像第一篇那样先让cmd转到视频和字幕文件所在的目录下运行,这样对于input.ass,只需要打上字幕文件的文件名就可以,不需要加上目录路径。二是照常输入,但特别注意需要像这样书写:
ffmpeg -i .\in.mp4 -vf subtitles="'d\:\\俺是文件夹名\\input.ass'"
即在原来的路径上再加上“\”进行转义,除了一对双引号还有一对单引号,才能正常使用!

感谢你观看到这里。