打开主菜单

编辑“如何使用 FFmpeg 进行视频转码:不仅能转码”

警告:您没有登录。如果您做出任意编辑,您的IP地址将会公开可见。如果您登录创建一个账户,您的编辑将归属于您的用户名,且将享受其他好处。

该编辑可以被撤销。请检查下面的对比以核实您想要撤销的内容,然后保存下面的更改以完成撤销。

最后版本 您的文字
第30行: 第30行:
 
...
 
...
 
</syntaxhighlight>
 
</syntaxhighlight>
 
== 批量处理 ==
 
 
命令行工具的一大好处就是它可以很方便地被写进脚本中,以此进行批量处理,在 GNU/Linux 和 Mac OS X 上,你可以创建一个文本文件,随便取个名字,在里面逐行写上想要执行的命令,比如:
 
 
<syntaxhighlight lang="shell">
 
ffmpeg -i a.mp4 a.mkv
 
ffmpeg -i b.mp4 b.mkv
 
</syntaxhighlight>
 
 
之后用 <code>sh 脚本文件名</code> 执行这个脚本,它就会依次执行 <code>ffmpeg -i a.mp4 a.mkv</code> 和 <code>ffmpeg -i b.mp4 b.mkv</code> 两条命令了。
 
 
在 Microsoft Windows 中也是如此,不过文件名必须得以 <code>.bat</code> 结尾,并且以双击的方式来执行脚本。
 
 
你也可以在脚本中使用 “for 循环” 来对许多文件名有规律的媒体文件进行转码,比如像这样(仅限 GNU/Linux 和 Max OS X ):
 
 
<syntaxhighlight lang="shell">
 
for i in "听爸爸的话 第{01..04}话"; do
 
    ffmpeg -i "${i}.mkv" -c copy "${i}.mp4"
 
done
 
</syntaxhighlight>
 
 
就会把 “听爸爸的话” 第 01 到 04 话从 MKV 转到 MP4 封装格式。不过因为这东西不属于 FFmpeg 的范畴,所以我在这里不打算详细说明,按照上面的例子生搬硬套也应该能满足大部分需求。
 
 
== 自己动手分配媒体流 ==
 
 
有时候我们要面对复杂的媒体流分配,比如我有两个视频文件, <code>a.mp4</code> 和 <code>b.mp4</code> ,我想将 <code>a.mp4</code> 的视频流和 <code>b.mp4</code> 的音频流提取出来,做成一个新的新视频文件,要怎么做呢?
 
 
我可以先用 <code>ffmpeg -i a.mp4 -c:v copy -an a_video.mp4</code> 将 <code>a.mp4</code> 的视频流单独提取到一个文件上,叫 <code>a_video.mp4</code> 。<br />
 
然后用 <code>ffmpeg -i b.mp4 -c:a copy -vn b_audio.aac</code> 将 <code>b.mp4</code> 的音频流单独提取到 <code>b_audio.aac</code> 上。<br />
 
