打开主菜单

更改

创建页面,内容为“== 简单的文件输入与输出 == 首先你要准备一个视频文件,大部分你能见到的视频文件都可以,只要不是有 [https://zh.wikipedia.or...”
== 简单的文件输入与输出 ==

首先你要准备一个视频文件,大部分你能见到的视频文件都可以,只要不是有 [https://zh.wikipedia.org/wiki/%E6%95%B0%E5%AD%97%E7%89%88%E6%9D%83%E7%AE%A1%E7%90%86 DRM 保护]的或者某某客户端的“专有格式”,基本上 FFmpeg 都能应付。不过作为练习,最好不要拿太大的文件,因为这样转换的时间会比较长。

我这里使用 [https://zh.wikipedia.org/wiki/Tor Tor] 的介绍视频来作为例子,可以从[https://blog.torproject.org/blog/releasing-tor-animation 这个页面]来下载到,我所选择的是 [https://media.torproject.org/video/2015-03-animation/HQ/Tor_Animation_en.mp4 English HQ] 版本。当然,如我刚刚所说,你没有必要非得使用这个视频。

假设这个视频已经下载到了你的电脑硬盘中,并存放在 <code>/home/alex/Downloads/</code> 这个目录里面,而且 FFmpeg 已经[[如何使用_FFmpeg_进行视频转码:下载与安装|安装]]到你的电脑中。那么现在[[如何使用_FFmpeg_进行视频转码:运行#查看帮助|打开终端]],然后使用 <code>cd</code> 命令转到文件所在的位置,比如在我的情况下,运行 <code>cd /home/alex/Downloads/</code> ,它不会有任何输出。

{{注意|如果文件路径包含空格或一些特殊字符,请使用半角引号( <code>'</code> 或 <code>"</code> )将路径名包起来,比如如果文件在 <code>/home/alex/path with space/</code> ,执行 <code>cd "/home/alex/path with space/"</code> 而'''不是''' <code>cd /home/alex/path with space/</code> 。}}

{{注意|如果你使用的是 Microsoft Windows ,并且文件不在 C 盘,需要再“执行”一下盘符,比如如果文件存放在 <code>D:\\Downloads\</code> 里面,执行以下两条命令:<syntaxhighlight lang="batch">cd D:\\Downloads\
D:</syntaxhighlight>}}

<code>cd</code> 完了之后,如果你有强迫症想要检查一下是否真的已经切换到目标目录去了,可以运行 <code>ls</code> ( GNU/Linux, Mac OS X )或 <code>dir</code> ( Microsoft Windows )。只要显示出来的确实是那个目录里的文件,就说明没有问题,你可以放心继续。

[[文件:Cd-ls.png]]

接下来输入 <code>ffmpeg</code> 但不要回车,我们要使用 <code>-i</code> [[如何使用_FFmpeg_进行视频转码:运行#“选项”与“参数”|选项]]来指定输入文件。输入文件就是我们要转换的文件,比如我在此处要转换的文件叫做 <code>Tor_Animation_en.mp4</code> ,我就再往命令行中打 <code>-i Tor_Animation_en.mp4</code> 。

在指定了输入文件之后,我们还要指定一个输出文件,不然 FFmpeg 把转换出来的文件保存在哪儿呢?

输出文件可以是任何名字,但它的后缀名很关键,[[如何使用_FFmpeg_进行视频转码:媒体文件的结构|上一章]]已经讲过,后缀名通常就代表着文件的封装格式。在这个例子中,我想将视频转换为 [https://zh.wikipedia.org/wiki/Matroska Matroska] 格式(俗称 MKV 格式),那么我输出文件的后缀名就得是 <code>.mkv</code> 。最终,我想将文件保存为 <code>tor.mkv</code> ,就在命令行后面直接加上这个文件名。

最后,我的命令行上有着这样一条命令:

<syntaxhighlight lang="shell">ffmpeg -i Tor_Animation_en.mp4 tor.mkv</syntaxhighlight>

{{注意|跟 <code>cd</code> 时的目录路径一样,如果文件名包含空格或一些特殊字符,也需要用半角引号将它们包裹起来。比如如果输入文件名叫 <code>input file.mp4</code> 且输出文件名叫 <code>output file.mkv</code> ,整条命令就得是 <code>ffmpeg -i "input file.mp4" "output file.mkv"</code> 。}}

按下回车吧!

虽然这一节的内容很长,不过你读过之后应该就会发现,这其实就是这么一条简单的命令。为了使大家更好理解,我才将这一节写的这么详细。

如果你使用的文件很小,而且电脑性能不是特别差,可能你还没有读完上一段话,就已经转换完成了。你的命令行窗口可能看起来像是这样:

[[文件:Successful-completed.png]]

你通常不必去管里面写的是什么,只要没出现红色的 <code>ERROR</code> ,一般就是没有问题地完成了。

现在,你闪闪发亮的输出文件已经保存在原来的目录中了。在我这里,这个 <code>tor.mkv</code> 就是转换后的输出文件。

[[文件:Files-in-explorer.png]]

== 制定编码器 ==

FFmpeg 会自动判断输入文件的封装格式以及编码,并且根据输出文件的后缀名来判断其封装格式。同时, FFmpeg 也会根据该种封装格式的默认编码来决定输出文件的编码。运行 <code>ffmpeg -help muxer=matroska</code> 就可以查看 Matroska 格式的默认编码了,我们可以在这条命令的输出中找到这样几行字:

<syntaxhighlight lang="text">
Muxer matroska [Matroska]:
Common extensions: mkv.
Mime type: video/x-matroska.
Default video codec: h264.
Default audio codec: vorbis.
Default subtitle codec: ass.
</syntaxhighlight>

它们的意思是: Matroska 封装格式,通常的后缀名为 <code>mkv</code> ,[https://zh.wikipedia.org/wiki/%E5%A4%9A%E7%94%A8%E9%80%94%E4%BA%92%E8%81%AF%E7%B6%B2%E9%83%B5%E4%BB%B6%E6%93%B4%E5%B1%95 MIME] 为 <code>video/x-matroska</code> ,默认视频编码为 <code>h264</code> ,默认音频编码为 <code>vorbis</code> ,默认字幕编码为 <code>ass</code> 。如果你的[[如何使用_FFmpeg_进行视频转码:运行#中文是世界上最美的语言,但是……|英语水平没问题]],读懂这些将轻而易举。

{{注意|FFmpeg 的版本不同,各种封装格式的默认编码器也有可能不同,请[[如何使用_FFmpeg_进行视频转码:运行#查看帮助|确认]]你所拥有的 FFmpeg 是最新版本的。}}

[https://zh.wikipedia.org/wiki/H.264/MPEG-4_AVC H264] 和 [https://zh.wikipedia.org/wiki/Vorbis Vorbis] 都是两种十分流行的编码,大部分播放器都可以播放。不过,如果我想使用 Matroska 作为封装格式,但使用 [https://zh.wikipedia.org/wiki/%E9%AB%98%E6%95%88%E7%8E%87%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81 HEVC] 作为视频编码,该怎么办呢?

快使用“帮助大法”,执行 <code>ffmpeg -help</code> 查看帮助!然后我们能看到这样一行:

<syntaxhighlight lang="text">
-vcodec codec force video codec ('copy' to copy stream)
</syntaxhighlight>

它告诉我们,使用 <code>-vcodec</code> 选项,可以指定视频编码器。如果指定 <code>copy</code> 将不会重新编码,而是直接把原来的媒体流拷贝过去。

现在我们可以在原来的命令( <code>ffmpeg -i Tor_Animation_en.mp4 tor.mkv</code> )的'''输出文件名之前''',加上 <code>-vcodec hevc</code> ,这样 FFmpeg 就会使用 HEVC 而不是 H264 进行视频的编码。

最后我们要使用的命令是这样的:

<syntaxhighlight lang="shell">
ffmpeg -i Tor_Animation_en.mp4 -vcodec hevc tor.mkv
</syntaxhighlight>

按下回车!

如果出现了 <code>File 'tor.mkv' already exists. Overwrite ? [y/N]</code> ,不要惊慌,他只是告诉你 <code>tor.mkv</code> 这个文件已经存在了,并问你是否要覆盖。如果你要覆盖原来的文件,按 <code>y</code> 再回车;如果你不想覆盖,按 <code>n</code> 回车,把文件名改一下,再重新执行命令。

这回的等待时间可能就长一些了,因为 HEVC 是一个压缩比更高的编码,需要的时间也长。

同样的,在 <code>ffmpeg -help</code> 的输出中,我们也可以找到 <code>-acodec</code> 选项,它是用来指定音频编码的。所以如果我想要以 Matroska 作为封装格式, HEVC 作为视频编码, [https://zh.wikipedia.org/wiki/Opus_codec Opus] 作为音频编码,使用的命令会是这样的:

<syntaxhighlight lang="shell">
ffmpeg -i Tor_Animation_en.mp4 -vcodec hevc -acodec opus tor.mkv
</syntaxhighlight>

如果我想要直接拷贝媒体流到输出文件中而不重新进行编码(也就是只转换一下封装格式),在编码器的位置上写 <code>copy</code> 。比如 <code>ffmpeg -i Tor_Animation_en.mp4 -vcodec copy -acodec copy tor.mkv</code> ,因为这样不进行编码,所以通常会很快。

{{提示|<code>-vcodec</code> 有一个缩写叫做 <code>-c:v</code> , <code>-acodec</code> 有一个缩写叫做 <code>-c:a</code> 。也就是说, <code>ffmpeg -i Tor_Animation_en.mp4 -vcodec hevc -acodec opus tor.mkv</code> 可以写为 <code>ffmpeg -i Tor_Animation_en.mp4 -c:v hevc -c:a opus tor.mkv</code> ,两者没有任何区别。<br>使用这样的小把戏可以省下打几个字母的时间。以后我举例也一直都会用这种简单的写法。}}

== 照它说的做 ==

[https://zh.wikipedia.org/wiki/%E9%80%B2%E9%9A%8E%E9%9F%B3%E8%A8%8A%E7%B7%A8%E7%A2%BC AAC] 是一种被十分广泛使用的音频编码,也是 [https://zh.wikipedia.org/wiki/MP4 MP4] 封装格式的默认音频编码。 FFmpeg 当然也对此提供了支持。那么现在我将我的视频转换为 Matroska 封装格式, HEVC 视频编码, AAC 音频编码吧!

可是,我在运行 <code>ffmpeg -i ffmpeg -i Tor_Animation_en.mp4 -c:v hevc -c:a aac tor.mkv</code> 的时候,它出错了,还以红色字体显示:

<syntaxhighlight lang="text">
[aac @ 0x55fcc749c580] The encoder 'aac' is experimental but experimental codecs
are not enabled, add '-strict -2' if you want to use it.
</syntaxhighlight>

这是什么情况?难道 FFmpeg 不支持 AAC 吗?当然不是,忽略程序给出的错误提示是不应该的,我们来看一看这条错误提示吧!

它说,编码器 <code>aac</code> 是实验性的,但是它没有被启用,如果你想使用他的话就加上 <code>-strict -2</code> 。

既然 FFmpeg 告诉了我们要加上 <code>-strict -2</code> ,那我们就照他说的做,在输出文件之前加上这两个选项。不用管它究竟是什么意思,加就是了。

<syntaxhighlight lang="shell">
ffmpeg -i Tor_Animation_en.mp4 -c:v hevc -c:a aac -strict -2 tor.mkv
</syntaxhighlight>

好,这样就顺利完成了。

FFmpeg 在出错的时候总会尽它的一切力量来减少你的麻烦,在它能做到的时候,甚至会手把手告诉你如何来解决,而且它的解决方式也通常是最有效的。即使它不能,也会给出详细的错误信息,方便你找到问题、上网搜索或请教别人。

== 学会看输出 ==

别看 FFmpeg 只有一条命令来让用户完成操作,实际上,它告诉你的信息多的令人惊讶!

=== 转换时 ===

在执行了上一节最后给出的命令后,我的终端窗口冒出了大量的字符,但是还没等我看完,就迅速被这样的信息给填满了:

<syntaxhighlight lang="text">
frame= 28 fps=0.0 q=0.0 size= 2kB time=00:00:01.49 bitrate= 11.3kbits/s
frame= 30 fps= 17 q=-0.0 size= 13kB time=00:00:01.49 bitrate= 71.1kbits/
frame= 34 fps= 15 q=-0.0 size= 20kB time=00:00:01.66 bitrate= 99.9kbits/
frame= 38 fps= 13 q=-0.0 size= 31kB time=00:00:01.83 bitrate= 138.1kbits/
frame= 42 fps= 12 q=-0.0 size= 40kB time=00:00:02.00 bitrate= 165.1kbits/
frame= 46 fps= 11 q=-0.0 size= 49kB time=00:00:02.17 bitrate= 185.4kbits/
frame= 50 fps= 10 q=-0.0 size= 57kB time=00:00:02.34 bitrate= 199.3kbits/
frame= 54 fps= 10 q=-0.0 size= 63kB time=00:00:02.51 bitrate= 204.9kbits/
frame= 58 fps=9.5 q=-0.0 size= 74kB time=00:00:02.68 bitrate= 226.2kbits/
frame= 62 fps=9.2 q=-0.0 size= 85kB time=00:00:02.68 bitrate= 260.5kbits/
frame= 65 fps=8.8 q=-0.0 size= 92kB time=00:00:02.85 bitrate= 264.9kbits/
</syntaxhighlight>

这些是什么玩意儿?我没有看到我的进度条,也没有百分比,难道我要在这里干等着,不知道什么时候转码才会结束吗?

FFmpeg 确实不会显示进度条和百分比,不过,它会给你比进度条和百分比还要多的信息。

# 最左边的 <code>frame= 65</code> 是转码所进行到的[https://zh.wikipedia.org/wiki/%E5%B8%A7 帧]数,显示 65 就表示现在已经转到了第 65 帧。
# 第二个 <code>fps=8.8</code> 中的 FPS 就是 '''F'''rame '''p'''er '''S'''econd ,也就是现在电脑每秒所处理的帧的数量。注意这个数字跟视频的帧率并无关系。
# <del>其实我也不知道后面那个 `q=-0.0` 是什么意思,大家不要来打我呀。</del>
# 接下来的 <code>size= 92kB</code> 表示现在已经转换出来的视频的体积,这个数字只会越变越大啊。
# 第五个 <code>time=00:00:02.85</code> 顾名思义就是时间了,它是已经转换出来的视频的时间。在我看来,它也是一个比百分比进度条更加精准的进度显示。

如果你认为这么多信息是“无用的”,那么只要看 <code>time</code> 这一栏就好,我想你应该知道你原来的视频有多长,那么从已经转换的时间应该能看出你已经完成了多少了吧?

=== 转换前 ===

话说回来,在我的终端被这些信息刷屏之前,出来的一大堆<del>看起来很不错的</del>文字是什么?让我们用鼠标滚轮滚回去看看吧。

<syntaxhighlight lang="text">
ffmpeg version 2.8 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 5.2.0 (GCC)
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripp
ing --enable-avisynth --enable-avresample --enable-fontconfig --enable-gnutls --
enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libfreety
pe --enable-libfribidi --enable-libgsm --enable-libmodplug --enable-libmp3lame -
-enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enab
le-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-
libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvorbis
--enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libx
vid --enable-shared --enable-version3 --enable-x11grab
libavutil 54. 31.100 / 54. 31.100
libavcodec 56. 60.100 / 56. 60.100
libavformat 56. 40.101 / 56. 40.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 40.101 / 5. 40.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.101 / 1. 2.101
libpostproc 53. 3.100 / 53. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Tor_Animation_en.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isomavc1
creation_time : 2015-03-12 15:36:45
encoder : HandBrake 0.9.5 2011010300
Duration: 00:02:17.45, start: 0.000000, bitrate: 842 kb/s
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709)
, 1920x1080 [SAR 1:1 DAR 16:9], 674 kb/s, 24 fps, 24 tbr, 90k tbn, 180k tbc (def
ault)
Metadata:
creation_time : 2015-03-12 15:36:45
encoder : JVT/AVC Coding
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, flt
p, 163 kb/s (default)
Metadata:
creation_time : 2015-03-12 15:36:45
x265 [info]: HEVC encoder version 1.7
x265 [info]: build info [Linux][GCC 5.1.0][64 bit] 8bpp
x265 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
x265 [info]: Main profile, Level-4 (Main tier)
x265 [info]: Thread pool created using 4 threads
x265 [info]: frame threads / pool features : 2 / wpp(17 rows)
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
x265 [info]: ME / range / subpel / merge : hex / 57 / 2 / 2
x265 [info]: Keyframe min / max / scenecut : 24 / 250 / 40
x265 [info]: Lookahead / bframes / badapt : 20 / 4 / 2
x265 [info]: b-pyramid / weightp / weightb / refs: 1 / 1 / 0 / 3
x265 [info]: AQ: mode / str / qg-size / cu-tree : 1 / 1.0 / 64 / 1
x265 [info]: Rate Control / qCompress : CRF-28.0 / 0.60
x265 [info]: tools: rd=3 psy-rd=0.30 signhide tmvp strong-intra-smoothing
x265 [info]: tools: deblock sao
Output #0, matroska, to 'tor.mkv':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isomavc1
encoder : Lavf56.40.101
Stream #0:0(und): Video: hevc (libx265), yuv420p, 1920x1080 [SAR 1:1 DAR 16:
9], q=2-31, 24 fps, 1k tbn, 24 tbc (default)
Metadata:
creation_time : 2015-03-12 15:36:45
encoder : Lavc56.60.100 libx265
Stream #0:1(eng): Audio: aac ([255][0][0][0] / 0x00FF), 48000 Hz, stereo, fl
tp, 128 kb/s (default)
Metadata:
creation_time : 2015-03-12 15:36:45
encoder : Lavc56.60.100 aac
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> hevc (libx265))
Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
frame= 28 fps=0.0 q=0.0 size= 2kB time=00:00:01.49 bitrate= 11.3kbits/s
</syntaxhighlight>

这些数据可有点多啊,我不会把每一句话都作详细说明,只是挑一些用处比较大的讲一下。

上面的版本信息不用管,然后我们能看到一行 <code>Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Tor_Animation_en.mp4':</code> ,显然这下面就是关于第 0 个输入文件的信息了。(别忘了,在 IT 界,许多东西都喜欢以 0 而不是 1 开始计数)

<code>Duration: 00:02:17.45, start: 0.000000, bitrate: 842 kb/s</code> 这一行告诉我们这个视频长度是 2 分 17 秒 45 ,从 0.000000 开始,比特率 842 kb/s 。

下面一行很长,不过我们只看前面一段 <code>Stream #0:0(und): Video: h264</code> ,它告诉我们, 0 号输入文件的 0 号媒体流,视频流, <code>h264</code> 编码。

然后是 <code>Stream #0:1(eng): Audio: aac</code> , 0 号输入文件的 1 号媒体流,音频流, <code>aac</code> 编码。

再往下 <code>x265 [info]</code> 开头的一大堆,都是 HEVC 的编码程序 <code>x265</code> 所给出的信息,看不懂就甭管了。

后面我们就能看到关于输出文件的信息,还有其编码。

接下来重要的信息来了:

<syntaxhighlight lang="text">
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> hevc (libx265))
Stream #0:1 -> #0:1 (aac (native) -> aac (native))
</syntaxhighlight>

媒体流的分配,很直观,我们能看到输入文件的视频流从 <code>h264</code> 转成了 <code>hevc</code> ,音频流从 <code>aac</code> 还是转成了一样的 <code>aac</code> 。从这里你可以快速的检查一下,你是否输入了你想要执行的命令。

哦,还不能忘记最后一条很有用的信息, <code>Press [q] to stop, [?] for help</code> ,它告诉你在转码的时候按 q 来中断, ? 来查看帮助。有经验的人可能知道用 Ctrl + C 可以中断,不过那个是强制退出,按 q 是相对自然一些的中断。

----

读到这里,你应该能使用 FFmpeg 来进行简单的转码了,而这个教程的“入门”阶段也完成了。在[[如何使用_FFmpeg_进行视频转码:转码时能顺便一起做的事情|下一章]],我们将会使 FFmpeg 变得更加有效率和实用。
按 ? 会出来什么呢?感兴趣的话就自己来探索一下吧。