FFmpeg 常见问题解答

目录

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

仅当您安装了 ffdshow 或 Xvid 等 MPEG-4 编解码器时。

mpeg1video

仅 .mpg

请注意,ASF 文件在 Windows 中通常具有 .wmv 或 .wma 扩展名。还应该提到的是,微软声称拥有 ASF 格式的专利,并且可能会起诉或威胁使用非微软软件创建 ASF 文件的用户。强烈建议尽可能避免非洲猪瘟。

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

adpcm_ima_wav
adpcm_ms
pcm_s16le

总是

libmp3lame

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

2 编译

2.1error: can't find a register in class 'GENERAL_REGS' while reloading 'asm'

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

另请注意,(某些)gcc 开发人员认为这不是错误,也不是他们应该修复的错误: https: //gcc.gnu.org/bugzilla/show_bug.cgi ?id=11203 。话又说回来,他们中的一些人不知道不可判定问题和 NP 困难问题之间的区别......

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

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

要构建 FFmpeg,您需要安装开发包。它通常被称为libfoo-dev或者libfoo-开发。您可以在构建完成后将其删除,但请务必保留主包。

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

在你的图书馆的某个地方,有一个。个人电脑文件(或多个)在软件包配置目录。您需要设置环境变量以指向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

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

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

pkg-config2.4交叉编译时如何使用?

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

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

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

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

3 使用方法

3.1 ffmpeg不起作用;怎么了?

make distclean在构建之前在 ffmpeg 源目录中尝试 a 。如果这没有帮助请参阅(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, ETC。

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

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

如果您有大量图片需要重命名,可以使用以下命令来减轻负担。该命令使用 bourne shell 语法,以符号方式链接当前目录中*jpg/tmp目录按顺序 img001.jpg,img002.jpg等等。

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

电影.mpg用作输入将被转换为 电影1.jpg,电影2.jpg, ETC...

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

-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 而不是默认值。

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_flagsskip_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_flagsskip_rd'。

3.11 使用 ffmpeg 编码时,隔行扫描视频看起来很糟糕,什么问题?

您应该使用“-flags +ilme+ildct”,也许还可以使用“-flags +alt”来表示交错材质,如果结果看起来真的很混乱,请尝试“-top 0/1”。

3.12 如何读取DirectShow 文件?

如果您已经构建了 FFmpeg ./configure --enable-avisynth (仅适用于 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),并且通过简单地调用 ffmpeg 和几个来完成-我选项。
  • 对于音频,将所有通道放在一个流中(例如:两个单声道流合并为一个立体声流):有时调用此方法来 合并它们,并且可以使用过滤器来完成 amerge
  • 对于音频,在另一个之上播放一个:这称为混合 它们,可以通过首先将它们合并到单个流中,然后使用过滤pan器随意混合通道来完成。
  • 对于视频,将两者一起显示、并排显示或一个显示在另一个的一部分之上;可以使用 overlay视频过滤器来完成。

3.14 如何拼接视频文件?

有多种解决方案,具体取决于具体情况。

3.14.1 使用 concat过滤器进行连接

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

3.14.2 使用 concat demuxer进行连接

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

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

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

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

因此,您可以通过首先将多媒体文件转码为这些特权格式,然后使用简单的命令(或Windows 下 cat同样简单的命令),最后转码回您选择的格式来连接多媒体文件。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 拉菲,音频无明显原因变成单声道。

使用-转储图-找出通道布局丢失的确切位置。

最有可能的是,它是通过auto-inserted aresample。尝试理解为什么那个地方需要转换过滤器。

就在输出之前是一个可能的位置,如-f 拉菲目前仅支持打包的S16。

然后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 or setsar filters.

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

例如,要修复编码错误的 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 挂起并显示诸如“暂停(tty 输出)”之类的消息?

如果您在后台运行 ffmpeg,您可能会发现其进程挂起。可能会出现诸如“暂停(tty 输出)”之类的消息。问题是如何防止进程被挂起。

例如:

% 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?

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

示例也是默认安装的,通常在 $PREFIX/share/ffmpeg/examples.

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

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

这取决于。如果您的编译器符合 C99 标准,那么支持它的补丁如果不会用与#ifdef编译器相关的 s 污染源代码,那么它们可能会受到欢迎。

4.3 是否支持 Microsoft Visual C++?

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

4.4 可以添加 automake、libtool 或 autoconf 支持吗?

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

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

FFmpeg 已经以高度模块化的方式组织,不需要用正式的对象语言重写。此外,许多开发人员更喜欢纯 C;这对他们有用。有关此事的更多争论,请阅读《编程宗教》

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

构建过程创建ffmpeg_gffplay_g等,其中包含完整的调试信息。这些二进制文件被剥离以创建 ffmpegffplay等。如果您需要调试信息,请使用 *_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)

文档/示例/Makefile文档/示例/pc-卸载更多细节。

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

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

请参阅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 一起使用?

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

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 fate没有运行所有测试?

确保您有命运套件示例,并且SAMPLESMake 变量或FATE_SAMPLES环境变量或该--samples configure选项设置为正确的路径。

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

您碰巧~在示例路径中有一个字符来指示主目录吗?该值的使用方式使 shell 无法扩展它,从而导致 FATE 找不到文件。只需替换~为完整路径即可。

本文档于2023 年 11 月 17 日使用makeinfo 生成。

由telepoint.bg提供的托管