最后用 <code>ffmpeg -i a_video.mp4 -i b_audio.aac -c copy final.mp4</code> 将 <code>a_video.mp4</code> 和 <code>b_audio.aac</code> 放到一起得到最后的成果 <code>final.mp4</code> 。
 
 
可是这样需要 3 个步骤,还会产生临时文件。实际上,我们还可以使用手动分配媒体流的方式,用一条命令完成。
 
 
这时就要用到 <code>-map</code> 选项了,一旦你使用了这个选项, FFmpeg 就不会自动为你将输入文件的媒体流分配到输出文件上,相对的,你可以手动分配。 <code>-map</code> 选项的参数是 <code>输入文件编号:这个文件的媒体流编号</code> ,指定一次即代表这个媒体流会被分配到输出文件中,比如 <code>-map 0:0</code> 将会指定 0 号输入文件的 0 号媒体流(注意编号是以 0 开始计数!)。
 
 
<code>-map</code> 选项可以指定多次,从而依次指定输出的媒体流顺序,也就是说,第一次 <code>-map</code> 指定的媒体流将会变成输出文件的 0 号媒体流,第二次 <code>-map</code> 就会指定输出文件的 1 号媒体流,以此类推。举个例子,如果写了 <code>-map 0:0 -map 0:1</code> ,那么 0 号输入文件的 0 号媒体流就会变成输出文件的 0 号媒体流, 0 号输入文件的 1 号媒体流就会变成输出文件的 1 号媒体流。画一幅图来帮助理解:
 
 
[[文件:Stream-map-simple.png]]
 
 
那么用 <code>-map</code> 该怎样完成这一节开头提到的任务呢?
 
 
首先我们需要知道 <code>a.mp4</code> 和 <code>b.mp4</code> 的媒体流有哪些,这可以通过 <code>ffmpeg -i a.mp4</code> 来完成, FFmpeg 会显示出该文件的信息,就像:
 
 
<syntaxhighlight lang="text">
 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'a.mp4':
 
  Metadata:
 
    major_brand    : isom
 
    minor_version  : 512
 
    compatible_brands: isomiso2avc1mp41
 
    encoder        : Lavf56.7.104
 
  Duration: 00:14:39.60, start: 0.000000, bitrate: 1674 kb/s
 
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1543 kb/s, 24 fps, 24 tbr, 16k tbn, 48 tbc (default)
 
    Metadata:
 
      handler_name    : VideoHandler
 
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 125 kb/s (default)
 
    Metadata:
 
      handler_name    : SoundHandler
 
</syntaxhighlight>
 
 
我们可以看到 <code>Stream #0:0</code> ,这代表接下来写的是第 1 个输入文件的第 1 个媒体流的信息,它告诉我们这是一个视频流,用 H264 编码。剩下的就不用管了,我们只需要记住 <code>a.mp4</code> 的视频流的编号是 <code>0</code> 就可以了。
 
 
同样的,用 <code>ffmpeg -i b.mp4</code> 查看 <code>b.mp4</code> 的信息,寻找它的音频流的编号并记住它,我这里以 <code>1</code> 为例。
 
 
那么现在我们可以写最后的命令了,先指定两个输入文件, <code>ffmpeg -i a.mp4 -i b.mp4</code> ,这样 <code>a.mp4</code> 就会是第一个输入文件(编号为 0 ), <code>b.mp4</code> 就会是第 2 个输入文件(编号为 1 )。
 
 
我们已经知道 <code>a.mp4</code> 的视频流的编号是 <code>0</code> 了,那么就加上 <code>-map 0:0</code> ,让 FFmpeg 把第 1 个输入文件的第 1 个媒体流输出,作为输出文件的的第 1 个媒体流。 
 
我们也知道 <code>b.mp4</code> 的音频流的编号是 <code>1</code> ,就再加上 <code>-map 1:1</code> 。
 
 
{{注意|别忘了 <code>-c copy</code> ,除非你想重新编码。}}
 
 
最后写上输出文件的名字,整条命令就会是 <code>ffmpeg -i a.mp4 -i b.mp4 -map 0:0 -map 1:1 -c copy final.mp4</code> 。
 
 
FFmpeg 在开始执行的时候会给我们一个很直观的媒体流分配图示:
 
 
<syntaxhighlight lang="text">
 
Stream mapping:
 
  Stream #0:0 -> #0:0 (copy)
 
  Stream #1:1 -> #0:1 (copy)
 
</syntaxhighlight>
 
 
也就是 0 号输入文件的 0 号媒体流变成了 0 号输出文件的 0 号媒体流, 1 号输入文件的 1 号媒体流变成了 0 号输出文件的 1 号媒体流。画成更加直观的图就是:
 
 
[[文件:Stream-map-selective.png]]
 
 
以此类推,你应该能使用更复杂的媒体流分配了。
 

请注意您对FiveYellowMice's Wiki的所有贡献都被认为是在署名-相同方式共享 4.0 国际下发布,请查看在项目:版权的细节。如果您不希望您的文字被任意修改和再散布,请不要提交。
您同时也要向我们保证您所提交的内容是您自己所作,或得自一个不受版权保护或相似自由的来源。不要在未获授权的情况下发表!

为保护wiki免于自动化编辑破坏,我们恳请您输入下面的验证码:

取消 编辑帮助(在新窗口中打开)