在做音视频的项目当中,常常遇到音视频不同步,编码和解码的出错的等等问题,这时候就需要将对应出问题的视频数据给dump下来进行分析,使用ffmpeg的各种工具能够更好的分析对应的音视频的文件。
ffmpeg
ffmpeg工具功能非常强大,主要用于音视频转码。
使用规则是:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
1.流说明符
stream_index
表示流的编号,是从0开始的,一般使用的时候都是配合streamType进行使用的。
示例
比如-codec:a :1 ac3,表示指定第二路音频流使用ac3进行编码,不指定stream_index的话,就表示所有的流,-b:a 128k,表示指定所有的音频流都用128k的码率,-codec copy 或者-codec:copy则表示将只是将流复制,并没有重新编码
stream_type
p:program_id[:stream_index] or p:program_id[:stream_type[:stream_index]] or p:program_idⓂ️key[:value]"
第一种情况,匹配指定的stream_index流;
第二种情况,匹配指定的stream_type和指定的stream_index的流;
第三种情况,匹配指定metadata的流
m:key[:value]
跟指定了metadata的key和value的流进行匹配,value没有给出的话,匹配有对应的key的流。
u
跟可用配置的流进行匹配。
2.通用选项
这些选项都在ff*的工具都通用
-L
显示证书
-h,-?,-help,–help [arg]
帮助说明
arg的取值
arg取值 说明
-version
显示版本
-formats、-demuxers、-muxers、-devices、-codecs、-decoders、-encoders、-bsfs、-protocols、-filters、-pix_fmts、-sample_fmts、-layouts-colors、-sources device[,opt1=val1[,opt2=val2]…]、-sinks device[,opt1=val1[,opt2=val2]…]
上面参数都显示类的,都是显示可用的参数,bsfs是bitstream fitlers
-loglevel [flags+]loglevel | -v [flags+]loglevel
loglevel有如下的值
-report
将所有的日志给dump下来,文件名字规则为program-YYYYMMDD-HHMMSS.log
-hide_bander
压制打印的banner
-cpuflags flags
3.主要的选项
-f fmt (input/output)
指定输入输出的格式
-i url (input)
输入的文件格式
-y (global)
不在询问的重写输出文件
-n (global)
不重写输出文件
-stream_loop number(input)
设置输入的流是否需要循环,Loop 0表示不loop,loop -l表示无限loop
-c[:stream_specifier] codec (input/output,per-stream)
-codec[:stream_specifier] codec (input/output,per-stream)
指定转码的编码器
ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT
-map 0表示对所有的视频流都生效,-c:v 表示指定视频流的编码器,-c:a 表示对音频流的只是复制而已。
ffmpeg -i INPUT -map 0 -c copy -c:v:1 libx264 -c:a:137 libvorbis OUTPUT
-t duration (input/output)
表示限制读取的数据的时间长度
-to position (input/output)
表示停止读取源文件的位置
-fs limit_size (output)
显示输出文件的大小
-ss position (input/output)
指定输入或者输出文件的起始位置
-sseof position (input)
指定输入文件的结束位置
-itsoffset offset (input)
设置输入文件的时间偏移
-timestamp date (output)
设置录制的时间戳
-metadata[:metadata_specifier] key=value (output,per-metadata)
添加输入文件的metadata信息
ffmpeg -i in.avi -metadata title="my title" out.flv
ffmpeg -i INPUT -metadata:s:a:0 language=eng OUTPUT
-disposition[:stream_specifier] value (output,per-stream)
设置流的配置
下面有流的配置
default
dub
original
comment
lyrics
karaoke
forced
hearing_impaired
visual_impaired
clean_effects
attached_pic
captions
descriptions
dependent
metadata
示例
设置第二路音频流为默认的流
ffmpeg -i in.mkv -c copy -disposition:a:1 default out.mkv
-program [title=title:][program_num=program_num:]st=stream[:st=stream…] (output)
创建指定的项目
-target type (output)
设置输出的文件类型
vcd, svcd, dvd, dv, dv50等等类型,有可能要使用这些格式前缀pal-, ntsc- or film-
示例
ffmpeg -i myfile.avi -target pal-vcd /tmp/vcd.mpg
-dn (output)
不转码data数据
-dframes number (output)
设置data数据的帧率
-frames[:stream_specifier] framecount (output,per-stream)
设置达到某个帧数,然后停止转码
-q[:stream_specifier] q (output,per-stream)
-qscale[:stream_specifier] q (output,per-stream)
用来解决高质量的转码
-filter[:stream_specifier] filtergraph (output,per-stream)
使用指定的滤镜效果,filtergraph是过滤器图
-filter_script[:stream_specifier] filename (output,per-stream)
和上面的参数一致
-filter_threads nb_threads (global)
定义处理filter的线程数
-pre[:stream_specifier] preset_name (output,per-stream)
设置流的预先配置
-stats (global)
打印转码的状态日志
-progress url (global)
将处理进度打印到文件当中
-stdin
开启标准输入输出
-debug_ts (global) 或者-fdebug ts
打印转码时间戳,用来测试或者debug的
-attach filename (output)
添加一个附属的文件到输出文件中
ffmpeg -i INPUT -attach DejaVuSans.ttf -metadata:s:2 mimetype=application/x-truetype-font out.mkv
-dump_attachment[:stream_specifier] filename (input,per-stream)
将附属文件给dump下来
ffmpeg -dump_attachment:t:0 out.ttf -i INPUT
3.视频的选项
-vframes number (output)
设置输出文件的帧数
-r[:stream_specifier] fps (input/output,per-stream)
设置输出的帧率
-s[:stream_specifier] size (input/output,per-stream)
设置输出文件的大小,这里是等比例缩放的
-aspect[:stream_specifier] aspect (output,per-stream)
设置输出文件视频宽高比例
-vn (output)
不开视频转码
-vcodec codec (output)或者-codec:v
设置视频编码的编码器
-pass[:stream_specifier] n (output,per-stream)
选择pass的数量
ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y NUL
ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y /dev/null
-passlogfile[:stream_specifier] prefix (output,per-stream)
设置pass的log文件
-vf filtergraph (output)
设置转码的变换的规则
//按照宽高最小值进行视频的转码为240p
ffmpeg -i output_p_540.mp4 -vf scale="floor(iw/min(iw\,ih)*240/2)*2:floor(ih/min(iw\,ih)*240/2)*2" output_p_480.mp4
4.高级的视频转码选项
-pix_fmt[:stream_specifier] format (input/output,per-stream)
设置输入或者输出的的pix_fmt,可以用-pix_fmts显示可用的pix_fmt
-sws_flags flags (input/output)
设置图片变换的flags
-rc_override[:stream_specifier] override (output,per-stream)
指定帧率控制的间隔
-ilme
强制编码器的交错支持
-psnr
计算PSNR即压缩后的视频质量
-vstats
dump转码的日志,到 vstats_HHMMSS.log中
-vstats_file file
dump转码的日志到指定的文件
-vstats_version file
version = 1 :
frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s
version > 1:
out= %2d st= %2d frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s
-top[:stream_specifier] n (output,per-stream)
top=1/bottom=0/auto=-1 field first
-dc precision
内部精度
-vtag fourcc/tag (output)
强制将视频为四字节代码???
-qphist (global)
显示QP的柱形图
-force_key_frames[:stream_specifier] time[,time…] (output,per-stream)
-force_key_frames[:stream_specifier] expr:expr (output,per-stream)
强加关键帧到指定时间戳
-copyinkf[:stream_specifier] (output,per-stream)
stream copy的时候,同时将不是第一个关键帧,前面的所有帧都拷贝过去
-init_hw_device type[=name][:device[,key=value…]]
-init_hw_device type[=name]@source
初始化硬编码设备
-init_hw_device list
查看ffmpeg支持的硬编码设备
-filter_hw_device name
通过硬编码设备调用指定的滤镜
-hwaccel[:stream_specifier] hwaccel (input,per-stream)
使用硬件加速去解码流
-hwaccel_device[:stream_specifier] hwaccel_device (input,per-stream)
选择一个设备去进行硬件加速
-hwaccels
列举FFmpeg支持的硬件加速
5.音频的选项
-aframes number (output)
设置输出的音频帧数
-ar[:stream_specifier] freq (input/output,per-stream)
设置音频的采样率
-aq q (output)
设置音频的质量
-ac[:stream_specifier] channels (input/output,per-stream)
设置音频的channel count
-an (output)
关闭音频的转码
-acodec codec (input/output)或者-codec:a
设置音频硬编码器
-sample_fmt[:stream_specifier] sample_fmt (output,per-stream)
设置采样的格式
-af filtergraph (output)
设置音频的转码的滤镜
6.高级音频的选项
-atag fourcc/tag (output)或者-tag:a
强制音频的选项
-guess_layout_max channels (input,per-stream)
猜测音频的channel
7.字幕选项
-scodec codec (input/output)
设置字幕的编码器
-sn (output)
不开启字幕转码
8.高级字幕选项
-fix_sub_duration
解决字幕时间
-canvas_size size
设置字幕显示的画布大小
9.高级选项
map [-]input_file_id[:stream_specifier][?][,sync_file_id[:stream_specifier]] | [linklabel] (output)
指定一个或者更多的输入的流输出到文件中
第一个-map选项,对应输出文件的流0,第二个-map选项,对应输出文件的流1,以此类推。
[-]选项,是指除了指定流以外的所有流
?选项,允许匹配到流
安排所有流从输入到输出文件
ffmpeg -i INPUT -map 0 output
假如有2路音频流在输入文件中,这些流都被指定为0:0 或者0:1,用-map来选择哪路流配置到输出文件中,下面是设置第2路音频流,到音频流中
ffmpeg -i INPUT -map 0:1 out.wav
选择第一个文件的index为2的流,并选择第二个文件的index为6的流到,输出文件中
ffmpeg -i a.mov -i b.mov -c copy -map 0:2 -map 1:6 out.mov
选择所有的视频流和第3路音频流到输出文件
ffmpeg -i INPUT -map 0:v -map 0:a:2 OUTPUT
选择除了第二路音频流的所有的流,都到输出文件中
ffmpeg -i INPUT -map 0 -map -0:a:1 OUTPUT
选择所有的视频流和音频流,假如这个文件没有音频流也没有问题
ffmpeg -i INPUT -map 0:v -map 0:a? OUTPUT
选择英文的音频流
ffmpeg -i INPUT -map 0:m:language:eng OUTPUT
-ignore_unknown
忽略未知类型的流拷贝错误
-copy_unknown
忽略拷贝流失败
map_channel [input_file_id.stream_specifier.channel_id|-1][?][:output_file_id.stream_specifier]
-1 是可以选择静音声道
选择输出的音频的声道
? 可以不匹配到声道
示例
假如输入文件是立体声道音频文件,通过下面命令变成双声道的音频文件
ffmpeg -i INPUT -map_channel 0.0.1 -map_channel 0.0.0 OUTPUT
静音第一个声道并且保持第二个声道
ffmpeg -i INPUT -map_channel -1 -map_channel 0.0.1 OUTPUT
-map_metadata[:metadata_spec_out] infile[:metadata_spec_in] (output,per-metadata)
设置输出文件的metadata
metadata可以由下面的表单
g
全局metadata
s[:stream_spec]
流index的metadata
c:chapter_index
每个chapter的metadata
p:program_index
每个program的metadata
示例
拷贝输入文件的第一路流的metadata到输出文件的全局metadata
ffmpeg -i in.ogg -map_metadata 0:s:0 out.mp3
拷贝全局的metadata到音频流中
ffmpeg -i in.mkv -map_metadata:s:a 0:g out.mkv
-map_chapters input_file_index (output)
从输入文件拷贝chapters到下个输出文件
-benchmark (global)
显示编码结束标记
-benchmark_all (global)
显示标记信息在编码中
-timelimit duration (global)
在某个时间点退出FFmpeg
-dump (global)
dump所有的输入到到文件中
-hex (global)
dump文件是,同时dump payload
-re (input)
输出的帧率和输入的文件保持一致
-loop_output number_of_times
重复这个文件,比如像gif文件
-vsync parameter
视频同步方法
parameter的取值
0, passthrough
从解复用直接传递到复用中去
1, cfr
帧会复用并且丢弃去达到指定的帧率
2,vfr
帧会直接按照时间戳传递过去,并且丢弃区具有相同时间戳的视频数据帧
drop
所有的帧都传递过去,但是基于新的帧率得到新的时间戳
-1, auto
依赖复用器的能力,选择1到2之间
-frame_drop_threshold parameter
丢帧的界限
-async samples_per_second
音频同步的方法
-copyts
不处理输入的时间戳,保持它们的值不收损害
-start_at_zero
当使用上面的选项,变化输入的文件的时间戳,所以他们其实时间为0
-copytb mode
在流拷贝的时候,设置编码器的时间基点
1
使用解复用的时间基点
0
使用解码器的时间基点
-1
自动选择时间基点,保证一个正常的输出
-enc_time_base[:stream_specifier] timebase (output,per-stream)
设置编码器的时间基点
0
设置一个默认的时间基点值
-1
尽量使用出入流的时间基点
'> 0
使用指定的值作为时间基点
-bitexact (input/output)
启动位精确模式,给解复用器和复用器
-shortest (output)
使用最短的流进行编码
-dts_delta_threshold
时间戳不连续的阈值
-muxdelay seconds (input)
设置最大的解码延迟
-muxpreload seconds (input)
设置初始化解码延迟
-streamid output-stream-index:new-value (output)
赋值一个新的流id的值到输出流中
ffmpeg -i inurl -streamid 0:33 -streamid 1:36 out.ts
-bsf[:stream_specifier] bitstream_filters (output,per-stream)
设置位流的滤镜给匹配的流
ffmpeg -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264
ffmpeg -i file.mov -an -vn -bsf:s mov2textsub -c:s copy -f rawvideo sub.txt
-tag[:stream_specifier] codec_tag (input/output,per-stream)
在指定的加个tag
-timecode hh:mm:ssSEPff
设置指定的时间点去写入
ffmpeg -i input.mpg -timecode 01:02:03.04 -r 30000/1001 -s ntsc output.mpg
-filter_complex filtergraph (global)
定义复杂的滤镜器图
覆盖一张图到视频上面
ffmpeg -i video.mkv -i image.png -filter_complex '[0:v][1:v]overlay[out]' -map
'[out]' out.mkv
[0:v]连接到第一个视频流在第一个输入的文件,连接到第一个输入输入的覆盖滤镜。
假设这里只有一个视频流的输入文件,我们可以删除输入的标志,所以上面等同于
ffmpeg -i video.mkv -i image.png -filter_complex 'overlay[out]' -map
'[out]' out.mkv
此外,我们可以忽略输出的标记和单个输出到滤镜器,并自动添加到输出文件。
ffmpeg -i video.mkv -i image.png -filter_complex 'overlay' out.mkv
完成5s的纯红视频,可以只用颜色源
ffmpeg -filter_complex 'color=c=red' -t 5 out.mkv
-filter_complex_threads nb_threads (global)
定义多少个线程进行滤镜的处理,默认的数值是CPU的位数
-lavfi filtergraph (global)
定义一个复杂的滤镜器图
-filter_complex_script filename (global)
这个选项同-filter_complex,唯一不同的是从文件进行读取规则
-accurate_seek (input)
这个选项开启和关闭精确的seeking,配合-ss选项,并使用-noaccurate_seek进行关闭
-seek_timestamp (input)
这个选项是开启或者关闭通过时间戳进行seeking
-thread_queue_size size (input)
这个选项设置最大的数据队列,当读取文件或者设备的时候,要低延时和高码率的直播流,数据包可能会被丢弃,当没有及时被读取到,提高这个值可以避免发送这种情况。
-sdp_file file (global)
打印sdp的信息到输出的流
-discard (input)
允许丢弃指定的流或者帧在解复用的时候
none
不丢弃任何帧
default
默认,不丢帧
noref
丢所有非参考帧
bidir
丢所有双向预测帧
nokey
丢了除了关键帧之外的所有帧
all
丢所有的帧
-xerror (global)
出错是停止
-max_muxing_queue_size packets (output,per-stream)
编码的时候,设置复用的包的队列的大小
硬编字幕在DVB-T记录到MPEG-TS格式,延时字幕为1s钟
ffmpeg -i input.ts -filter_complex \
'[#0x2ef] setpts=PTS+1/TB [sub] ; [#0x2d0] [sub] overlay' \
-sn -map '#0x2dc' output.mkv
11.例子
11.1 音视频抓取
如果你指定输入的格式和设备,FFmpeg能够直接抓取视频或者音频
ffmpeg -f oss -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg
或者使用ALSA的音频输入源替代OOS
ffmpeg -f alsa -ac 1 -i hw:1 -f video4linux2 -i /dev/video0 /tmp/out.mpg
11.2 X11抓取
通过x11显示进行抓取
ffmpeg -f x11grab -video_size cif -framerate 25 -i :0.0 /tmp/out.mpg
0.0是显示屏的坐标X11 Server,和DISPLAY环境变量相似
ffmpeg -f x11grab -video_size cif -framerate 25 -i :0.0+10,20 /tmp/out.mpg
11.3 音视频文件格式变换
使用YUV文件作为输入源
ffmpeg -i /tmp/test%d.Y /tmp/out.mpg
这会使用这些文件
/tmp/test0.Y, /tmp/test0.U, /tmp/test0.V,
/tmp/test1.Y, /tmp/test1.U, /tmp/test1.V, etc...
使用原始YUV420P的文件
ffmpeg -i /tmp/test.yuv /tmp/out.avi
输出YUV420P文件
ffmpeg -i mydivx.avi hugefile.yuv
设置各自输入文件和输出文件
ffmpeg -i /tmp/a.wav -s 640x480 -i /tmp/a.yuv /tmp/a.mpg
可以做音频和视频转换
ffmpeg -i /tmp/a.wav -ar 22050 /tmp/a.mp2
同一时间进行几种格式的转换
ffmpeg -i /tmp/a.wav -map 0:a -b:a 64k /tmp/a.mp2 -map 0:a -b:a 128k /tmp/b.mp2
从视频里面截取图片
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
通过使用-frames:v或者-t ,进行限制输出的帧数,或者通过-ss仅仅想视频视频
ffmpeg -f image2 -framerate 12 -i foo-%03d.jpeg -s WxH foo.avi
当导入一个图片集合,-i 同时可以支持的
ffmpeg -f image2 -pattern_type glob -framerate 12 -i 'foo-*.jpeg' -s WxH foo.avi
可以将多路相同的流,放到输出文件中
ffmpeg -i test1.avi -i test2.avi -map 1:1 -map 1:0 -map 0:1 -map 0:0 -c copy -y test12.nu
强制输出CBR视频输出
ffmpeg -i myfile.avi -b 4000k -minrate 4000k -maxrate 4000k -bufsize 1835k out.m2v
四个选项Imin,Imax,mblmin和mblmax使用‘lambda’单元
ffmpeg -i src.ext -lmax 21*QP2LAMBDA dst.ext
12.实际项目使用的命令
AAC转PCM文件
ffmpeg -i input.aac -f s16le -ar 44100 -acodec pcm_s16le output.pcm
PCM文件转AAC
ffmpeg -f s16le -ar 44100 -ac 2 -acodec pcm_s16le -i input. output.wav
FFmpeg推拉流命令
//推流本地文件到服务器
ffmpeg -re -i /Users/xu/Desktop/bangbangbang.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/home
//本地桌面录制或者分享
ffmpeg -f avfoundation -i "1" -vcodec libx264 -preset ultrafast -acodec libfaac -f flv rtmp://localhost:1935/rtmplive/home
//桌面+麦克风
ffmpeg -f avfoundation -i "1:0" -vcodec libx264 -preset ultrafast -acodec libmp3lame -ar 44100 -ac 1 -f flv rtmp://localhost:1935/rtmplive/home
//桌面+麦克风+摄像头
ffmpeg -f avfoundation -framerate 30 -i "1:0" \-f avfoundation -framerate 30 -video_size 640x480 -i "0" \-c:v libx264 -preset ultrafast \-filter_complex 'overlay=main_w-overlay_w-10:main_h-overlay_h-10' -acodec libmp3lame -ar 44100 -ac 1 -f flv rtmp://localhost:1935/rtmplive/home
FFmpeg的视频分辨率转换公式
ffmpeg -i output_p_540.mp4 -vf scale="floor(iw/min(iw\,ih)*240/2)*2:floor(ih/min(iw\,ih)*240/2)*2" output_p_480.mp4
FFmpeg进行转码
ffmpeg -i input_ac3.mp4 -vcodec copy -acodec aac -f flv output.flv