教程菜单 本页目录

经常问的问题

1 一般问题

1.1 为什么 FFmpeg 不支持功能 [xyz]?

因为还没有人承担这项任务。FFmpeg 的开发由对个人开发人员来说很重要的任务驱动。如果有一个对你来说很重要的功能,实现它的最佳方式是自己承担任务或赞助开发人员。

1.2 FFmpeg 不支持编解码器 XXX。您可以包含 Windows DLL 加载器来支持它吗?

不可以。Windows DLL 不可移植、臃肿且通常很慢。此外,FFmpeg 致力于原生支持所有编解码器。DLL 加载器不利于实现该目标。

1.3 虽然 ffmpeg 似乎支持这种格式,但我无法读取此文件。

即使 ffmpeg 可以读取容器格式,也可能不支持其所有编解码器。请参阅 ffmpeg 文档中支持的编解码器列表。

1.4 Windows 支持哪些编解码器?

除非您安装一些额外的编解码器,否则 Windows 不能很好地支持 MPEG 等标准格式。

以下视频编解码器列表应适用于大多数 Windows 系统:

msmpeg4v2

.avi/.asf

msmpeg4

仅限.asf

wmv1

仅限.asf

wmv2

仅限.asf

mpeg4

仅当您安装了某些 MPEG-4 编解码器(如 ffdshow 或 Xvid)时才可使用。

mpeg1video

仅限 .mpg

请注意,Windows 中的 ASF 文件通常具有 .wmv 或 .wma 扩展名。还应提及,Microsoft 已申请 ASF 格式的专利,并可能起诉或威胁使用非 Microsoft 软件创建 ASF 文件的用户。强烈建议尽可能避免使用 ASF。

以下音频编解码器列表应适用于大多数 Windows 系统:

adpcm_ima_wav
adpcm_ms
pcm_s16le

总是

libmp3lame

如果安装了某些 MP3 编解码器(如 LAME)。

2 编译

2.1 错误:重新加载“asm”时无法在“GENERAL_REGS”类中找到寄存器

这是 gcc 中的一个错误。请勿向我们报告。相反,请将其报告给 gcc 开发人员。请注意,我们不会为 gcc 错误添加解决方法。

还请注意,(部分) gcc 开发人员认为这不是错误,或者不是他们应该修复的错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11203。不过,他们中的一些人不知道不可判定问题和 NP 难问题之间的区别……

2.2 我已经使用发行版的包管理器安装了此库。为什么 configure 看不到它?

发行版通常将库分成几个包。主包包含使用库运行程序所需的文件。开发包包含使用库构建程序所需的文件。有时,文档和/或数据也在单独的包中。

要构建 FFmpeg,您需要安装开发包。它通常称为

libfoo-dev

libfoo-devel

。您可以在构建完成后将其删除,但请务必保留主包。

2.3 如何让 pkg-config 找到我的库?

除了库之外,在 pkgconfig 目录中还有一个(或多个).pc 文件。您需要设置环境变量以将 pkg-config 指向这些文件。

如果您需要将目录添加到 pkg-config 的搜索列表中(典型用例:单独安装的库),请将其添加到 $PKG_CONFIG_PATH:

export PKG_CONFIG_PATH=/opt/x264/lib/pkgconfig:/opt/opus/lib/pkgconfig

如果您需要替换 pkg-config 的搜索列表(典型用例:交叉编译),请在 $PKG_CONFIG_LIBDIR 中设置它:

export PKG_CONFIG_LIBDIR=/home/me/cross/usr/lib/pkgconfig:/home/me/cross/usr/local/lib/pkgconfig

如果您需要了解库的内部依赖项(典型用途:静态链接),请将 --static 选项添加到 pkg-config:

./configure --pkg-config-flags=--static

2.4 如何在交叉编译时使用 pkg-config?

最好的方法是在交叉编译环境中安装 pkg-config。它将自动使用交叉编译库。

您还可以通过明确指定 --pkg-config=pkg-config 来从主机环境中使用 pkg-config。在这种情况下,您必须使用 PKG_CONFIG_LIBDIR 将 pkg-config 指向正确的目录,如上一条所述。

