ffmpeg在PC上编译问题全解决
Posted blackhumour2018
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ffmpeg在PC上编译问题全解决相关的知识,希望对你有一定的参考价值。
原帖地址:http://blog.sina.com.cn/s/blog_61bc01360102w815.html
Optional
所以需要分别下载并解压以下三个库:
http://downloads.sourceforge.net/freetype/freetype-2.6.2.tar.bz2
http://fribidi.org/download/fribidi-0.19.7.tar.bz2
http://www.freedesktop.org/software/fontconfig/release/fontconfig-2.11.1.tar.bz2
(2)先来编译freetype-2.6.2(ubuntu):
./configure --prefix=/usr --disable-static && make && sudo make install
上面是在ubuntu上的,在MAC上不要指定安装目录,即如下:
./configure --disable-static && make && sudo make install
(3)接下来编译fontconfig-2.11.1(ubuntu):
./configure --prefix=/usr -disable-docs && make && sudo make install
上面是在ubuntu上的,在MAC上不要指定安装目录,即如下:
./configure -disable-docs && make && sudo make install
(4)接下来编译fribidi-0.19.7
编译fribidi的时候需要先下载expat源码并编译
http://expat.sourceforge.net/
./configure && make && sudo make install
开始编译 fribidi(ubuntu):
./configure --prefix=/usr && make && sudo make install
在MAC上用以下指令:
./configure && make && sudo make install
(5)以上三个依赖库编译完后,开始编译libass (ubuntu):
./configure --prefix=/usr --disable-static && make && sudo make install
在MAC上使用以下指令:
./configure --disable-static && make && sudo make install
如果在编译libass的时候还有问题,请重新把上面的几个库变个顺序编译一遍就可以解决。也可以在libass编译时出错的信息中看到依赖的哪个库没有找到,重新编译这个库就可以。
(6)编译完后发现依然还是产生错误:ERROR: libass not found using pkg-config
从config.log文件的最后看出来,是pk-config这个工具在查找一个*.pc的文件,比如libass就查找的是libass.pc这个文件。
从命令行模式进入到/usr/lib/和/usr/local/lib/下,查找是否有一个pkgconfig的文件夹,找到后,看是否有需要的哪个后缀名为pc的文件,如下图所示
执行export命令把这个路径export出来:
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig/
注意上述命令中是 /usr/lib/pkgconfig,而不是/usr/local/lib/pkgconfig,这个每个人的路径都不相同,不能设置错了。
编译后问题解决。
2,ERROR: libopenjpeg not found
http://code.google.com/p/openjpeg/downloads/detail?name=openjpeg-1.5.1.tar.gz&can=2&q=
下载openjpeg-1.5.1的代码,注意不要下载openjpeg-2.0的,否则ffmpeg跟openjpeg的接口不支持,编译会处错误。
./configure && make && sudo make install
找到头文件是在/usr/local/include/openjpeg-1.5.1下面,而ffmpeg在连接的时候,其实是/usr/local/include,所以提示说“ERROR: libopenjpeg not found”。将/usr/local/include/openjpeg-1.5.1下面的头文件“openjpeg.h”拷贝到/usr/local/include下面。
3,ERROR: libx264 not found
git clone https://github.com/ShiftMediaProject/x264.git
如果还是提示ERROR: libx264 not found,那跟openjpeg的情况类似,需要将x264.h这个文件要放在/usr/local/include下,而不是在/usr/local/下单独建个子目录放。其他的库都是在make install的时候自己建的子文件夹。
需要将libx264的库文件拷贝到/usr/local/lib下
或者直接在configure的时候,改变路径,如下所示:
./configure --includedir=/usr/local/include --libdir=/usr/local/lib --enable-shared
即可。
4,ERROR:libfdk_aac not found
https://sourceforge.net/projects/opencore-amr/files/fdk-aac/
下载fdk-aac-0.1.1.tar.gz
执行
./configure && make && sudo make install
5,ERROR: libopencore_amrnb not found
https://sourceforge.net/projects/opencore-amr/files/opencore-amr/
执行
./configure && make && sudo make install
6,ERROR: libvo-aacenc not found
https://sourceforge.net/projects/opencore-amr/files/vo-aacenc/
下载
执行
./configure && make && sudo make install
7,ERROR: vo-amrwbenc not found
https://sourceforge.net/projects/opencore-amr/files/vo-amrwbenc/
下载
执行
./configure && make && sudo make install
7,ERROR: libfaac not found
https://sourceforge.net/projects/faac/files/faac-src/
下载
执行
./configure && make && sudo make install
出现错误:
In file included from mp4common.h:29:0,
from atom_mvhd.cpp:22:
mpeg4ip.h:126:58: error: ambiguating new declaration of ‘char* strcasestr(const char*, const char*)’
char *strcasestr(const char *haystack, const char *needle);
^
In file included from mp4common.h:29:0,
from atom_stbl.cpp:22:
mpeg4ip.h:126:58: error: ambiguating new declaration of ‘char* strcasestr(const char*, const char*)’
char *strcasestr(const char *haystack, const char *needle);
8,ERROR:libilbc not found
https://github.com/dekkers/libilbc
git clone git://github.com/dekkers/libilbc.git
解压
安装cmake,如下所示
sudo apt-get install cmake
创建一个build目录,执行:
cd build
cmake .. (这里的..意思是,如果是一个.表示CMakeLists.txt在当前路径下,两个..表示CMakeLists.txt在上一层目录下)
cmake install ..
make (在build/bin下会找到可执行文件。)
make install (将生成的库拷贝到linux相关目录下)
9,ERROR: libvpx decoder version must be >=0.9.1
git clone https://github.com/webmproject/libvpx.git
./configure --enable-vp8 --enable-vp9 --enable-vp10 && make && sudo make install
如果编译过程中出现如下错误:
test/../nestegg/halloc/src/align.h:33:25: error: typedef redefinition with different types (‘union max_align‘ vs ‘long double‘)
typedef union max_align max_align_t;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/include/__stddef_max_align_t.h:32:21: note: previous
definition is here
typedef long double max_align_t;
^
那么vi test/../nestegg/halloc/src/align.h的第33行,注释掉当前行即可。
10,ERROR:libx265 not found
hg clone http://hg.videolan.org/x265
cd source
11,编译ffmpeg没有出现ffplay,这个是因为ffmpeg配置的时候需要支持sdl库,如图所示SDL没有探测到:
sudo apt-get install libsdl1.2-dev
或者
到 https://www.libsdl.org/download-2.0.php 下载SDL-1.2.15.tar.gz,注意这里不能下载SDL-2-2.0.4.tar.gz这个版本,因为ffmpeg目前只认SDL不认SDL2.0.
解压后执行:
./configure && make && sudo make install
可能在编译的时候会出现如下错误:
./src/video/quartz/SDL_QuartzVideo.h:94:5: error: unknown type name ‘CGDirectPaletteRef‘
vi ./src/video/quartz/SDL_QuartzVideo.h的94行,注释掉这个变量即可。
之后继续编译会出现以下错误:
./src/video/x11/SDL_x11sym.h:168:17: error: conflicting types for ‘_XData32‘
修改这个文件如下:
vi ./src/video/x11/SDL_x11sym.h 到168行
跳到168行,将
./configure && make && sudo make install
在ffmpeg中执行configure时可以看到如下SDL已经探测成功,编译完ffmpeg后ffplay产生,如图所示:
12 MAC环境下,在运行ffplay的时候,出现错误如下:
zzh:ffmpeg-3.1.2 zzh$ ./ffplay
dyld: Library not loaded: @rpath/libx265.89.dylib
Referenced from: /Users/zzh/work/workspace_ffmpeg/ffmpeg-3.1.2/./ffplay
Reason: image not found
Trace/BPT trap: 5
以下是解决办法:
(1)设置一个暂时的路径,DYLD_FALLBACK_LIBRARY_PATH。不太了解这个路径是做什么用的,看官网是这样的:DYLD_FALLBACK_LIBRARY_PATH
DYLD_FALLBACK_LIBRARY_PATH This is a colon separated list of directories that contain libraries. It is used as the default location for libraries not found in their install path. By default, it is set to $(HOME)/lib:/usr/local/lib:/lib:/usr/lib.
在/usr/lib或者/usr/local/lib下找libx265.89.dylib的路径,在命令行下设置如下路径,:
export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/lib
(2)然后运行,发现已经解决了。
./ffplay
ffplay version 3.1.2 Copyright (c) 2003-2016 the FFmpeg developers
built with Apple LLVM version 7.3.0 (clang-703.0.29)
configuration: --enable-static --enable-version3 --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-libilbc --enable-libvpx --enable-libx264 --enable-libopenjpeg --enable-pic --enable-libass --enable-libvpx --enable-libx265
libavutil 55. 28.100 / 55. 28.100
libavcodec 57. 48.101 / 57. 48.101
libavformat 57. 41.100 / 57. 41.100
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 47.100 / 6. 47.100
libswscale 4. 1.100 / 4. 1.100
libswresample 2. 1.100 / 2. 1.100
libpostproc 54. 0.100 / 54. 0.100
Simple media player
usage: ffplay [options] input_file
An input file must be specified
Use -h to get full help or, even better, run ‘man ffplay‘
13 ffmpeg: error while loading shared libraries: libavdevice.so.52: cannot open shared object file
Solution:
Search the file libavdevice.so.52 on the server using the ‘find’ command
1# find / -name libavdevice.so.52
You need to add the path to the directory the file is in, in the ‘ld.so.conf’ file. If for example the file is located under “/usr/local/lib” directory, execute
1# vi /etc/ld.so.conf
and add the following at the bottom of the file
/usr/local/lib
Save the file and for the new changes to take effect, execute
1
|
# ldconfig |
14 在编译opencv的时候报libvpx没有使用-fPIC来编译
Compilation fails with “relocation R_X86_64_32 against `.rodata.str1.8‘ can not be used when making a shared object”
14 运行ffplay的时候出现以下错误:
dyld: Library not loaded: /opt/local/lib/libiconv.2.dylib
Referenced from: /Users/baidu/work/workspace_ffmpeg/ffmpeg-3.1.2/./ffplay
Reason: Incompatible library version: ffplay requires version 8.0.0 or later, but libiconv.2.dylib provides version 7.0.0
Trace/BPT trap: 5
需要安装libiconv:
brew install homebrew/dupes/libiconv
如果无法下载成功,则可以手动下载,如下:
下载 https://ftpmirror.gnu.org/libiconv/libiconv-1.14.tar.gz
解压后,
configure && make && sudo make install
之后运行,还会报上面的错误,找不到/opt/local/lib/libiconv.2.dylib
在/usr/local/下找到 libiconv* 开头的库,拷贝到 /opt/local/lib下
运行ffplay,问题解决。
15 error while loading shared libraries: libilbc.so.1: cannot open shared object file: No such file or directory
(vpx_codec.c.o recompile with -fPIC
solution:
in libvpx:configure --enable-pic
in ffmpeg: configure --enable-pic
如上,先找到libilbc.so.1,然后将路径加入到/etc/ld.so.conf中。
1# cat /etc/ld.so.conf
/usr/local/lib /usr/local/lib/i386-linux-gnu/
16,relocation R_X86_64_32 against `.rodata.str1.1‘ can not be used when making a shared object; recompile with -fPIC
solution: ffmpeg configure add option: --enable-static
http://www.learndiary.com/2011/04/ubuntu-linux-下-ffmpeg-及-mencoder-安装使用小结/
近段时间在学习 Ffmpeg、Mencoder 音视频转换,大概在 Ubuntu 10.04、Ubuntu 10.10、Ubuntu Natty 测试版上安装和使用过。重点是针对低分辨率的普通手机视频,测试的手机为 Bird V780,主要参数为,视频编码:mpeg4、h263,音频编码:faac、amrnb,容器格式:mp4、3gp,分辨率:176×144;音乐文件格式:mp3 。下面对 Ubuntu Linux 下 Ffmpeg 及 Mencoder 安装使用作个小结。
1、安装:
安装 Ubuntu 软件仓库里的版本是很容易的,用 sudo apt-get install 命令就可以自动安装上。但是官方仓库里面的版本比较陈旧,可能缺失一些功能和存在一些 bug 没有解决,更重要的是,一些需要的编码支持没有被官方版本编译进去,如用于普通手机视频的 faac、amr 音频编码支持等。而且,两个软件官方网站均推荐使用其 svn 或 git 开发版本。所以,下面着重总结编译安装 ffmpeg 和 mencoder。
为了避免可能的冲突,在开始之前,我卸载了仓库版本的相关软件:sudo apt-get remove ffmpeg mencoder mplayer
获取 Ffmpeg 开发版本:git clone git://git.videolan.org/ffmpeg.git ffmpeg
获取 Mplayer 开发版本(包含了 mencoder):svn checkout svn://svn.mplayerhq.hu/mplayer/trunk mplayer
实际上 ./configure 配置 Mplayer 时会自动从 Ffmpeg 的开发库中下载 ffmpeg 最新开发版源码供编译 Mplayer 使用,因为 Mplayer 和 Mencoder 会调用 Ffmpeg 的库。而且,在当前的 Mplayer 编译中,如果没有特别设定,Mplayer 会把 Ffmpeg 的库编译成静态库编入 Mplayer 或 Mencoder 的二进制文件中,使这两个文件达到约14M左右。但是,我为了保险起见,编译 Ffmpeg 时就使用单独下载的源码。
通过事先的了解或在二者源码树下面执行 ./configure –help 得到配置帮助,得到编译额外编码支持库的信息,如:libfaac, libopencore_amrnb 等。你可以据此计划需要安装哪些额外编码库。
然后是根据你的需要安装额外编码库。在 Ubuntu 下,可以用 apt-get 安装那些库:如:
sudo apt-get install libx264-dev libxvidcore-dev libopencore-amrwb-dev libopencore-amrnb-dev libfaad-dev libfaac-dev libmp3lame-dev libtwolame-dev liba52-0.7.4-dev libcddb2-dev libcdaudio-dev libcdio-cdda-dev libvorbis-dev libopenjpeg-dev |
但是,在 configure ffmpeg 时,会报告:libx264 version must be >= 0.99
显然是 Ubuntu 中的 libx264 版本低了,那么 git clone git://git.videolan.org/x264.git
得到 x264 的源码再编译安装就行了。
当然,如果 Ubuntu 仓库中的版本不能满足你的需要,你可以选择从源码安装。更多的从源码安装编解码库的信息可以参考 Mplayer 相关文档。
另外,编译 ffplay 需要 libsdl1.2-dev 库:sudo apt-get install libsdl1.2-dev
下面进行 Ffmpeg 的编译安装。经过试验,也许是由于 Ubuntu 中的一个 bug,当存在仓库版本中的 libavutil、libavcodec、libavformat 等库时,编译安装的 ffmpeg 执行失败(比如报错:ffmpeg: relocation error: /opt/ffmpeg20110404/lib/libavfilter.so.1: symbol av_expr_free, version LIBAVUTIL_50 not defined in file libavutil.so.50 with link time reference),普通的 apt-get remove 不行,要连配置文件一起去掉,用 apt-get purge才行 (我在 Ubuntu 10.10 中发现,apt-get remove 后,仍存在 /usr/lib/i686/cmov/ 目录下面的相关文件)。如我使用了下面的命令彻底卸载了我认为有关的一些库:
sudo apt-get purge libavutil-dev libavutil50 libavutil-extra-50 libavcodec-dev libavcodec52 libavcodec-extra-52 libavformat-dev libavformat52 libavformat-extra-52 libavdevice-dev libavdevice52 libavdevice-extra-52 libavfilter-dev libavfilter1 libavfilter-extra-1 libswscale-dev libswscale0 libswscale-extra-0 libpostproc-dev libpostproc51 libpostproc-extra-51 gnome-desktop-environment |
最后那个 gnome-desktop-environment 如果不卸载掉,是无法同时卸载如:libavutil50 和 libavutil-extra-50 的,也无法清除掉 /usr/lib/i686/cmov 下面的内容,从而导致 ffmpeg 在 Ubuntu 中执行报错。
我看卸载了 gnome-desktop-environment 只是会卸载如:totem、gnash、sound-juicer 等并不是核心的组件,不会影响平常的使用。如果确实需要保留这些东西,我觉得可以试试把原来 ffmpeg 和 mplayer 的仓库版本文件强制删除,但在软件包管理系统中应该并没有被卸载的记录,再把 ffmpeg 和 mplayer 等安装在 /usr 标准目录下,用以替代原来的相应文件。不过,我没有试过。
下面配置 ffmpeg :
./configure --enable-nonfree --enable-gpl --enable-version3 --enable-shared --enable-postproc--enable-libmp3lame --enable-libopenjpeg --enable-libvorbis --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libxvid --enable-libx264 --enable-libfaac --enable-pthreads--prefix=/opt/ffmpeg20110404 |
然后,按照常规的 make, sudo make install 就完成了,双核电脑可以用 make -j 2 节省编译时间。
因为我将 ffmpeg 安装在了非标准目录,所以添加了库文件搜索设置(使用 root 权限):echo "/opt/ffmpeg20110404/lib" > /etc/ld.so.conf.d/ffmpeg.conf && ldconfig -v
下面配置 mplayer (mencoder):
在编译安装 mplayer 之前,在 Ubuntu 下要安装 libasound2-dev ,否则会因为缺少 alsa 的声音驱动而导致播放没有声音。
经过试验,mplayer 的配置比较自动化,configure 程序会搜索相关编码库文件,如果存在则会自动启用,而不用像 ffmpeg 那样必须像“–enable-libmp3lame”那样明确指定。不过,默认配置选项编译的 mplayer 是静态链接到它自带的 ffmpeg 源码中编译的静态链接库,这导致了 mplayer 或 mencoder 的二进制文件达到了 14M 左右。这可以通过禁用 ffmpeg 静态链接编译(–disable-ffmpeg_a)和告知 ffmpeg 的头文件和库文件位置( –extra-cflags=”-I/opt/ffmpeg20110404/include” –extra-ldflags=”-L/opt/ffmpeg20110404/lib”)来达到动态链接到已经安装完成的 ffmpeg 库文件的目的。同样,我把 mencoder 安装在了非标准目录,下面是我用的配置命令:
./configure --prefix=/opt/mplayer20110404 --disable-ffmpeg_a --extra-cflags="-I/opt/ffmpeg20110404/include" --extra-ldflags="-L/opt/ffmpeg20110404/lib" |
从 ./configure –help 中,与动态链接到 ffmpeg 库可能相关的参数有:–enable-rpath –disable-ffmpeg_a –enable-dynamic-plugins,但我只用了 –disable-ffmpeg_a 就完成了动态链接到 已经安装了的 ffmpeg 库的目的,也没有详细研究其它的参数了。
安装 ffmpeg 的 man 文档需要:sudo make install-man
与 ffmpeg 类似,编译安装完成后使用 root 权限执行:echo "/opt/mplayer20110404/lib" > /etc/ld.so.conf.d/mplayer20110404.conf && ldconfig -v
另外,如果不需要 ffmpeg 和 mplayer 中的一些组件(如: ffplay, mplayer),可以在 configure 中设定。具体查看: ./configure –help
然后,把 ffmpeg 和 mencoder 的可执行文件路径加入 PATH 环境变量,使用 root 权限执行:
echo "export PATH="/opt/ffmpeg20110404/bin:/opt/mplayer20110404/bin:$PATH"" >> /etc/profile |
2、使用
主要以转换成普通手机(以 Bird V780 为测试手机)可以播放的 176×144 分辨率的 3gp 或 mp4 文件为例,小结一下 ffmpeg 和 mencoder 的使用。
总的来说,ffmpeg 转换视频比 mencoder 更傻瓜化,只要指定了必要的参数,它就能产生能在手机上播放的 3gp 文件,如下:
ffmpeg -i test10s.avi -ar 8000 -ac 1 -ab 10.2k -s 176x144 -aspect 11:9 -b 200k -r 15outaspect.3gp #生成 h263+libopencore_amrnb 的 3gp 视频 |
ffmpeg -i test10s.avi -b 200k -r 15 -s 176x144 -aspect 11:9 -acodec libfaac -ac 2 -ar 44100 -ab 128k outfaac.3gp #生成 h263+libfaac 的 3gp 视频 |
但是用 Mencoder 转换,我使用的可工作的命令行为:
mencoder yyzs.rmvb -ss 160:0 -endpos 1:0 -of lavf -lavfopts format=mp4 -srate 44100 -vf-addcrop=440:360,scale=176:144,harddup -ofps 15 -oac faac -faacopts br=128:mpeg=4:object=2:raw -ovc lavc -lavcopts vcodec=mpeg4:aglobal=1:vglobal=1 -o yyzs17tt10.mp4 |
在 Bird V780上测试,其中缺了:br=128:mpeg=4:object=2:raw aglobal=1:vglobal=1 都不能播放,缺了 br=128:mpeg=4会变成6声道从而不能播放。但在 Bird V780 手机上不能播放并不能说明在其它手机或电脑上不能播放。因为可能是 mencoder 的 bug,到目前为止,libopencore_amrnb 音频编码的 3gp 视频不能正常转换,后面会详述。
Mencoder 的局限及解决方案
上面说过,因为可能是 mencoder 的 bug,到目前为止,libopencore_amrnb 音频编码的 3gp 视频不能正常转换。因为在我的测试中,转换成的 3gp 视频的音频长度比实际长度短了五分之四,下面的例子是 10 秒的音频被强制压缩成了 2 秒:
/usr/local/bin/mencoder -noconfig all -oac lavc -ovc lavc -lavcopts vcodec=h263:vbitrate=200:acodec=libopencore_amrnb:abitrate=10200 -of lavf -ofps 15 -srate8000 -vf scale=176:144 -af lavcresample=8000,channels=1,volnorm -otest10s.r33081.h263.openamrnb.3gp test10s.avi |
就算是把 mplayer 的版本换成原来的 1.0rc3,把 amr 的编码器换成旧的 libamr_nb 也是同样的效果。详见:MENCODER: Sound problems trying to convert from anything to 3gp w/amrnb: http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1603 。
解决方案暂时用 ffmpeg 来转换需要编码成 libopencore_amrnb 音频编码的视频。上面有一个相应的 ffmpeg 使用示例。
另外,Mencoder 不能直接把视频转换成只包含音频的音频文件,只能是视频转换到视频。解决方案有两个:
1)、使用 ffmpeg 转换,如下:
ffmpeg -i test.rmvb -vol 1000 test.mp3 |
上面那个 -vol 是为增加音量加的,不加这个参数默认的音量好像是 256。这个参数比较有用,在 mencoder 转换中好像控制音量只有一个 volnorm 声音滤镜参数(-af)用于在不失真的前提下最大化音量,而不能像 ffmpeg 这样有量化的增加音量(但增加过大声音可能会失真)。
2)、使用 mplayer 提取出 pcm 格式的音频,再选择其它工具转换成纯音频文件,如下面是转换成 mp3 的 shell 文件(其中使用了命名管道作为格式转换的中间传递,可以避免中间文件占用磁盘空间及加快处理过程):
#!/bin/bash # usage: tomp3.sh yyzs.rmvb 02:00:00 00:10:00 yyzs2h.mp3 tempfile=`mktemp` rm$tempfile mkfifo $tempfile /usr/bin/mplayer -ss $2 -endpos $3 -vc null -vo null -ao pcm:fast:waveheader:file=$tempfile $1 & lame $tempfile $4 rm $tempfile |
后台执行 mplayer 必须在脚本文件中执行,在终端中执行会出错如下:
问题:为什么从命令行终端直接执行如:” /usr/bin/mplayer -vc null -vo null yyzs.rmvb & “会报错:
mplayer: could not connect to socket mplayer: No such file or directory Failed to open LIRC support. You will not be able to use your remote control. ? |
也许你要问,既然 mencoder 转换视频音频这么多局限,为什么不使用其它工具,如 ffmpeg 直接进行转换呢?答案就是与 mplayer 被称为 Linux 世界的万能播放器有关,通过支持闭源的 dll 等第三方解码库,mplayer 几乎可以播放世面上的所有音频视频格式文件,包括那些封闭的特殊格式。mencoder 和 mplayer 同用一个解码库,理论上(还没有碰到实践中的意外)只要 mplayer 能够播放,mencoder 就能进行解码从而进行格式转换。尽管网上有说法说 mencoder 的代码很滥,但是它却是 Linux 世界的其它转换工具无法替代的,包括 ffmpeg。
Ffmpeg 的局限
尽管 ffmpeg 转换音频、视频比较方便,而且据说速度还非常快,但其中有一个非常显著的局限,而且这个局限是设计理念造成的。就是 ffmpeg 不支持第三方封装的编解码器,致力于提供原生的编解码器,详见 ffmpeg 文档的 FAQ: http://www.ffmpeg.org/faq.html#SEC5 :
1.4 FFmpeg does not support codec XXX. Can you include a Windows DLL loader to support it? No. Windows DLLs are not portable, bloated and often slow. Moreover FFmpeg strives to support all codecs natively. A DLL loader is not conducive to that goal. |
比如下面的 2 个文件,用 ffmpeg 就不能正常转换格式:
FullMetal[wmv+AAC]_remux-006.mkv ffplay播放、ffmpeg编码图像花
niceday.wmv 主要约有两处ffplay播放、ffmpeg编码图像花
而用 mencoder 进行转码,用 mplayer 播放上面 2 个源文件效果无误。但需要把额外的解码器 wmvdomd.dll 放入 codecs 解码器目录,否则出现与 ffplay 播放相同的问题。
取长补短,综合运用 mencoder 和 ffmpeg 进行音频视频转换
使用命令行工具有一个好处就是可以用脚本把不同的命令行工具结合起来完成某一个任务。下面针对几种情况小结一下。
1)、音频转换
从试验的结果,单纯的音频转换完全使用 ffmpeg 即可,因为即使是视频文件中的视频部分有问题,音频部分却是可以被 ffmpeg 正常解码从而转换成纯音频文件(我的试验中还没有碰到不能转换的)。
示例命令: ffmpeg -i niceday.wmv niceday.mp3
2)、转换成 mencoder 支持的编码格式(如:不需要转换成 libopencore_amrnb 音频编码的视频格式)
鉴于 mencoder 解码格式的全面性,直接用 mencoder 转换。
3)、转换成 mencoder 不支持但是 ffmpeg 支持的编码格式(如:libopencore_amrnb 音频编码的视频格式)
可以直接用 ffmpeg 转换;如果 ffmpeg 不能正常解码,可以先用 mencoder 转换成中间格式,再用 ffmpeg 由中间格式转换成最终格式,示例如下:
#!/bin/bash # usage: convert3gp.sh yyzs.rmvb yyzs10.3gp 02:00:00 00:10:00 # usage: convert3gp.sh 原视频 目的视频 开始时间点 持续时间 echo "`date`: convert3gp.sh $1 $2 $3 $4 begin.">> timerec.log tempfile=`mktemp` rm $tempfile tempfile=$tempfile.mkv mkfifo $tempfile mencoder -ss $3 -endpos $4 -noconfig all -oac pcm -ovc lavc -lavcopts vcodec=h263:vbitrate=200 -of lavf -lavfopts format=mkv -ofps 15 -vf scale=176:144 -o$tempfile $1 & #经试验,avi 的中间格式和未指定容器格式的默认情况,好像有时会出错, #像这样使用 mkv 中间格式的情况还没出现过异常。 #mencoder -ss $3 -endpos $4 -noconfig all -oac pcm -ovc raw #-vf format=yuy2 -o $tempfile $1 & #中间格式可以使用 raw video,但是转换时间要长一些。 #部分RV40 的视频导出raw video 用默认的格式为黑白颜色, #要把格式指定为其它的格式如 -vf format=yuy2 才行 ffmpeg -y -i$tempfile -vcodec h263 -b 200k -r 15 -s 176x144 -aspect 11:9 -acodec libopencore_amrnb -ac 1-ar 8000 -ab 10.2k -f 3gp $2 #虽然在中间格式中已经转换成了 h263 的视频部分,但如果不重新指定相关参数, #转换成的视频文件会出现“[h263 @ 0x14f81c0]warning: first frame is no #keyframe”的问题,从而导致在定位视频时出现花屏的现象。 #ffmpeg -y -i $tempfile -vcodec h263 -b 200k -r 15 -s 176x144 #-aspect 11:9 -acodec libfaac -ac 2 -ar 44100 -ab 128k -f 3gp $2 rm $tempfile echo `date` >> timerec.logexit 0 |
转换速度及质量问题
在相同的环境下作了一个测试,转换一个 rmvb 文件6分钟的视频,目的视频是可以在 Bird V780 上播放的 176×144 3gp 文件,视频编码采用 h263,音频编码采用 faac。脚本及测试记录见附件:速度测试,下面是结果比较:
名称 比特率 转换时间 区别 ffmpegonly.3gp 336Kbps 3‘22" 只用 ffmpeg 转换,加 -async 1 参数; menonly.3gp 321Kbps 2‘52" 只用 mencoder 转换,harddup 视频滤镜,-oac faac 音频编码; menonly2.3gp 321Kbps 2‘40" 只用 mencoder 转换,harddup 视频滤镜,-oac lavc -ovc lavc -lavcopts acodec=libfaac 音频编码; intermkv.3gp 336Kbps 2‘47" mencoder 和 ffmpeg 结合转换,mencoder 无 harddup 视频滤镜,使用结果视频参数,ffmpeg 指定视频详细参数 -vcodec h263 -b 200k -r 15 -s 176x144 -aspect 11:9; intermkv2.3gp 336Kbps 2‘47" mencoder 和 ffmpeg 结合转换,mencoder 加 harddup 视频滤镜,使用结果视频参数,ffmpeg 指定视频详细参数 -vcodec h263 -b 200k -r 15 -s 176x144 -aspect 11:9; intermkv3.3gp 322Kbps 2‘37" mencoder 和 ffmpeg 结合转换,mencoder 加 harddup 视频滤镜,使用结果视频参数,ffmpeg 未指定视频详细参数 -vcodec copy,缺失关键帧错误导致定位时花屏; interraw.3gp 336Kbps 3‘56" mencoder 和 ffmpeg 结合转换,mencoder 无 harddup 视频滤镜,使用 raw 视频,ffmpeg 指定视频详细参数 -vcodec h263 -b 200k -r 15 -s 176x144 -aspect 11:9; interraw2.3gp 336Kbps 4‘03" mencoder 和 ffmpeg 结合转换,mencoder 加 harddup 视频滤镜,使用 raw 视频,ffmpeg 指定视频详细参数 -vcodec h263 -b 200k -r 15 -s 176x144 -aspect 11:9 |
从测试结果可知:
1)、只用 mencoder 转换时,采用 lavc 中 faac (libfaac) 的音频编码 menonly2.sh 比直接采用 faac 音频编码 menonly.sh 快 12 秒;
2)、采用 ffmpeg、mencoder 两步转换的 intermkv2.sh 比只采用 mencoder 的 menonly2.sh 慢 7 秒;
3)、只采用 ffmpeg 转换 ffmpegonly.sh 比只采用 mencoder 的 menonly2.sh 慢 42 秒,比采用 ffmpeg、mencoder 两步转换的 intermkv2.sh 慢 35 秒;
4)、转换中,mencoder 加与未加 harddup 视频滤镜转换时间几乎无差别;
5)、采用 ffmpeg、mencoder 两步转换时,采用 raw 视频中间格式的 interraw2.sh 比采用结果视频中间视频格式的 intermkv2.sh 慢 76 秒;
6)、采用 ffmpeg、mencoder 两步转换时,当采用结果视频中间视频格式,ffmpeg 重新指定视频编码详细参数的 intermkv2.sh 比直接使用 -vcodec copy 的 intermkv3.sh 慢 10 秒,但是直接使用 -vcodec copy 会出现缺失关键帧错误导致定位时花屏。
因为转换视频是用于普通手机播放的低分辨率视频,从转换结果和比特率和直观观看来说看不出明显的质量差别。
初步来看,如果遇到 ffmpeg 无法识别原始文件格式但能编码成目的格式,而 mencoder 无法编码成目的格式但能识别原始文件格式时,使用二者结合转换手机低分辨率视频是可行的。在我进行 rmvb 到 3gp 的转换测试中,这种结合转换比纯粹使用 mencoder 约慢,但还比纯粹使用 ffmpeg 转换时快不少。估计是 ffmpeg 解码 rmvb 文件时的效率没有 mencoder 高的缘故吧。
其它问题
1)、在转换宽银幕电影到手机视频的过程中,为了使画面的主要内容更加清晰,可以先截去两边超宽的部分再进行转换,在 mencoder 中可以使用 crop 视频滤镜处理,例如原始为 640×360 的 16:9 ,要转换成 176×144 的 11:9,可以使用视频滤镜 -vf-add crop=440:360,scale=176:144 达到效果;
2)、在 ffmpeg 中,如果只截取中间一段转换进行转换,将 “-i 原始文件名“ 放在 “-ss 开始时间 -t 持续时间“ 的后面并且加上 “-async 1(避免音画不同步)” 可以避免搜索不需要转换的部分而浪费的大量时间。例如,在我的测试中,E7400 双核电脑上,如果转换一部2个半小时电影中2小时以后的10分钟内容,真正转换的时间只用大约1分钟,而如果把 “-i 原始文件名“ 放在 “-ss 开始时间 -t 持续时间“ 的前面,则要增加大约10分钟的定位搜索时间!详见:question about “Buffering several frames is not supported. Please consume all available frames before adding a new one.”
3)、因为多次的测试,上面的命令不一定是同一次的安装,例如有时安装在 /usr/local 下面,有时是安装在 /opt/ 下面等;而且,版本也不一定是同一版本,但命令应该是至少可以在最近的版本中通用的(2011年4月左右)。
结论:
像这种非经济驱动的开源工具,也许不一定像一些闭源的商业工具自成体系的较为完整的功能,但可以通过脚本把各种各有所长的开源命令行工具结合在一起,从而完成任务。以上内容和观点仅供参考,欢迎交流。
以上是关于ffmpeg在PC上编译问题全解决的主要内容,如果未能解决你的问题,请参考以下文章
ffmpeg neon 在 android 上编译 - 汇编错误
运行./configure时在Windows上编译FFmpeg错误
mac上编译雷神的《最简单的基于FFMPEG+SDL的视频播放器-最终版》代码