打开主菜单

如何使用 FFmpeg 进行视频转码:开始转码

128.199.198.241讨论2022年6月23日 (四) 15:26的版本 →‎简单的文件输入与输出 Windows 注意
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

简单的文件输入与输出编辑

首先你要准备一个视频文件,大部分你能见到的视频文件都可以,只要不是有 DRM 保护的或者某某客户端的“专有格式”,基本上 FFmpeg 都能应付。不过作为练习,最好不要拿太大的文件,因为这样转换的时间会比较长。

我这里使用 Tor 的介绍视频来作为例子,可以从这个页面来下载到,我所选择的是 English HQ 版本。当然,如我刚刚所说,你没有必要非得使用这个视频。

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

注意: 如果文件路径包含空格或一些特殊字符,请使用半角引号( '" )将路径名包起来,比如如果文件在 /home/alex/path with space/ ,执行 cd "/home/alex/path with space/"不是 cd /home/alex/path with space/
注意: 如果你使用的是 Microsoft Windows ,并且文件不在 C 盘,则需为 cd 添加 /D 选项(成为 cd /D ),或者改用 pushd 进行切换;也可以“执行”一下目标盘符,比如如果文件存放在 D:\\Downloads\ 里面,执行以下两条命令:
cd D:\\Downloads\
D:

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

 

接下来输入 ffmpeg 但不要回车,我们要使用 -i 选项来指定输入文件。输入文件就是我们要转换的文件,比如我在此处要转换的文件叫做 Tor_Animation_en.mp4 ,我就再往命令行中打 -i Tor_Animation_en.mp4

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

输出文件可以是任何名字,但它的后缀名很关键,上一章已经讲过,后缀名通常就代表着文件的封装格式。在这个例子中,我想将视频转换为 Matroska 格式(俗称 MKV 格式),那么我输出文件的后缀名就得是 .mkv 。最终,我想将文件保存为 tor.mkv ,就在命令行后面直接加上这个文件名。

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

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

按下回车吧!

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

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

 

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

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

 

指定编码器编辑

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

Muxer matroska [Matroska]:
    Common extensions: mkv.
    Mime type: video/x-matroska.
    Default video codec: h264.
    Default audio codec: vorbis.
    Default subtitle codec: ass.

它们的意思是: Matroska 封装格式,通常的后缀名为 mkvMIMEvideo/x-matroska ,默认视频编码为 h264 ,默认音频编码为 vorbis ,默认字幕编码为 ass 。如果你的英语水平没问题,读懂这些将轻而易举。

注意: FFmpeg 的版本不同,各种封装格式的默认编码器也有可能不同,请确认你所拥有的 FFmpeg 是最新版本的。

H264Vorbis 都是两种十分流行的编码,大部分播放器都可以播放。不过,如果我想使用 Matroska 作为封装格式,但使用 HEVC 作为视频编码,该怎么办呢?

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

-vcodec codec       force video codec ('copy' to copy stream)

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

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

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

ffmpeg -i Tor_Animation_en.mp4 -vcodec hevc tor.mkv

按下回车!

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

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

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

ffmpeg -i Tor_Animation_en.mp4 -vcodec hevc -acodec opus tor.mkv

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

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

照它说的做编辑

AAC 是一种被十分广泛使用的音频编码,也是 MP4 封装格式的默认音频编码。 FFmpeg 当然也对此提供了支持。那么现在我将我的视频转换为 Matroska 封装格式, HEVC 视频编码, AAC 音频编码吧!

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

[aac @ 0x55fcc749c580] The encoder 'aac' is experimental but experimental codecs
are not enabled, add '-strict -2' if you want to use it.

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

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

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

ffmpeg -i Tor_Animation_en.mp4 -c:v hevc -c:a aac -strict -2 tor.mkv

好,这样就顺利完成了。

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

学会看输出编辑

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

转换时编辑

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

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/

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

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

  1. 最左边的 frame= 65 是转码所进行到的数,显示 65 就表示现在已经转到了第 65 帧。
  2. 第二个 fps=8.8 中的 FPS 就是 Frame per Second ,也就是现在电脑每秒所处理的帧的数量。注意这个数字跟视频的帧率并无关系。
  3. 其实我也不知道后面那个 `q=-0.0` 是什么意思,大家不要来打我呀。
  4. 接下来的 size= 92kB 表示现在已经转换出来的视频的体积,这个数字只会越变越大啊。
  5. 第五个 time=00:00:02.85 顾名思义就是时间了,它是已经转换出来的视频的时间。在我看来,它也是一个比百分比进度条更加精准的进度显示。

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

转换前编辑

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

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

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

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

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

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

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

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

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

接下来重要的信息来了:

Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> hevc (libx265))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))

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

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


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