作为中间解决方案,您可以在交叉编译环境中放置一个脚本,该脚本调用设置了 PKG_CONFIG_LIBDIR 的主机 pkg-config。该脚本可能如下所示:

#!/bin/sh
PKG_CONFIG_LIBDIR=/path/to/cross/lib/pkgconfig
export PKG_CONFIG_LIBDIR
exec /usr/bin/pkg-config "$@"

3 使用

3.1 ffmpeg 不起作用;哪里出了问题?

在构建之前,尝试在 ffmpeg 源目录中执行 make distclean。如果这没有帮助,请参阅 (https://ffmpeg.org/bugreports.html)。

3.2 如何将单张图片编码成电影?

首先,重命名图片以遵循数字顺序。例如,img1.jpg、img2.jpg、img3.jpg,...然后您可以运行:

ffmpeg -f image2 -i img%d.jpg /tmp/a.mpg

请注意,“%d”被图像编号替换。

img%03d.jpg 表示序列 img001.jpg、img002.jpg 等。

使用 -start_number 选项声明序列的起始编号。如果您的序列不是以 img001.jpg 开头,但仍按数字顺序排列,则这很有用。以下示例将从 img100.jpg 开始:

ffmpeg -f image2 -start_number 100 -i img%d.jpg /tmp/a.mpg

如果您有大量图片需要重命名,可以使用以下命令来减轻负担。该命令使用 Bourne shell 语法,将当前目录中与 *jpg 匹配的所有文件以 img001.jpg、img002.jpg 等顺序符号链接到 /tmp 目录。

x=1; for i in *jpg; do counter=$(printf %03d $x); ln -s "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done

如果您希望按最早修改的顺序排列它们,请用 $(ls -r -t *jpg) 替换 *jpg。

然后运行:

ffmpeg -f image2 -i /tmp/img%03d.jpg /tmp/a.mpg

ffmpeg 读取的任何图像格式都使用相同的逻辑。

您还可以使用 cat 将图像传送到 ffmpeg:

cat *.jpg | ffmpeg -f image2pipe -c:v mjpeg -i - output.mpg

3.3 如何将电影编码为单张图片?

使用:

ffmpeg -i movie.mpg movie%d.jpg

用作输入的 movie.mpg 将转换为 movie1.jpg、movie2.jpg 等...

除了依赖文件格式自我识别之外,您还可以使用

-c:v ppm
-c:v png
-c:v mjpeg

强制编码。

将其应用于上一个示例:

ffmpeg -i movie.mpg -f image2 -c:v mjpeg menu%d.jpg

请注意,没有“jpeg”编解码器。请改用“mjpeg”。

3.4 为什么我看到多线程 MPEG* 编码的质量略有下降?

对于多线程 MPEG* 编码,编码的片段必须是独立的,否则线程 n 实际上必须等待 n-1 完成,因此质量略有下降是很合乎逻辑的。这不是错误。

3.5 我如何从标准输入读取或写入标准输出?

使用 - 作为文件名。

3.6 -f jpeg 不起作用。

尝试“-f image2 test%d.jpg”。

3.7 为什么我不能更改帧速率?

某些编解码器(如 MPEG-1/2)仅允许少量固定帧速率。使用 -c:v 命令行选项选择不同的编解码器。

3.8 如何使用 ffmpeg 编码 Xvid 或 DivX 视频?

Xvid 和 DivX(版本 4+)都是 ISO MPEG-4 标准的实现(请注意,还有许多其他编码格式使用相同的标准)。因此,使用 '-c:v mpeg4' 以这些格式进行编码。存储在 MPEG-4 编码文件中的默认 fourcc 将为 'FMP4'。如果您想要不同的 fourcc,请使用 '-vtag' 选项。例如,'-vtag xvid' 将强制将 fourcc 'xvid' 存储为视频 fourcc,而不是默认的 fourcc。

3.9 哪些是编码高质量 MPEG-4 的良好参数?

’-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -g 300 -pass 1/2’,可尝试:’-bf 2’、’-mpv_flags qp_rd’、’-mpv_flags mv0’、’-mpv_flags skip_rd’。

3.10 哪些参数适合编码高质量 MPEG-1/MPEG-2?

’-mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -pass 1/2’ 但请注意,’-g 100’ 可能会导致某些解码器出现问题。可尝试:’-bf 2’、’-mpv_flags qp_rd’、’-mpv_flags mv0’、’-mpv_flags skip_rd’。

3.11 使用 ffmpeg 编码时,隔行扫描视频看起来非常糟糕,问题出在哪里?

对于隔行扫描材料,您应该使用’-flags +ilme+ildct’,也许还可以使用’-flags +alt’,如果结果看起来非常混乱,请尝试’-top 0/1’。

3.12 我如何读取 DirectShow 文件?

如果您已使用 ./configure --enable-avisynth 构建了 FFmpeg(仅在 MinGW/Cygwin 平台上可用),那么您可以使用 DirectShow 可以读取的任何文件作为输入。

只需创建一个包含以下一行的“input.avs”文本文件...

DirectShowSource("C:\path to your file\yourfile.asf")

...然后将该文本文件提供给 ffmpeg:

ffmpeg -i input.avs

如需有关 AviSynth 的任何其他帮助,请访问 AviSynth 主页。

3.13 如何合并视频文件?

“合并”视频文件的含义相当模糊。以下列表解释了不同类型的“合并”,并指出了 FFmpeg 中如何处理这些文件。合并视频文件可能意味着:

  • 将它们一个接一个地放置:这被称为连接它们(简称:concat),并在本常见问题解答中进行了说明。
  • 将它们放在同一个文件中,让用户在不同的版本之间进行选择(例如:不同的音频语言):这被称为将它们多路复用在一起(简称:mux),只需使用几个-i选项调用 ffmpeg 即可。
  • 对于音频,将所有通道放在一个流中(例如:将两个单声道流合并为一个立体声流):这有时被称为合并它们,可以使用 amerge 过滤器来完成。
  • 对于音频,将一个音频叠加在另一个音频之上:这称为混合音频,可以先将它们合并为一个流,然后使用 pan 过滤器随意混合通道。
  • 对于视频,将两个视频并排显示或将一个视频叠加在另一个视频的一部分之上;可以使用 overlay video 过滤器完成。

3.14 如何连接视频文件?

根据具体情况,有几种解决方案。

3.14.1 使用 concat 过滤器进行连接

FFmpeg 有一个专门为此设计的 concat 过滤器,文档中有示例。如果您需要重新编码,建议执行此操作。

3.14.2 使用 concat 解复用器进行连接

FFmpeg 有一个 concat 解复用器,当您想要避免重新编码并且您的格式不支持文件级连接时,您可以使用它。

3.14.3 使用 concat 协议(文件级)进行连接

FFmpeg 有一个专门为此设计的 concat 协议,文档中提供了示例。

一些多媒体容器(MPEG-1、MPEG-2 PS、DV)允许通过连接包含它们的文件来连接视频。

因此,您可以先将多媒体文件转码为这些特权格式,然后使用简单的 cat 命令(或 Windows 下同样简单的 copy),最后转码回您选择的格式,从而连接多媒体文件。

ffmpeg -i input1.avi -qscale:v 1 intermediate1.mpg
ffmpeg -i input2.avi -qscale:v 1 intermediate2.mpg
cat intermediate1.mpg intermediate2.mpg > intermediate_all.mpg
ffmpeg -i intermediate_all.mpg -qscale:v 2 output.avi

此外,您可以使用 concat 协议代替 cat 或 copy,这将避免创建可能巨大的中间文件。

ffmpeg -i input1.avi -qscale:v 1 intermediate1.mpg
ffmpeg -i input2.avi -qscale:v 1 intermediate2.mpg
ffmpeg -i concat:"intermediate1.mpg|intermediate2.mpg" -c copy intermediate_all.mpg
ffmpeg -i intermediate_all.mpg -qscale:v 2 output.avi

请注意,您可能需要转义字符“|”,这对许多 shell 来说是特殊的。

另一个选项是使用命名管道,如果您的平台支持它:

mkfifo intermediate1.mpg
mkfifo intermediate2.mpg
ffmpeg -i input1.avi -qscale:v 1 -y intermediate1.mpg < /dev/null &
ffmpeg -i input2.avi -qscale:v 1 -y intermediate2.mpg < /dev/null &
cat intermediate1.mpg intermediate2.mpg |\
ffmpeg -f mpeg -i - -c:v mpeg4 -c:a libmp3lame output.avi

3.14.4 使用原始音频和视频进行连接

同样,yuv4mpegpipe 格式以及原始视频、原始音频编解码器也允许连接,并且转码步骤几乎无损。当使用多个 yuv4mpegpipe 时,需要从除第一个流之外的所有流中丢弃第一行。这可以通过如下所示的 tail 管道来实现。请注意,当通过 tail 管道时,您必须使用命令分组 { ;} 才能正确进行背景处理。

例如,假设我们想将两个 FLV 文件连接成一个 output.flv 文件:

mkfifo temp1.a
mkfifo temp1.v
mkfifo temp2.a
mkfifo temp2.v
mkfifo all.a
mkfifo all.v
ffmpeg -i input1.flv -vn -f u16le -c:a pcm_s16le -ac 2 -ar 44100 - > temp1.a < /dev/null &
ffmpeg -i input2.flv -vn -f u16le -c:a pcm_s16le -ac 2 -ar 44100 - > temp2.a < /dev/null &
ffmpeg -i input1.flv -an -f yuv4mpegpipe - > temp1.v < /dev/null &
{ ffmpeg -i input2.flv -an -f yuv4mpegpipe - < /dev/null | tail -n +2 > temp2.v ; } &
cat temp1.a temp2.a > all.a &
cat temp1.v temp2.v > all.v &
ffmpeg -f u16le -c:a pcm_s16le -ac 2 -ar 44100 -i all.a \
       -f yuv4mpegpipe -i all.v \
       -y output.flv
rm temp[12].[av] all.[av]

3.15 使用-f lavfi,音频莫名其妙地变成单声道。

使用 -dumpgraph - 找出丢失声道布局的确切位置。

最有可能的原因是自动插入的 aresample。尝试理解为什么那个地方需要转换过滤器。

输出之前是一个可能的位置,因为 -f lavfi 目前仅支持打包的 S16。

然后在 filtergraph 中明确插入正确的 aformat,指定确切的格式。

aformat=sample_fmts=s16:channel_layouts=stereo

3.16 为什么 FFmpeg 看不到我的 VOB 文件中的字幕?

VOB 和其他一些格式没有描述文件中所有内容的全局标头。相反,应用程序应该扫描文件以查看其包含的内容。由于 VOB 文件通常很大,因此只扫描开头。如果字幕只在文件的后面出现,则不会最初检测到它们。

某些应用程序(包括 ffmpeg 命令行工具)只能处理在初始扫描期间检测到的流;稍后检测到的流将被忽略。

初始扫描的大小由两个选项控制:probesize(默认值 ~5 Mo)和 analyzeduration(默认值 5,000,000 µs = 5 s)。要检测字幕流,两个值都必须足够大。

3.17 为什么要删除 ffmpeg-sameq选项?用什么来代替?

-sameq 选项表示“相同量化器”,仅在非常有限的情况下才有意义。不幸的是,很多人误以为它是“相同质量”,并在没有意义的地方使用它:它大致具有预期的可见效果,但以非常低效的方式实现。

每个编码器都有自己的一组选项来设置质量与尺寸的平衡,使用您正在使用的编码器的选项将质量级别设置为适合您口味的点。最常用的选项是 -qscale 和 -qmax,但您应该仔细阅读您选择的编码器的文档。

3.18 我的视频被拉伸了,为什么缩放无法修复?

许多视频编解码器和格式可以存储视频的宽高比:这是完整图像(DAR,显示宽高比)或单个像素(SAR,样本宽高比)的宽度和高度之间的比率。例如,分辨率为 640×350 的 EGA 屏幕具有 4:3 DAR 和 35:48 SAR。

大多数静态图像处理使用方形像素,即 1:1 SAR,但许多视频标准(尤其是模拟数字过渡时代的视频标准)使用非方形像素。

FFmpeg 中的大多数处理过滤器都会处理宽高比以避免拉伸图像:裁剪会调整 DAR 以保持 SAR 不变,缩放会调整 SAR 以保持 DAR 不变。

如果要拉伸或“取消拉伸”图像,则需要使用 setdar 或 setsar 过滤器覆盖信息。

不要忘记仔细检查原始视频,以检查拉伸是来自图像还是来自宽高比信息。

例如,要修复编码错误的 EGA 捕获,请使用以下命令,第一个命令用于升级到方形像素,第二个命令用于设置正确的宽高比,第三个命令用于避免转码(可能不起作用,具体取决于格式/编解码器/播放器/月相):

ffmpeg -i ega_screen.nut -vf scale=640:480,setsar=1 ega_screen_scaled.nut
ffmpeg -i ega_screen.nut -vf setdar=4/3 ega_screen_anamorphic.nut
ffmpeg -i ega_screen.nut -aspect 4/3 -c copy ega_screen_overridden.nut

3.19 如何将 ffmpeg 作为后台任务运行?

ffmpeg 通常会在执行操作时检查控制台输入,例如“q”用于停止和“?”用于提供帮助。ffmpeg 没有办法检测它何时作为后台任务运行。当它检查控制台输入时,这可能会导致在后台运行 ffmpeg 的进程暂停。

为了防止这些输入检查,允许 ffmpeg 作为后台任务运行,请在 ffmpeg 调用中使用 -nostdin 选项。无论您是在 shell 中运行 ffmpeg 还是通过操作系统 API 在其自己的进程中调用 ffmpeg,这都是有效的。

作为替代方案,当您在 shell 中运行 ffmpeg 时,您可以将标准输入重定向到 /dev/null(在 Linux 和 macOS 上)或 NUL(在 Windows 上)。您可以在 ffmpeg 调用时或从调用 ffmpeg 的 shell 脚本中执行此重定向。

例如:

ffmpeg -nostdin -i INPUT OUTPUT

或(在 Linux、macOS 和其他类 UNIX shell 上):

ffmpeg -i INPUT OUTPUT </dev/null

或(在 Windows 上):

ffmpeg -i INPUT OUTPUT <NUL

3.20 如何防止 ffmpeg 因出现类似suspended (tty output)的消息而挂起?

如果您在后台运行 ffmpeg,您可能会发现其进程挂起。可能会出现类似suspended (tty output)的消息。问题是如何防止进程被挂起。

例如:

% ffmpeg -i INPUT OUTPUT &> ~/tmp/log.txt &
[1] 93352
%
[1]  + suspended (tty output)  ffmpeg -i INPUT OUTPUT &>

尽管有“tty output”消息,但这里的问题是 ffmpeg 在运行时通常会检查控制台输入。操作系统会检测到这种情况,并暂停该进程,直到您可以将其带到前台并处理它。

解决方案是使用正确的技术告诉 ffmpeg 不要咨询控制台输入。您可以使用“-nostdin”选项,或使用“< /dev/null”重定向标准输入。有关详细信息,请参阅常见问题解答如何将 ffmpeg 作为后台任务运行?

4 开发

4.1 是否有示例说明如何使用 FFmpeg 库,特别是 libavcodec 和 libavformat?

是的。检查源存储库中的 doc/examples 目录,也可以在线获取:https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples。

示例也默认安装,通常位于 $PREFIX/share/ffmpeg/examples。

您也可以阅读 FFmpeg 文档的开发人员指南。或者,检查已包含 FFmpeg 的众多开源项目之一的源代码(projects.html)。

4.2 您能支持我的 C 编译器 XXX 吗?

视情况而定。如果您的编译器符合 C99 标准,那么支持它的补丁很可能会受到欢迎,前提是它们不会用与编译器相关的 #ifdefs 污染源代码。

4.3 是否支持 Microsoft Visual C++?

是的。请参阅 FFmpeg 文档中的 Microsoft Visual C++ 部分。

4.4 您能添加 automake、libtool 或 autoconf 支持吗?

不。这些工具太臃肿,使构建变得复杂。

4.5 为什么不使用面向对象的 C++ 重写 FFmpeg?

FFmpeg 已经以高度模块化的方式组织起来,不需要用正式的对象语言重写。此外,许多开发人员更喜欢直接使用 C;这对他们来说很有用。有关此事的更多论据,请阅读“编程宗教”。

4.6 为什么 ffmpeg 程序没有调试符号?

构建过程会创建包含完整调试信息的 ffmpeg_g、ffplay_g 等。这些二进制文件被剥离以创建 ffmpeg、ffplay 等。如果您需要调试信息,请使用 *_g 版本。

4.7 我不喜欢 LGPL,我可以用 GPL 来贡献代码吗?

可以,只要代码是可选的,并且可以轻松干净地放在 #if CONFIG_GPL 下而不会破坏任何东西。因此,例如,新的编解码器或过滤器在 GPL 下是可以的,而对 LGPL 代码的错误修复则不行。

4.8 我在 C 应用程序中使用 FFmpeg,但链接器抱怨库本身缺少符号。

FFmpeg 默认构建静态库。在静态库中,不处理依赖项。这有两个后果。首先,您必须按依赖顺序指定库:-lavdevice 必须在 -lavformat 之前,-lavutil 必须在其他所有库之后,等等。其次,还必须指定 FFmpeg 中使用的外部库。

获取所需库的完整列表(按依赖顺序)的简单方法是使用 pkg-config。

c99 -o program program.c $(pkg-config --cflags --libs libavformat libavcodec)

有关更多详细信息,请参阅

doc/example/Makefile

doc/example/pc-uninstalled

4.9 我在 C++ 应用程序中使用 FFmpeg,但链接器抱怨缺少似乎可用的符号。

FFmpeg 是一个纯 C 项目,因此若要在 C++ 应用程序中使用这些库,您需要明确声明您正在使用 C 库。您可以通过使用 extern "C" 包含 FFmpeg 来实现这一点。

请参阅 http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.3

4.10 我在 C++ 应用程序中使用 libavutil,但编译器抱怨“UINT64_C”未在此范围内声明

FFmpeg 是一个使用 C99 数学功能的纯 C 项目,为了使 C++ 能够使用它们,您必须将 -D__STDC_CONSTANT_MACROS 附加到您的 CXXFLAGS

4.11 我在内存中有一个文件/一个与 *open/*read/libc 不同的 API,我该如何将其与 libavformat 一起使用?

您必须使用 avio_alloc_context 创建自定义 AVIOContext,请参阅 FFmpeg 中的 libavformat/aviobuf.c 和 MPlayer 或 MPlayer2 源中的 libmpdemux/demux_lavf.c。

4.12 有关 ffv1、msmpeg4、asv1、4xm 的文档在哪里?

请参阅 https://www.ffmpeg.org/~michael/

4.13 如何将 H.263-RTP(以及 RTP 中的其他编解码器)提供给 libavcodec?

尽管 RTP 是面向网络的,因此有些特殊,但它与其他容器一样。您必须在将有效负载提供给 libavcodec 之前对 RTP 进行解复用。在此特定情况下,请查看 RFC 4629 以了解应如何执行。

4.14 AVStream.r_frame_rate 是错误的,它比帧速率大得多。

r_frame_rate 不是平均帧速率,它是可以准确表示所有时间戳的最小帧速率。所以,如果它大于平均值,那就没有错!例如,如果您混合了 25 和 30 fps 的内容,则 r_frame_rate 将为 150(它是最小公倍数)。如果您要查找平均帧速率,请参阅 AVStream.avg_frame_rate。

4.15 为什么 make fortune 没有运行所有测试?

确保您拥有 fortune-suite 样本,并且 SAMPLES Make 变量或 FATE_SAMPLES 环境变量或 --samples 配置选项设置为正确的路径。

4.16 为什么 make fortune 找不到样本?

样本路径中是否恰好有一个 ~ 字符来表示主目录?该值的使用方式导致 shell 无法扩展它,导致 FATE 找不到文件。只需将 ~ 替换为完整路径即可。

本页目录