FFmpeg常用基本命令

  Rov      2015-05-10   

FFmpeg常用基本命令

1、  分离视频流

说明:单独分离出电影中的视频流

命令:ffmpeg –i input_file(*.mp4;*.avi;…) –vcodec copy –an output_file_video


2、  分离音频流

说明:单独分离出电影中的音频流

命令:ffmpeg –i input_file(*.mp4;*.avi;…) –vcodec copy –vn output_file_audio


3、  视频解复用

说明:

命令:ffmpeg –i input_file(*.mp4;*.avi;…) –vcodec copy –an –f m4v output_file.264


4、  视频转码

说明:对视频进行转码操作

命令:

转码为码流原始文件:

   1:ffmpeg –i input_file(*.mp4;*.avi;…) –vcode h264 –s 352*278 –an –f m4v output_file.264

   2:ffmpeg –i input_file(*.mp4;*.avi;…) –vcode h264 –bf 0 –g 25 –s 352*278 –an –f m4v output_file.264

转码为封装文件:

      ffmpeg –i input_file(*.mp4;*.avi;…) –vcode mpeg4 –vtag xvid –qsame output_file.avi

参数说明:-bf B帧数目控制, -g 关键帧间隔控制, -s 分别率控制


5、  视频封装

说明:对单视频文件和音频文件进行封装(合并)

命令:ffmpeg –i video_file –i audio_file –vcodec copy –acodec copy output_file


6、  视频剪切

说明:对视频进行分割或截取处理

命令:

1:图片提取(将视频输出为图片)

  Ffmpeg –i input_video_file(*.mp4;*.avi;…) –r 24 –f image2 image-%3d.jpeg(*.jpeg;*.png;*.tiff;….)

2:剪切视频

  Ffmpeg –ss 0:1:15 –t 0:0:50 –i input_video_file(*.mp4;*.avi;…) –vcodec copy –acodec copy output_file(*.mp4;*.avi;…)

参数说明:-r 提取图像的帧率,-ss 截取开始时间,-t 截取视频长度


7、  视频录制

说明:

命令:ffmpeg –I rtsp://192.168.3.205:5555/test –vcodec copy output_file.avi


8、  YUV序列播放

说明:以YUV序列播放视频

命令:ffplay –f rawvideo –video_size 1920×1080 input.YUV


9、  YUV序列转AVI

说明:将YUV序列转换成avi视频

命令:ffmpeg –s w*h –pix_fmt yuv420p –I input.yuv –vcodec mpeg4 output_file.avi


10、 音频转换指定参数

说明:将原音频文件转换为24位深度音频

命令:ffmpeg –i input_file(*.mp3;*.wav;*.dts;…) –acodec pcm_s24le output_file(*.mp3;*.wav;*.dts;…)

其他:pcm_s16be、pcm_s16be_planar、pcm_s16le、pcm_sle_planar、pcm_s24be、pcm_s24daud、pcm_s24le、pcm_s24le_planar、pcm_s32be、pcm_s32le、pcm_s32le_planar、pcm_s8、pcm_s8_planar、pcm_u16be、pcm_u16le、…


11、 输出tiff序列

ffmpeg -f rawvideo -r 24 -s 1920x1080 -i j:\out_ViewId0000.yuv -s 1998x1080 -f image2 d:\Video\tiff-left\l-%06d.tif


12、将MXF返回avi格式

ffmpeg -loglevel debug -vcodec libopenjpeg -i Test.mxf -vcodec mpeg4 -b 15000k Test.avi


13、 提取视频中的字幕

ffmpeg -i xxx -vn -an -scodec copy sub.ass


14、 其他说明

主要参数说明:

-i 设定输入流;

-f  设定输出格式;

-ss 设定开始时间;


视频处理参数:

     -b 设定视频流量,默认为:200kbit/s

     -r 设定帧速率,默认为25帧

     -s 设定画面的宽与高

     -aspect 设定画面的比例

     -vn 不处理视频

     -vcodec 设定视频编码、解码器,未设定时则使用与输入流相同的编码、解码器


音频处理参数:

     -ar 设定采样率

     -ac 设定声音的Channel数(通道数)

     -acodec 设定声音编码、解码器,未设定时则使用与输入流相同的编码、解码器

     -an 不处理音频

14、分割视频

ffmpeg -ss 01:00:00 -i input_file_h264.mp4 -vcodec copy -acodec copy -t 00:06:00 output_file.mp4

其中

-ss 表示分割视频开始时间

时间单位为小时:分:秒

-i 输入文件

input_file_h264.mp4 表示要分割的视频

-vcodec copy 复制视频编码

-acodec copy 复制音频编码

-t 表示从开始分割到分割结束整个分割视频的时间

output_file.mp4 表示分割后的视频

15、ffmpeg格式

ffmpeg [[options][`-i' input_file]]... {[options] output_file}...

如果没有输入文件,那么视音频捕捉(只在Linux下有效,因为Linux下把音视频设备当作文件句柄来处理)就会起作用。作为通用的规则,选项一般用于下一个特定的文件。如果你给 –b 64选项,改选会设置下一个视频速率。对于原始输入文件,格式选项可能是需要的。缺省情况下,ffmpeg试图尽可能的无损转换,采用与输入同样的音频视频参数来输出。

16、 流复制:复制文件的流,只更改容器(文件)格式。

./ffmpeg –v debug –i inputfile.mpg –c copy  -f asf outfile.asf

-f:设置混合器

-c:设置编码器。当为 copy:指复制编码流

-i:输入文件

-v:调试信息级别(quiet、panic、fatal、error、warning、info、verbose、debug)

17、指定流:

一个容器里可以包含许多流,包括任何的音视频流。那么在命令行怎样区分流呢?

答:由“:”进行分隔

./ffmpeg –i inputfile.mpg –c:v h263 –c:a g722 –f asf outfile.asf

./ffmpeg –i inputfile.mpg –c:0 h263 –c:1 g722 –f asf outfile.asf

上面命令表示把输入文件 inputfile文件的视频流转换成h263格式,把音频流转换成g722格式。

v:视频

a:音频

数字:表示第几路,从0开始

 Ffmpeg选项详解

18、ffmpeg –help来获得选项内容

19、通用选项

-L license

-h 帮助

-fromats显示可用的格式,编解码的,协议的

-codecs 显示可用的编解码器

-bsfs     显示bit流过滤器

-protocols显示可用的协议

-pix_fmts显示可用的位图格式

-sample_fmts显示可用的音频采样格式

-loglevel loglevel set libav* logging level

-v loglevel        set libav* logging level

-debug flags       set debug flags

-fdebug flags      set debug flags

-report            generate a report

-f fmt强迫采用格式fmt

-i filename输入文件

-y 覆盖输出文件

-c编解码器名字

-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持

-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持

-timestamp time 设置记录时间戳(‘now’指定当前时间)

-title string 设置标题

-author string 设置作者

-copyright string 设置版权

-comment string 设置评论

20、视频选项

-vframes number     设置记录的视频帧数

-r rate            设置帧率 (Hz value, fraction or abbreviation)

-s size            设置帧的大小 (WxH or abbreviation)

-aspect aspect      set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)

-bits_per_raw_sample number  set the number of bits per raw sample

-croptop size       Removed, use the crop filter instead

-cropbottom size    Removed, use the crop filter instead

-cropleft size      Removed, use the crop filter instead

-cropright size     Removed, use the crop filter instead

-padtop size        Removed, use the pad filter instead

-padbottom size     Removed, use the pad filter instead

-padleft size       Removed, use the pad filter instead

-padright size      Removed, use the pad filter instead

-padcolor color     Removed, use the pad filter instead

-vn               禁用视频

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

-sameq              use same quantizer as source (implies VBR)

-same_quant         use same quantizer as source (implies VBR)

-timecode hh:mm:ss[:;.]ff  set initial TimeCode value.

-pass n             select the pass number (1 or 2)

-passlogfile prefix  select two pass log file name prefix

-vf filter list     video filters

-b bitrate         video bitrate (please use -b:v)

-dn                 disable data

21、高级视频选项

-pix_fmt format     设置位图格式

-intra              deprecated use -g 1

-vdt n              discard threshold

-rc_override override  rate control override for specific intervals

-deinterlace        this option is deprecated, use the yadif filter instead

-psnr               calculate PSNR of compressed frames

-vstats             dump video coding statistics to file

-vstats_file file   dump video coding statistics to file

-intra_matrix matrix  specify intra matrix coeffs

-inter_matrix matrix  specify inter matrix coeffs

-top                top=1/bottom=0/auto=-1 field first

-dc precision       intra_dc_precision

-vtag fourcc/tag    force video tag/fourcc

-qphist             show QP histogram

-force_fps          force the selected framerate, disable the best supported framerate selection

-force_key_frames timestamps  force key frames at specified timestamps

-vbsf video bitstream_filters  deprecated

-vpre preset        set the video options to the indicated preset

22、音频选项

-aframes number    设置帧频数

-aq quality         设置音频质量(编解码器专用)

-ar rate            设置音频采样率(以Hz为单位)

-ac channels        通道设置

-an               禁用音频

-acodec codec      音频编解码器(“copy”来复制数据流编码)

-vol volume        音量增减音量(256=正常)

-af filter list        音频过滤器

23、音频/视频捕获选项

-vc channel         deprecated, use -channel

-tvstd standard     deprecated, use -standard

-isync              sync read on input

-vd device 设置视频捕获设备。比如/dev/video0

-dv1394 设置DV1394捕获

-av device 设置音频设备比如/dev/dsp

24、高级选项

-cpuflags flags     force specific cpu flags

-map [-]input_file_id[:stream_specifier][,sync_file_id[:stream_s  set input stream mapping

-map_channel file.stream.channel[:syncfile.syncstream]  map an audio channel from one stream to another

-map_chapters input_file_index  set chapters mapping

-benchmark          add timings for benchmarking

-benchmark_all      add timings for each task

-progress url       write program-readable progress information

-dump               dump 每个输入包

-hex                当 dumping包时,也dump其荷载

-re                 read input at native frame rate

-vsync              video sync method

-async              audio sync method

-adrift_threshold threshold  audio drift threshold

-copyts             copy timestamps

-copytb mode        copy input stream time base when stream copying

-shortest           finish encoding within shortest input

-dts_delta_threshold threshold  timestamp discontinuity delta threshold

-dts_error_threshold threshold  timestamp error delta threshold

-copyinkf           copy initial non-keyframes

-q q                use fixed quality scale (VBR)

-qscale q           use fixed quality scale (VBR)

-profile profile    set profile

-filter_complex graph_description  create a complex filtergraph

-debug_ts           打印调试信息时间戳

-streamid streamIndex:value  set the value of an outfile streamid

-muxdelay seconds   set the maximum demux-decode delay

-muxpreload seconds  set the initial demux-decode delay

-fpre filename      set options from indicated preset file

25、截取一张352x240尺寸大小的,格式为jpg的图片:

ffmpeg -i test.asf -y -f image2 -t 0.001 -s 352x240 a.jpg

26、把视频的前30帧转换成一个Animated Gif

ffmpeg -i test.asf -vframes 30 -y -f gif a.gif

27、截取指定时间的缩微图

ffmpeg -i test.avi -y -f image2 -ss 8 -t 0.001 -s 350x240 test.jpg

-ss后跟的时间单位为秒

28、转换文件为3GP格式

ffmpeg -y -i test.mpeg -bitexact -vcodec h263 -b 128 -r 15 -s 176x144

-acodec aac -ac 2 -ar 22500 -ab 24 -f 3gp test.3gp

29、使用ffmpeg录像屏幕

ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -vd x11:0,0 -s 1024x768 ~/test.avi

:其中,-vd x11:0,0指录制所使用的偏移为 x=0和 y=0,-s 1024×768指录制视频的大小为 1024×768。录制的视频文件为 test.avi,将保存到用户主目录中

如果你只想录制一个应用程序窗口或者桌面上的一个固定区域,那么可以指定偏移位置和区域大小。使用xwininfo -frame命令可以完成查找上述参数。

重新调整视频尺寸大小

ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -i ~/test.avi -s 800×600 ~/test-800-600.avi

注:上面的ffmpeg的屏幕录制功能只能在Linux环境下有效。在windows下是否可行,本人还不知道如何操作,如果你知道,请告诉我J

30、把摄像头的实时视频录制下来,存储为文件

在windows有两种视频捕获方式,使用VFW或DSHOW,你需要在编译ffmpeg时,把相应的组件编译进libavdevice中,下面使用vfw方式捕获:

./ffmpeg -t 10 -f vfwcap -i 0 -r 25 -f asf cap.asf

我们采集10秒,采集设备为vfwcap类型设备,第0个vfwcap采集设备(如果系统有多个vfw的视频采集设备,可以通过-i num来选择),每秒25帧,输出方式为文件,格式为asf

在Linux平台上,ffmpeg对V4L2的视频设备提高了很好的支持,如:

./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 8 -i /dev/video0 -vcodec h263 -f rtp rtp://192.168.1.105:5060 > /tmp/ffmpeg.sdp

以上命令表示:采集10秒钟视频,对video4linux2视频设备进行采集,采集QCIF(176*144)的视频,每秒8帧,视频设备为/dev/video0,视频编码为h263,输出格式为RTP,后面定义了IP地址及端口,将该码流所对应的SDP文件重定向到/tmp/ffmpeg.sdp中,将此SDP文件上传到流媒体服务器就可以实现直播了。

./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 10 -vpre libx264-hq.ffpreset -i /dev/video0 -vcodec libx264 -f rtp rtp://192.168.1.105:6060 > /tmp/x264.sdp

这条命令与上面的类似,但是视频编码为h264,由于ffmpeg是用外部库x264支持h264编码,因此h264的视频采集需要更多参数。主要是需要指定-vpre libx264-hq.ffpreset 才可以。

下面命令则是把捕获到的视频保存成文件:

ffmpeg  -f video4linux -s 320*240 -r 10 -i /dev/video0  test.asf

31、接收组播直播流,并保存成文件:

./ffmpeg -i udp://@ip:port  test.ts

32、从文件生成直播流:

ffmpeg  -i  a.flv  -f  flv  rtmp://IP/livepkgr/livestream?adbe-live-event=liveevent

IP是你的fms服务器的IP地址

33、从组播地址接收组播,并把它转成rtmp协议发给 fms服务器

ffmpeg  –i  udp://@:port  –f  flv  rtmp://IP/livepkgr/livestream?adbe-live-event=liveevent

34、对流进行分片(支持hls协议)

ffmpeg  -I  a.asf  -codec  copy  -map  0  -f  segment-segment_list  out.m3u8 out%03d.tss

1 音频转换

ffmpeg -i my_audio.wav  my_audio.mp3

-i 后为要转换的音频文件,my_audio.mp3为目的音频文件

2 视频转换

ffmpeg -i my_video.mpeg -s 500×500 my_video.flv

-i 后为源视频文件, -s 表示设置目标视频文件的分辨率   my_video.flv为目的视频文件

3

从视频中截取图片

ffmpeg -i test.mpg image%d.jpg

默认1s截取25张图片,可以通过-r设置每秒截取的图片数量

-r fps 设置帧率,也就是每秒截取图片的数量(默认25)

ffmpeg -i test.mpg -r 1 image%d.jpg

这样子每1s截取1张图片

还可以设置截取间隔,起止

-ss 设定时间位置,语法:hh:mm:ss[.xxx]

-t 时长:限制转码/捕获视频的时间,语法:hh:mm:ss[.xxx]

ffmpeg -i test.mpg -r 25 -ss 00:00:10 -t 00:00:05 images%05d.png

在第10秒开始,以每秒截取25张图片的速度,截取5秒时长的图片

4 从视频中采集音频

ffmpeg -i video.avi -f mp3 audio.mp3

-f 强制选择格式

ffmpeg -i video.avi -vn audio.mp3

-vn 取消截取视频(也就是只输出音频文件)

5 创建截屏视频

ffmpeg -f x11grab -r 25 -s wxga -i :0.0 /tmp/outputFile.mpg

0.0 是你X11 server的屏幕显示号吗,和DISPLAY一样样的.

此条命令以每秒25帧的速率来截取wxga屏幕视频,当然这里可以用-s 来设置视频分辨率,输出文件是/tmp/outputFile.mpg

6

用图片制作视频

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

将`img001.jpg’, `img002.jpg'这种顺序排列的图片文件转制作为视频

7

从webcam中截取视频

ffmpeg -f video4linux2 -s 320x240 -i /dev/video0 out.mpg

同时截取音频和视频:

ffmpeg -f oss -i /dev/dsp -f video4linux2 -s 320x240 -i /dev/video0 out.mpg

/dev/video0为视频设备 /dev/dsp为音频设备


例子:ffmpeg -y -i "d:\video\a1.avi" -title "Test" -vcodec xvid -s 368x208 -r 29.97 -b 1500 -acodec aac -ac 2 -ar 24000 -ab 128 -vol 200 -f psp -muxvb 768 "d:\video\a2.wmv"


解释:以上命令可以在Dos命令行中输入,也可以创建到批处理文件中运行。不过,前提是:要在ffmpeg所在的目录中执行(转换君所在目录下面的cores子目录)。

参数:

-y覆盖输出文件,即如果 output.wmv 文件已经存在的话,不经提示就覆盖掉-i "1.avi"输入文件是和ffmpeg在同一目录下的1.avi文件,可以自己加路径,改名字-title "Test"在PSP中显示的影片的标题-vcodec xvid使用XVID编码压缩视频,不能改的-s 368x208输出的分辨率为368x208,注意片源一定要是16:9的不然会变形-r 29.97帧数,一般就用这个吧-b 1500视频数据流量,用-b xxxx的指令则使用固定码率,数字随便改,1500以上没效果;还可以用动态码率如:-qscale 4和-qscale 6,4的质量比6高-acodec aac音频编码用AAC-ac 2声道数1或2-ar 24000声音的采样频率,好像PSP只能支持24000Hz-ab 128音频数据流量,一般选择32、64、96、128-vol 200200%的音量,自己改-muxvb 768好像是给PSP机器识别的码率,一般选择384、512和768,我改成1500,PSP就说文件损坏了-f psp输出psp专用格式"output.wmv"输出文件名,也可以加路径改文件名

示例1:

截取一张352x240尺寸大小的,格式为jpg的图片:

ffmpeg -i test.asf -y -f image2 -t 0.001 -s 352x240 a.jpg

示例2:

把视频的前30帧转换成一个Animated Gif :

ffmpeg -i test.asf -vframes 30 -y -f gif a.gif

示例3:

在视频的第8.01秒处截取 352*240 的缩略图

ffmpeg -i test2.asf -y -f image2 -ss 08.010 -t 0.001 -s 352x240 b.jpg

**************************************************************************************

a) 通用选项


-L license


-h 帮助


-fromats 显示可用的格式,编解码的,协议的。。。


-f fmt 强迫采用格式fmt


-I filename 输入文件


-y 覆盖输出文件


-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持


-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持


-title string 设置标题


-author string 设置作者


-copyright string 设置版权


-comment string 设置评论


-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置 ,只需要输入如下的就可以了:

ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg


-hq 激活高质量设置


-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持


b) 视频选项


-b bitrate 设置比特率,缺省200kb/s


-r fps 设置帧频 缺省25


-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:

Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576


-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777


-croptop size 设置顶部切除带大小 像素单位


-cropbottom size –cropleft size –cropright size


-padtop size 设置顶部补齐的大小 像素单位


-padbottom size –padleft size –padright size –padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)


-vn 不做视频记录


-bt tolerance 设置视频码率容忍度kbit/s


-maxrate bitrate设置最大视频码率容忍度


-minrate bitreate 设置最小视频码率容忍度


-bufsize size 设置码率控制缓冲区大小


-vcodec codec 强制使用codec编解码方式。 如果用copy表示原始编解码数据必须被拷贝。


-sameq 使用同样视频质量作为源(VBR)


-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率


-passlogfile file 选择两遍的纪录文件名为file



c)高级视频选项


-g gop_size 设置图像组大小


-intra 仅适用帧内编码


-qscale q 使用固定的视频量化标度(VBR)


-qmin q 最小视频量化标度(VBR)


-qmax q 最大视频量化标度(VBR)


-qdiff q 量化标度间最大偏差 (VBR)


-qblur blur 视频量化标度柔化(VBR)


-qcomp compression 视频量化标度压缩(VBR)


-rc_init_cplx complexity 一遍编码的初始复杂度


-b_qfactor factor 在p和b帧间的qp因子


-i_qfactor factor 在p和i帧间的qp因子


-b_qoffset offset 在p和b帧间的qp偏差


-i_qoffset offset 在p和i帧间的qp偏差


-rc_eq equation 设置码率控制方程 默认tex^qComp


-rc_override override 特定间隔下的速率控制重载


-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full


-dct_algo algo 设置dct的算法 可用的有 0 FF_DCT_AUTO 缺省的DCT 1 FF_DCT_FASTINT 2 FF_DCT_INT 3 FF_DCT_MMX 4 FF_DCT_MLIB 5 FF_DCT_ALTIVEC


-idct_algo algo 设置idct算法。可用的有 0 FF_IDCT_AUTO 缺省的IDCT 1 FF_IDCT_INT 2 FF_IDCT_SIMPLE 3 FF_IDCT_SIMPLEMMX 4 FF_IDCT_LIBMPEG2MMX 5 FF_IDCT_PS2 6 FF_IDCT_MLIB 7 FF_IDCT_ARM 8 FF_IDCT_ALTIVEC 9 FF_IDCT_SH4 10 FF_IDCT_SIMPLEARM


-er n 设置错误残留为n 1 FF_ER_CAREFULL 缺省 2 FF_ER_COMPLIANT 3 FF_ER_AGGRESSIVE 4 FF_ER_VERY_AGGRESSIVE


-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)


-bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4


-mbd mode 宏块决策 0 FF_MB_DECISION_SIMPLE 使用mb_cmp 1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD


-4mv 使用4个运动矢量 仅用于mpeg4


-part 使用数据划分 仅用于mpeg4


-bug param 绕过没有被自动监测到编码器的问题


-strict strictness 跟标准的严格性


-aic 使能高级帧内编码 h263+


-umv 使能无限运动矢量 h263+


-deinterlace 不采用交织方法


-interlace 强迫交织法编码 仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大


-psnr 计算压缩帧的psnr


-vstats 输出视频编码统计到vstats_hhmmss.log


-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开


d)音频选项


-ab bitrate 设置音频码率


-ar freq 设置音频采样率


-ac channels 设置通道 缺省为1


-an 不使能音频纪录


-acodec codec 使用codec编解码


e)音频/视频捕获选项


-vd device 设置视频捕获设备。比如/dev/video0


-vc channel 设置视频捕获通道 DV1394专用


-tvstd standard 设置电视标准 NTSC PAL(SECAM)


-dv1394 设置DV1394捕获


-av device 设置音频设备 比如/dev/dsp



f)高级选项


-map file:stream 设置输入流映射


-debug 打印特定调试信息


-benchmark 为基准测试加入时间


-hex 倾倒每一个输入包


-bitexact 仅使用位精确算法 用于编解码测试


-ps size 设置包大小,以bits为单位


-re 以本地帧频读数据,主要用于模拟捕获设备


-loop 循环输入流。只工作于图像流,用于ffserver测试


FFMpeg 中比较重要的函数以及数据结构如下:


1. 数据结构:


(1) AVFormatContext


(2) AVOutputFormat


(3) AVInputFormat


(4) AVCodecContext


(5) AVCodec


(6) AVFrame


(7) AVPacket


(8) AVPicture


(9) AVStream


2. 初始化函数:


(1)av_register_all()


(2) avcodec_open()


(3) avcodec_close()


(4)av_open_input_file()


(5)av_find_input_format()


(6)av_find_stream_info()


(7)av_close_input_file()


3. 音视频编解码函数:


(1)avcodec_find_decoder()


(2)avcodec_alloc_frame()


(3)avpicture_get_size()


(4)avpicture_fill()


(5) img_convert()


(6) avcodec_alloc_context()


(7)avcodec_decode_video()


(8)av_free_packet()


(9) av_free()


4. 文件操作:


(1) avnew_steam()


(2) av_read_frame()


(3)av_write_frame()


(4) dump_format()


5. 其他函数:


(1)avpicture_deinterlace()


(2)ImgReSampleContext()


(3)sws_setColorspaceDetails()


以下就根据,以上数据结构及函数在ffmpeg测试代码output_example.c中出现的前后顺进行分析。


交待完毕进入正题。


一.FFMpeg 中的数据结构:  


I. AVFormatContext


一般在使用ffmpeg sdk的代码中AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。FFmpeg代码中对这个数据结构的注释是:format I/O context 此结构包含了一个视频流的格式内容。其中存有了AVInputFormat(or AVOutputFormat同一时间AVFormatContext内只能存在其中一个),和AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。还有一些可能在编解码中会用到的信息,诸如:duration, file_size, bit_rate等。参考avformat.h头文件。


Useage:


声明:


AVFormatContext*oc; (1)


初始化:由于AVFormatConext结构包含许多信息因此初始化过程是分步完成,而且有些变量如果没有值可用,也可不初始化。但是由于一般声明都是用指针因此一个分配内存过程不可少:


oc =av_alloc_format_context(); (2)


结构中的AVInputFormat*(或AVOutputFormat*)是一定要初始化的,基本上这是编译码要使用什么codec的依据所在:


oc->oformat =fmt; or oc->iformat = fmt; (3)


其中AVOutputFormat* fmt或AVInputFormat* fmt。(AVInputFormat and AVOutputFormat的初始化在后面介绍。随后在参考代码output_example.c中有一行:


snprintf(oc-filename,sizeof(oc->filename), “%s”, filename); (4)


还不是十分清楚有什么作用,估计是先要在输出文件中写一些头信息。




在完成以上步骤後,(初始化完毕AVInputFormat*(或AVOutputFormat*)以及AVFormatContext)接下来就是要利用oc初始化本节开始讲到的AVFormatContext中的第二个重要结构。AVStream(假设已经有了声明AVStream *video_st。参考代码用了一个函数来完成初始化,当然也可以在主函数中做,传递进函数的参数是oc和fmt->video_codec(这个在下一节介绍(29)):


vdeo_st =add_video_stream(oc, fmt->video_codec); (5)


此函数会在后面讲到AVStream结构时分析。


AVFormatContext最后的一个设置工作是:


if(av_set_paramters(oc,NULL) < 0){ (6)


//handle error;


}


dump_format(oc, 0,filename, 1); (7)


作用就是看看先前的初始化过程中设置的参数是否符合规范,否则将报错。


上面讲的都是初始化的过程,包括AVFormatContext本身的和利用AVFormatContext初始化其他数据结构的。接下来要讲讲整个的编解码过程。我想先将ouput_example.c中main函数内的编解码函数框架描述一下。这样比较清晰,而且编码者为了结构清晰,在写ouput_example.c的过程中也基本上在main函数中只保持AVFormatContext和AVStream两个数据结构




(AVOutputFormat其实也在但是包含在AVFormatContext中了)。


// open video codecand allocate the necessary encode buffers


if(video_st)


open_video(oc,video_st); (8)


// write the streamheader, if any


av_write_header(oc);(9)


// encode anddecode process


for(; ;){


write_video_frame(oc,video_st); (10)


// breakcondition…here


}


//close codec


if(video_st)


close_video(oc,video_st); (11)


//write the trailer, if any


av_write_trailer(oc);(12)


// free the streams


for(i=0;i<oc->b_streams; i++){


av_freep(&oc->streams[i]->codec);(13)


av_freep(&oc->streams[i]);(14)


}


//close the ouputfile


if(!(fmt->flags& AVFMT_NOFILE)){


url_fclose(&oc->pb);(15)


}


av_free(oc); (16)


通过以上的一串代码,就可以清晰地看出AVFormatContex* oc和AVStream* video_st是在使用ffmpeg SDK开发时贯穿始终的两个数据结构。以下,简要介绍一下三个标为红色的函数,他们是参考代码output_example.c开发者自行定义的函数。这样可以使整个代码结构清晰,当然你在使用ffmpeg SDK时也可以在主函数中完成对应的功能。在后面我们会专门针对这三个函


数做分析。


1. open_video(oc,video_st);


此函数主要是对视频编码器(或解码器)的初始化过程。初始化的数据结构为AVCodec* codec和AVCodecContext* c包括用到了的SDK函数有:


c = st->codec;


codec =avcodec_find_encoder(c->codec_id); //编码时,找编码器 (17)


codec =avcodec_find_decoder(c->codec_id); //解码时,找解码器 (18)




AVCodecContex是结构AVStream中的一个数据结构,因此在AVStream初始化後(5)直接复值给c。


// internal openvideo codec


avcodec_open(c,codec);(19)


// allocate videostream buffer


// AVFrame *picture


// uint8_t*video_outbuf


video_outbuf_size=200000;


video_outbuf =av_maloc(video_outbuf_size); (20)


// allocate videoframe buffer


picture =alloc_picture(c->pix_fmt, c->width, c->height); (21)


上述三步比较容易理解,打开视频编解码codec、分配输出流缓存大小、分配每一帧图像缓存大小。其中AVFrame也是ffmpeg中主要数据结构之一。这一步(8)是对编解码器的初始化过程。


2.write_video_frame(AVFormatContext *oc, AVStream *st)


这个函数中做了真正的编解码工作,其中的函数比较复杂先列出来慢慢分析。


用到的数据结构有AVCodecContext *c, SwsContext*img_convert_ctx。其中SwsContext是用来变换图像格式的。比如yuv422变到yuv420等,当然也用到函数,见下面列表。


fill_yuv_image(tmp_picture,frame_count, c->width, c->height); (22)


sws_scale(img_convert_ctx,tmp_picture->, tmp_picture->linesize,


0, c->height,picture->data, picture->linesize); (23)


img_convert_ctx =sws_getContxt(c->width, c->height, PIX_FMT_YUV420P, (24)


c->width,c->heigth, c->pix_fmt, sws_flags, NULL, NULL, NULL);




由于参考代码中做的是一个编码。因此,它总是要求编码器输入的是yuv文件,而且是yuv420格式的。就会有了以上一些处理过程。接下来调用编码器编码,数据规则化(打包)用到AVPacket,这也是ffmpeg中一个比较不好理解的地方。


out_size =avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); (25)


AVPacket pkt;


av_init_packet(&pkt);(26)


//……handle pktprocess, we will analyze later


ret =av_write_frame(oc, &pkt); (27)


有encode就一定会有decode。而且ffmpeg专为解码而生,但是为什么在参考代码中只用了encoder呢?个人猜想是因为encode只是用yuv420来编码,这样的yuv420生成比较容易,要是用到解码的化,还要在代码中附带一个其他格式的音视频文件。在源代码libavcodec文件夹中有一个apiexample.c的参考代码,其中就做了编解码。有空的化我会分析一下。


3.close_video(AVFormatContext *oc, AVStream *st)


avcodec_close(st->codec);


av_free(picture->data[0]);


av_free(picture);


av_free(video_outbuf);




比较容易理解,不多说了。


以上一大段虽然名为介绍AVFormatContext。但基本上把ouput_example.c的视频编码部分的框架走了一遍,其一是想说明结构AVFormatContext的重要性,另一方面也是希望对使用FFMpeg SDK开发者有一个大致的框架。


其实,真正的一些编码函数,内存分配函数在SDK中都已经封装好了,只要搞清楚结构就能用了。而开发者要做的就是一些初始化的过程,基本上就是针对数据结构1的初始化。




II. AVOutputFormat


虽然简单(初始化)但是十分重要,他是编解码器将要使用哪个codec的“指示”。在其成员数据中最重要的就是关于视频




codec的了:enum CodecID video_codec;


AVOutputFormat*fmt;


fmt =guess_format(NULL, filename, NULL); (28)


根据filename来判断文件格式,同时也初始化了用什么编码器。当然,如果是用AVInputFormat *fmt的化,就是fix用什么解码器。(指定输出序列->fix编码器,指定输入序列->fix解码器?)


III. AVStream


AVStream作为继AVFormatContext後第二个贯穿始终的结构是有其理由的。他的成员数据中有AVCodecContext这基本的上是对所使用的Video Codec的参数进行设定的(包括bit rate、分辨率等重要信息)。同时作为“Stream”,它包含了“流”




这个概念中的一些数据,比如:帧率(r_frame_rate)、基本时间计量单位(time_base)、(需要编解码的)首帧位置(start_time)、持续时间(duration)、帧数(nb_frames)以及一些ip信息。当然后面的这些信息中有些不是必须要初




始化的,但是AVCodecContex是一定要初始化的,而且就是作为初始化AVStream最重要的一个部分。我们在前面就谈到了AVStream的初始化函数(5),现在来看看他是怎么做的:


// declaration


AVStream *video_st;


video_st =add_video_stream(oc, fmt->video_codec);


static AVStream*add_video_stream(AVFormatContex *oc, int codec_id){ (29)


AVCodecContext *c;// member of AVStream, which will be initialized here


AVStream *st; //temporary data, will be returned


st = av_new_stream(oc,0); (30)


c = st->codec;


// 以下基本是针对c的初始化过程。包括比特率、分辨率、GOP大小等。


……


// 以下的两行需要注意一下,特别是使用MP4的


if(!strcmp(oc->oformat->name,“mp4”) || !strcmp(oc->oformat->name, “mov”) ||!strcmp(oc->oformat->name, “3gp”))


c->flags |=CODEC_FLAG_GLOBAL_HEADER;


// 将st传给video_st;


return st;


}


以上代码中,有几点需要注意的。一个是(30)和c = st->codec是一定要做的,当然这是编程中最基本的问题,(30)是将st这个AVSteam绑定到AVFormatContext* oc上。后面的c = st->codec是将c绑定到st的AVCodecContext上。其二是对c的初始化过程中,ouput_example.c里做的是一些基本的配置,当然作为使用者的你还希望对codec加入其他的一些编解码的条件。


可以参考avcodec.h里关于AVCodecContext结构的介绍,注释比较详细的。关于AVStream的使用在前面介绍AVFormatContext时已有所涉及,在主函数中三个编解码函数中(8)、(10)和(11)中。观察相关的代码,可以发现主要还是将AVStream中的AVCodecContext提取出来,再从中提取出AVCodec结构如在(8)中:


// open_video(oc,video_st);


// AVFormatContext*oc, AVStream *st


AVCodec *codec;


AVCodecContext *c;


c = st->codec;


codec =avcodec_find_encoder(c->codec_id); (31)


// open the codec


avcodec_open(c,codec); (32)




同样,我们可以看到在(10)(write_video_frame())中AVFrame也是做为传递AVCodecContext结构的载体而存在。(11)




(close_video())比较简单,不熬述。


IV. AVCodecContext


此结构在Ffmpeg SDK中的注释是:main external apistructure其重要性可见一斑。而且在avcodec它的定义处,对其每个成员变量,都给出了十分详细的介绍。应该说AVCodecContext的初始化是Codec使用中最重要的一环。虽然在前面的AVStream中已经有所提及,但是这里还是要在说一遍。AVCodecContext作为Avstream的一个成员结构,必须要在Avstream初始化後(30)再对其初始化(AVStream的初始化用到AVFormatContex)。虽然成员变量比较多,但是这里只说一下在output_example.c中用到了,其他的请查阅avcodec.h文件中介绍。


// static AVStream*add_video_stream(AVFormatContext *oc, int codec_id)


AVCodecContext *c;


st =av_new_stream(oc, 0);


c = st->codec;


c->codec_id =codec_id;


c->codec_type =CODEC_TYPE_VIDEO;


c->bit_rate =400000; // 400 kbits/s


c->width = 352;


c->height = 288;// CIF


// 帧率做分母,秒做分子,那么time_base也就是一帧所用时间。(时间基!)


c->time_base.den= STREAM_FRAME_RATE;


c->time_base.num= 1;


c->gop_size =12;


// here define:


// #defineSTREAM_PIX_FMT PIX_FMT_YUV420P


// pixel format,see PIX_FMT_xxx


// -encoding: setby user.


// -decoding: setby lavc.


c->pix_fmt =STREAM_PIX_FMT;


除了以上列出了的。还有诸如指定运动估计算法的: me_method。量化参数、最大b帧数:max_b_frames。码率控制的参数、差错掩盖error_concealment、模式判断模式:mb_decision (这个参数蛮有意思的,可以看看avcodec.h 1566行)、Lagrange multipler参数:lmin & lmax 和宏块级Lagrange multipler参数:mb_lmin & mb_lmax、constant quantization parameterrate control method: cqp等。值得一提的是在AVCodecContext中有两个成员数据结构:AVCodec、AVFrame。AVCodec记录了所要使用的Codec信息并且含有


5个函数:init、encoder、close、decode、flush来完成编解码工作(参见avcode.h 2072行)。AVFrame中主要是包含了编码後的帧信息,包括本帧是否是key frame、*data[4]定义的Y、Cb和Cr信息等,随后详细介绍。


初始化後,可以说AVCodecContext在(8)&(10)中大显身手。先在(8)open_video()中初始化AVCodec *codec以及AVFrame*


picture:


// AVCodecContext*c;


codec =avcodec_find_encoder(c->codec_id);


……


picture =alloc_picture(PIX_FMT_YUV420P, c->width, c->height);


後在writer_video_frame(AVFormatContext*oc, AVStream *st)中作为一个编解码器的主要参数被利用:


AVCodecContext *c;


c = st->codec;


……


out_size =avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);


V.AVCodec


结构AVCodec中成员变量和成员函数比较少,但是很重要。他包含了CodecID,也就是用哪个Codec、  像素格式信息。还有前面提到过的5个函数(init、encode、close、decoder、flush)。顺便提一下,虽然在参考代码output_example.c中的编码函数用的是avcodec_encode_video(),我怀疑在其中就是调用了AVCodec的encode函数,他们传递的参数和返回值都是一致的,当然还没有得到确认,有兴趣可以看看ffmpeg源代码。在参考代码中,AVCodec的初始化後的使用都是依附于AVCodecContex,前者是后者的成员。在AVCodecContext初始化後(add_video_stream()),AVCodec也就能很好的初始化了:


//初始化


codec =avcodec_find_encoder(c->codec_id); (33)


//打开Codec


avcodec_open(c, codec) (34)


VI. AVFrame


AVFrame是个很有意思的结构,它本身是这样定义的:


typedef structAVFrame {


FF_COMMON_FRAME


}AVFrame;


其中,FF_COMMON_FRAME是以一个宏出现的。由于在编解码过程中AVFrame中的数据是要经常存取的。为了加速,要采取这样的代码手段。


AVFrame是作为一个描述“原始图像”(也就是YUV或是RGB…还有其他的吗?)的结构,他的头两个成员数据,uint8_t


*data[4],int linesize[4],第一个存放的是Y、Cb、Cr(yuv格式),linesize是啥?由这两个数据还能提取处另外一个数据结构:


typedef struct AVPicture{


uint8_t *data[4];


int linesize[4]; //number of bytes per line


}AVPicture ;


此外,AVFrame还含有其他一些成员数据,比如。是否key_frame、已编码图像书coded_picture_number、是否作为参考帧reference、宏块类型 *mb_type等等(avcodec.h 446行)。


AVFrame的初始化并没有他结构上看上去的那么简单。由于AVFrame还有一个承载图像数据的任务(data[4])因此,对他分配内存应该要小心完成。output_example.c中提供了alloc_picute()来完成这项工作。参考代码中定义了两个全局变量:


AVFrame *picture,*tmp_picture。(如果使用yuv420格式的那么只用到前一个数据picture就行了,将图像信息放入picture中。如果是其他格式,那么先要将yuv420格式初始化后放到tmp_picture中在转到需求格式放入picture中。)在open_video()打开编解码器后初始化AVFrame:


picture =alloc_picture(c->pix_fmt, c->width, c->height);


tmp_picture =alloc_picture(PIX_FMT_YUV420P, c->width, c->height);


static AVFrame*alloc_picture(int pix_fmt, int width, int height){


AVFrame *picture;


uint8_t*picture_buf; // think about why use uint8_t? a byte!


picture =avcodec_alloc_frame(); (35)


if(!picture)


return NULL;


size =avpicture_get_size(pix_fmt, width, height); (36)


picture_buf =av_malloc(size); (37)


if(!picture_buf){


av_free(picture);(38)


return NULL;


}


avpicture_fill ( (AVPicture*)picture, picture_buf, pix_fmt, width, height); (39)


return picture;


}


从以上代码可以看出,完成对一个AVFrame的初始化(其实也就是内存分配),基本上是有这样一个固定模式的。至于(35)(39)分别完成了那些工作,以及为什么有这样两步,还没有搞清楚,需要看原代码。我的猜测是(35)对AVFrame做了基本的内存分配,保留了对可以提取出AVPicture的前两个数据的内存分配到(39)来完成。说到这里,我们观察到在(39)中有一个(AVPicture *)picture,AVPicture这个结构也很有用。基本上他的大小也就是要在网络上传输的包大小,我们在后面可以看到AVPacket跟AVPicture有密切的关系。




VII.AVPicture


AVPicture在参考代码中没有自己本身的申明和初始化过程。出现了的两次都是作为强制类型转换由AVFrame中提取出来的:


// open_video() 中


avpicture_fill((AVPicture*)picture, picture_buf, pix_fmt, width, height); (40)


//write_video_frame中


// AVPacket pkt;


if(oc->oformat->flags& AVFMT_RAWPICTURE){


……


pkt.size =sizeof(AVPicture); (41)


}


在(40)中,实际上是对AVFrame的data[4]、linesize[4]分配内存。由于这两个数据大小如何分配确实需要有pix_fmt、width、height来确定。如果输出文件格式就是RAW图片(如YUV和RGB),AVPacket作为将编码后数据写入文件的基本数据单元,他的单元大小、数据都是由AVPacket来的。总结起来就是,AVPicture的存在有以下原因,AVPicture将Picture的概念从Frame中提取出来,就只由Picture(图片)本身的信息,亮度、色度和行大小。而Frame还有如是否是key frame之类的信息。这样的类似“分级”是整个概念更加清晰。


VIII.AVPacket


AVPacket的存在是作为写入文件的基本单元而存在的。我们可能会认为直接把编码后的比特流写入文件不就可以了,为什么还要麻烦设置一个AVPacket结构。在我看来这样的编码设置是十分有必要的,特别是在做视频实时传输,同步、边界问题可以通过AVPacket来解决。AVPacket的成员数据有两个时间戳、数据data(通常是编码后数据)、大小size等等(参见avformat.h 48行)。讲AVPacket的用法就不得不提到编解码函数,因为AVPacket的好些信息只有在编解码后才能的知。在参考代码中(ouput_example.c从362到394行),做的一个判断分支。如果输出文件格式是RAW图像(即YUV或RGB)那么就没有编码函数,直接写入文件(因为程序本身生成一个YUV文件),这里的代码虽然在此看来没什么价值,但是如果是解码函数解出yuv文件(或rgb)那么基本的写文件操作就是这样的:


if(oc->oformat->flags& AVFMT_RAWPICTURE) {


AVPacket pkt; // 这里没有用指针!


av_init_packet(&pkt);


pkt.flags |=PKT_FLAG_KEY // raw picture 中,每帧都是key frame?


pkt.stream_index =st->index;


pkt.data = (uint8_t*)picture;


pkt.size =sizeof(AVPicture);


ret =av_write_frame(oc, &pkt);


}


输出非raw picture,编码后:


else{


// video_outbuf& video_outbuf_size在open_video()中初始化


out_size =avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); (42)


if(out_size >0){


AVPacket pkt;


av_init_packet(&pkt);(43)


pkt.pts=av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);(44)


if(c->coded_frame->key_frame)


pkt.flags |=PKT_FLAG_KEY;


pkt.stream_index=st->index;


pkt.data=video_outbuf;


pkt.size=out_size;




/* write thecompressed frame in the media file */


ret =av_write_frame(oc, &pkt); (45)


} else {


ret = 0;


}


if (ret != 0) {


fprintf(stderr,"Error while writing video frame\n");


exit(1);


}


其中video_outbuf和video_outbuf_size在open_video()里的初始化是这样的:


video_outbuf =NULL;


// 输出不是raw picture,而确实用到编码codec


if(!(oc->oformat->flags & AVFMT_RAWPICTURE)){


video_outbuf_size =200000;


video_outbuf =av_malloc(video_outbuf_size);


}


(43)是AVPacket结构的初始化函数。(44)比较难理解,而且为什么会有这样的一些时间戳我也没有搞明白。其他的AVPacket成员数据的赋值比较容易理解,要注意的是video_outbuf和video_outbuf_size的初始化问题,由于在参考代码中初始化和使用不在同一函数中,所以比较容易忽视。(45)是写文件函数,AVFormatContext* oc中含有文件名等信息,返回值ret因该是一共写了多少数据信息,如果返回0则说明写失败。(42)和(45)作为比较重要的SDK函数,后面还会介绍的。.


IX. Conclusion


以上分析了FFMpeg中比较重要的数据结构。下面的这个生成关系理一下思路:(->表示派生出)


AVFormatContext->AVStream->AVCodecContext->AVCodec


|


AVOutputFormat orAVInputFormat


AVFrame->AVPicture….>AVPacket


二.FFMpeg 中的函数:


在前一部分的分析中我们已经看到FFMpeg SDK提供了许多初始化函数和编码函数。我们要做的就是对主要数据结构正确的初始化,以及正确使用相应的编解码函数以及读写(I/O)操作函数。作为一个整体化的代码SDK,FFMpeg有一些他自己的标准化使用过程。比如函数av_register_all();就是一个最开始就该调用的“注册函数”,他初始化了libavcodec,“注册”了所有的的codec和视频文件格式(format)。下面,我沿着参考代码(ouput_example.c)的脉络,介绍一下相关函数。




/******************************************************************


main()


******************************************************************/


1. av_register_all();


usage: initializeibavcoded, and register all codecs and formats


每个使用FFMpeg SDK的工程都必须调用的函数。进行codec和format的注册,然后才能使用。声明在allformats.c中,都是宏有兴趣看看。


2. AVOutputFormatguess_format(const char *short_name, const char *filename, const char*mime_type)


usage: 通过文件后缀名,猜测文件格式,其实也就是要判断使用什么编码器(or解码器)。


AVOutputFormat *fmt;


fmt =guess_format(NULL, filename, NULL);


3. AVFormatContext*av_alloc_format_context(void)




usage: allocate theoutput media context.实际是初始化AVFormatContext的成员数据AVClass:


AVFormatContext*ic;


ic->av_class =&av_format_context_class;


//where


// format_to_name,options are pointer to function


static const AVClassav_format_context_class = {“AVFormatContext”, format_to_name, options};


4. static AVStream*add_video_stream(AVFormatContext *ox, int codec_id);


AVStream *video_st;


video_st =add_video_stream(oc, fmt->video_codec);


5. intav_set_parameters(AVFormatContext *s, AVFormatParameters *ap)


usage: set theoutput parameters (must be done even if no parameters).


AVFormatContext*oc;


// if failed,return integer smaller than zero


av_set_parameters(oc,NULL);


6. voiddump_format(AVFormatContext *ic, int index, const char *url, int is_output);


usage: 这一步会用有效的信息把 AVFormatContext的流域(streams field)填满。作为一个可调试的诊断,我们会将这些信息全盘输出到标准错误输出中,不过你在一个应用程序的产品中并不用这么做:


dump_format(oc, 0,filename, 1); // 也就是指明AVFormatContext中的事AVOutputFormat,还是 // AVInputFormat


7. static voidopen_video(AVFormatContext *oc, AVStream *st)


open_video(oc,video_st);


8. intav_write_header(AVFormatContext *s)


usage: allocate thestream private data and writer the stream header to an output media file. params media


file


handle, return 0 ifOK, AVERROR_xxx if error.


write the streamheader, if any


av_write_header(oc);


9. static voidwrite_video_frame(AVFormatContext *oc, AVStream *st)


write_video_frame(oc,video_st);


10. static voidclose_video(AVFormatContext *oc, AVStream *st)


// close each codec


close_video(oc,video_st);


11. intav_write_trailer(AVFormatContext *s)


usage: write thetrailer, if any. Write the stream trailer to an output media file and free thefile private


data.


av_write_trailer(oc);


12. voidav_freep(void *arg)


usage: free thestreams. Frees memory and sets the pointer to NULL. arg pointer to the pointerwhich should


be freed .


av_freep(&oc->streams[i]->codec);


av_freeep(&oc->streams[s]);




13. inturl_fclose(ByteIOContext *s);


usage: close theoutput file


url_fclose(&oc->pb);


14. voidav_free(void *ptr)


usage: free thestream. Free memory which has been allocated with av_malloc(z)() orav_realloc().


av_free(oc);


/******************************************************************


******************************************************************


add_video_stream()


AVCodecContext *c


AVStream *st


******************************************************************/


******************************************************************


1.AVStream *av_new_stream(AVFormatContext*s, int id)


usage: add a newstream to a media file. s: media file handle, id: file format dependent streamid


st =av_new_stream(oc, 0);


/******************************************************************


******************************************************************


open_video()


AVCodecContext *c


AVCodec *codec


AVFrame *picture,*tmp_picture


uint8_t*video_output


int frame_count,video_outbuf_size;


******************************************************************


******************************************************************/


1 AVCodec*avcodec_find_encoder(enum CodecID id)


usage: find thecodec of encoder by CodecID. 在前面main中的guess_format()就已经开始为此准备了。


codec =avcodec_find_encoder(c->codec_id);


2 int avcodec_open(AVCodecContext*avctx, AVCodec *codec);


usage: opens /inits the AVCodecContext. 打开失败的话,返回值小于零。


avcodec_open(c,codec);


3 void*av_malloc(unsigned in size);


usage: you canredefine av_malloc and av_free in your project to use your memory allocator.You do not need


to suppress thisfile because the linker will do it automatically


Memory allocationof size byte with alignment suitable for all memory accesses (including vectorsif


available on theCPU). av_malloc(0) must return a non NULL pointer.


video_outbuf_size =200000;


video_outbuf =avmalloc(video_outbuf_size);


4 static AVFrame*alloc_picture(int pix_fmt, int width, int height)


picture =alloc_picture(c->pix_fmt, c->width, c->height);




/******************************************************************


******************************************************************


******************************************************************


alloc_picture()


AVFrame *picture


uint8_t*picture_buf


int size


******************************************************************


******************************************************************/


******************************************************************


1.avcodec_alloc_frame()




usage: initializeAVFrame* picture


picture = avcodec_alloc_frame()


2. intavpicture_get_size(int pix_fmt, int width, int height)




usage: 根据像素格式和视频分辨率获得picture存储大小。


size =avpicture_get_size(pix_fmt, width, height);


picture_buf =av_malloc(size)


3. intavpicture_fill(AVPicture *picture, uint8_t *ptr, int pix_fmt, int width, intheight)




usage: Picturefield are filled with ‘ptr’ addresses, also return size。用ptr中的内容根据文件格式(YUV…)


和分辨率填充picture。这里由于是在初始化阶段,所以填充的可能全是零。


avpicture_fill((AVPicture*)picture,picture_buf, pix_fmt, width, height);


/******************************************************************


******************************************************************


write_video_frame()


int out_size, ret;


AVCodecContext *c;


static structSwsContext *img_convert_ctx


******************************************************************


******************************************************************/


1 struct SwsContext*sws_getContext(int srcW, ……)


usage: 转变raw picture格式的获取context函数,比如下面的代码就是将其他格式的(如yuv422)转为yuv420,就要将


context 保存在img_convert_ctx中,然后再利用后面的介绍函数做转化。


img_convert_ctx =sws_getContext(c->width, c->height,


PIX_FMT_YUV420P,


c->width,c->height,


c->pix_fmt,


sws_flags, NULL,NULL, NULL);


2 intsws_scale(struct SwsContext *ctx, uing8_t* src[], int srcStride[], intsrcSliceY, int srcSliceH,


uint8_t* dst[], intdstStride[]);


usage: 根据SwsContext保存的目标文件context将src(source)转为dst(destination)。


sws_scale(img_convert_ctx,tmp_picture->data, tmp_picture->linesize, 0, c->height,picture->data, picture-


>linesize);


4. intavcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, constAVFrame *pict);




usage: 根据AVCodecContext将pict编码到buf中,buf_size是buf的大小。




out_size =avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);


5 static inlinevoid av_init_packet(AVPacket *pkt)


usage: initializeoptional fields of a packet.初始化AVPacket。


AVPacket pkt;


av_init_packet(&pkt)


6 int64_tav_rescale_q(int64_t a, AVRational bq, AVRational cq)




usage: 校准时间基(maybe)


pkt.pts =av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);


7 intav_write_frame(AVFormatContext *s, AVPacket *pkt)




usage: write apacket to an output media file . pkt: the packet, which contains thestream_index,


buf/buf_size,dts/pts, …if error return<0, if OK =0, if end of stream wanted =1


ret =av_write_frame(oc, &pke);


/******************************************************************


******************************************************************


static voidclose_video(AVFormatContext *oc, AVStream *st)


{


avcodec_close(st->codec);


av_free(picture->data[0]);


av_free(picture);


if (tmp_picture) {


av_free(tmp_picture->data[0]);


av_free(tmp_picture);


av_free(video_outbuf);


/******************************************************************


******************************************************************


讲初始化过的,特别是分配过内存的,都要释放。


ffmpeg.exe -i F:\闪客之家\闪客之歌.mp3 -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\11.flv   ffmpeg -i F:\01.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\test.flv   使用-ss参数 作用(time_off set the start time offset),可以从指定时间点开始转换任务。如:   转换文件格式的同时抓缩微图:   ffmpeg -i "test.avi" -y -f image2 -ss 8 -t 0.001 -s 350x240 'test.jpg'   对已有flv抓图:   ffmpeg -i "test.flv" -y -f image2 -ss 8 -t 0.001 -s 350x240 'test.jpg'   -ss后跟的时间单位为秒   Ffmpeg转换命令   ffmpeg -y -i test.mpeg -bitexact -vcodec h263 -b 128 -r 15 -s 176x144 -acodec aac -ac 2 -ar 22500   -ab 24 -f 3gp test.3gp   或者   ffmpeg -y -i test.mpeg -ac 1 -acodec amr_nb -ar 8000 -s 176x144 -b 128 -r 15 test.3gp   ffmpeg参数设定解说   -bitexact 使用标准比特率   -vcodec xvid 使用xvid压缩   -s 320x240 指定分辨率   -r 29.97 桢速率(可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97)   画面部分,选其一   -b <比特率> 指定压缩比特率,似乎ffmpeg是自动VBR的,指定了就大概是平均比特率,比如768,1500这样的   就是原来默认项目中有的   -qscale <数值> 以<数值>质量为基础的VBR,取值0.01-255,约小质量越好   -qmin <数值> 设定最小质量,与-qmax(设定最大质量)共用,比如-qmin 10 -qmax 31   -sameq 使用和源同样的质量   声音部分   -acodec aac 设定声音编码   -ac <数值> 设定声道数,1就是单声道,2就是立体声,转换单声道的TVrip可以用1(节省一半容量),高品质   的DVDrip就可以用2   -ar <采样率> 设定声音采样率,PSP只认24000   -ab <比特率> 设定声音比特率,前面-ac设为立体声时要以一半比特率来设置,比如192kbps的就设成96,转换   君默认比特率都较小,要听到较高品质声音的话建议设到160kbps(80)以上   -vol <百分比> 设定音量,某些DVDrip的AC3轨音量极小,转换时可以用这个提高音量,比如200就是原来的2倍   这样,要得到一个高画质音质低容量的MP4的话,首先画面最好不要用固定比特率,而用VBR参数让程序自己去   判断,而音质参数可以在原来的基础上提升一点,听起来要舒服很多,也不会太大(看情况调整   例子:ffmpeg -y -i "1.avi" -title "Test" -vcodec xvid -s 368x208 -r 29.97 -b 1500 -acodec aac -ac 2 -ar 24000 -ab 128 -vol 200 -f psp -muxvb 768 "1.***"   解释:以上命令可以在Dos命令行中输入,也可以创建到批处理文件中运行。不过,前提是:要在ffmpeg所在的目录中执行(转换君所在目录下面的cores子目录)。   参数:   -y(覆盖输出文件,即如果1.***文件已经存在的话,不经提示就覆盖掉了)   -i "1.avi"(输入文件是和ffmpeg在同一目录下的1.avi文件,可以自己加路径,改名字)   -title "Test"(在PSP中显示的影片的标题)   -vcodec xvid(使用XVID编码压缩视频,不能改的)   -s 368x208(输出的分辨率为368x208,注意片源一定要是16:9的不然会变形)   -r 29.97(帧数,一般就用这个吧)   -b 1500(视频数据流量,用-b xxxx的指令则使用固定码率,数字随便改,1500以上没效果;还可以用动态码率如:-qscale 4和-qscale 6,4的质量比6高)   -acodec aac(音频编码用AAC)   -ac 2(声道数1或2)   -ar 24000(声音的采样频率,好像PSP只能支持24000Hz)   -ab 128(音频数据流量,一般选择32、64、96、128)   -vol 200(200%的音量,自己改)   -f psp(输出psp专用格式)   -muxvb 768(好像是给PSP机器识别的码率,一般选择384、512和768,我改成1500,PSP就说文件损坏了)   "1.***"(输出文件名,也可以加路径改文件名)   机器强劲的话,可以多开几个批处理文件,让它们并行处理。   E:\ffmpeg.exe -i I:\1.wmv -b 360 -r 25 -s 320x240 -hq -deinterlace -ab 56 -ar 22050 -ac 1 D:\2.flv




可以ffmpeg提取字幕数据

I am currently using ffmpeg to convert videos in various formats to flv files. One request has also come up and that is to get closed caption info out o the file as well. Does anyone have any experience with this or know it can even be done. I don't see any options for it but thought I would ask and see.

For getting just the subtitles and not any meta junk, I've found that

ffmpeg -i input.mov -an -vn -bsf:s mov2textsub -scodec copy -f rawvideo sub.txt

works best for me.

2014年03月11日32分08秒

If the caption are included as a separate stream, then extracting them is (relatively) straightforward:

ffmpeg -i input.mov -an -vn -c:s copy -f rawvideo -map 0:s sub.txt

If it's "burned in" on the video file, then you're probably out of luck, but I that would be more common for subtitles than closed captions.

2014年03月11日32分08秒

Closed Captions are not separate streams, nor are they burned into the picture, they are interlaced in scanlines IN the picture - this a strange American idea, not really used elsewhere. Though you can buy DVD's which has this kind of subtitling, usually people outside the US can't see the subtitles, and may not even know there are some in the file.

CCExtractor can extract this information from VOB's by looking at the TS metadata:http://ccextractor.sourceforge.net/

And since its open source someone might actually want to add it to FFMpeg. Though it would probably require a lot of programming.

2014年03月11日32分08秒

////字幕添加

-vf "movie=input.png [watermark]; [in][watermark] overlay=0:0:0 [out]"



FFmpeg

FFmpeg 基本用法

本课要解决的问题

1.FFmpeg的转码流程是什么?

2.常见的视频格式包含哪些内容吗?

3.如何把这些内容从视频文件中抽取出来?

4.如何从一种格式转换为另一种格式?

5.如何放大和缩小视频?

6.如何旋转,翻转,填充,裁剪,模糊,锐化视频?

7.如何给视频加logo,删除logo?

8.如何给视频加文本,动态文本?

9.如何处理图片?

10.如何录像,添加动态logo,截图,马赛克视频?

第一部分

基础

术语

容器(Container)

容器就是一种文件格式,比如flv,mkv等。包含下面5种流以及文件头信息。

流(Stream)

是一种视频数据信息的传输方式,5种流:音频,视频,字幕,附件,数据。

帧(Frame)

帧代表一幅静止的图像,分为I帧,P帧,B帧。

编解码器(Codec)

是对视频进行压缩或者解压缩,CODEC =COde (编码) +DECode(解码)

复用/解复用(mux/demux)

把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux)

把不同的流从某种容器中解析出来,这种行为叫做解复用(demux)



简介


FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表“Fast Forward”,FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换。


FFmpeg的用户有Google,Facebook,Youtube,优酷,爱奇艺,土豆等。

组成

1、libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含demuxers和muxer库;

2、libavcodec:用于各种类型声音/图像编解码;

3、libavutil:包含一些公共的工具函数;

4、libswscale:用于视频场景比例缩放、色彩映射转换;

5、libpostproc:用于后期效果处理;

6、ffmpeg:是一个命令行工具,用来对视频文件转换格式,也支持对电视卡实时编码;

7、ffsever:是一个HTTP多媒体实时广播流服务器,支持时光平移;

8、ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;


FFmpeg处理流程

过滤器(Filter)

在多媒体处理中,filter的意思是被编码到输出文件之前用来修改输入文件内容的一个软件工具。如:视频翻转,旋转,缩放等。

语法:[input_link_label1][input_link_label2]… filter_name=parameters [output_link_label1][output_link_label2]…

过滤器图link label :是标记过滤器的输入或输出的名称

1.视频过滤器 -vf

如testsrc视频按顺时针方向旋转90度

ffplay -f lavfi -i testsrc -vf transpose=1

如testsrc视频水平翻转(左右翻转)

ffplay -f lavfi -i testsrc -vf hflip

2.音频过滤器 -af

实现慢速播放,声音速度是原始速度的50%

ffplay p629100.mp3 -af atempo=0.5


如何实现顺时针旋转90度并水平翻转?

过滤器链(Filterchain)

基本语法

Filterchain = 逗号分隔的一组filter

语法:“filter1,filter2,filter3,…filterN-2,filterN-1,filterN”

顺时针旋转90度并水平翻转

ffplay -f lavfi -i testsrc -vf transpose=1,hflip





如何实现水平翻转视频和源视频进行比较? 看过滤器链是如何实现的。







过滤器链(Filterchain)

第一步: 源视频宽度扩大两倍。

ffmpeg -i jidu.mp4 -t 10 -vf pad=2*iw output.mp4

第二步:源视频水平翻转

ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4

第三步:水平翻转视频覆盖output.mp4

ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4

是不是很复杂?

用带有链接标记的过滤器图(Filtergraph)只需一条命令。

过滤器图(Filtergraph)

基本语法

Filtergraph = 分号分隔的一组filterchain

“filterchain1;filterchain2;…filterchainN-1;filterchainN”



Filtergraph的分类

1、简单(simple) 一对一

2、复杂(complex)多对一, 多对多

过滤器图(Filtergraph)

简单过滤器图处理流程:



复杂过滤器图处理流程:




从图中可以发现复杂过滤器图比简单过滤器图少2个步骤,效率比简单高,ffmpeg建议尽量使用复杂过滤器图。

回答上面提的问题,实现水平翻转视频和源视频进行比较


过滤器图(Filtergraph)

用ffplay直接观看结果:

ffplay -f lavfi -i testsrc -vf split[a][b];[a]pad=2*iw[1];[b]hflip[2];[1][2]overlay=w





F1: split过滤器创建两个输入文件的拷贝并标记为[a],[b]

F2: [a]作为pad过滤器的输入,pad过滤器产生2倍宽度并输出到[1].

F3: [b]作为hflip过滤器的输入,vflip过滤器水平翻转视频并输出到[2].

F4: 用overlay过滤器把 [2]覆盖到[1]的旁边.



选择媒体流

一些多媒体容器比如AVI,mkv,mp4等,可以包含不同种类的多个流,如何从容器中抽取各种流呢?

语法:

-map file_number:stream_type[:stream_number]


这有一些特别流符号的说明:

1、-map 0 选择第一个文件的所有流

2、-map i:v 从文件序号i(index)中获取所有视频流, -map i:a 获取所有音频流,-map i:s 获取所有字幕流等等。

3、特殊参数-an,-vn,-sn分别排除所有的音频,视频,字幕流。


注意:文件序号和流序号从0开始计数。

选择媒体流

第二部分

查看帮助

帮助

FFmpeg工具有一个巨大的控制台帮助。下表描述了可用的一些选项,斜体字表示要被替换的项,ffplay和ffprobe也有一些类似的选项。


帮助

可用的bit流 :ffmpeg –bsfs

可用的编解码器:ffmpeg –codecs

可用的解码器:ffmpeg –decoders

可用的编码器:ffmpeg –encoders

可用的过滤器:ffmpeg –filters

可用的视频格式:ffmpeg –formats

可用的声道布局:ffmpeg –layouts

可用的license:ffmpeg –L

可用的像素格式:ffmpeg –pix_fmts

可用的协议:ffmpeg -protocals


第三部分

码率、帧率和文件大小

概述

       码率和帧率是视频文件的最重要的基本特征,对于他们的特有设置会决定视频质量。如果我们知道码率和时长那么可以很容易计算出输出文件的大小。


帧率:帧率也叫帧频率,帧率是视频文件中每一秒的帧数,肉眼想看到连续移动图像至少需要15帧。

码率:比特率(也叫码率,数据率)是一个确定整体视频/音频质量的参数,秒为单位处理的字节数,码率和视频质量成正比,在视频文件中中比特率用bps来表达。

帧率

1、用 -r 参数设置帧率

ffmpeg –i input –r fps output

2、用fps filter设置帧率

ffmpeg -i clip.mpg -vf fps=fps=25 clip.webm

帧率的预定义值:






例如设置码率为29.97fps,下面三种方式具有相同的结果:

ffmpeg -i input.avi -r 29.97 output.mpg

ffmpeg -i input.avi -r 30000/1001 output.mpg

ffmpeg -i input.avi -r netsc output.mpg


码率、文件大小

设置码率 –b 参数

-b

ffmpeg -i film.avi -b 1.5M film.mp4


音频:-b:a     视频: - b:v

设置视频码率为1500kbps

ffmpeg -i input.avi -b:v 1500k output.mp4


控制输出文件大小

-fs (file size首字母缩写)

ffmpeg -i input.avi -fs 1024K output.mp4

计算输出文件大小

(视频码率+音频码率) * 时长 /8 = 文件大小K



第四部分

调整视频分辨率

调整视频分辨率

1、用-s参数设置视频分辨率,参数值wxh,w宽度单位是像素,h高度单位是像素

ffmpeg -i input_file -s 320x240 output_file


2、预定义的视频尺寸

下面两条命令有相同效果

ffmpeg -i input.avi -s 640x480 output.avi

ffmpeg -i input.avi -s vga output.avi


下表列出了所有的预定义尺寸





Scale filter调整分辨率

Scale filter的优点是可以使用一些额外的参数

语法:

Scale=width:height[:interl={1|-1}]

下表列出了常用的额外参数

举例

下面两条命令有相同效果

ffmpeg -i input.mpg -s 320x240 output.mp4

ffmpeg -i input.mpg -vf scale=320:240 output.mp4


对输入视频成比例缩放

改变为源视频一半大小

ffmpeg -i input.mpg -vf scale=iw/2:ih/2 output.mp4

改变为原视频的90%大小:

ffmpeg -i input.mpg -vf scale=iw*0.9:ih*0.9 output.mp4


举例

在未知视频的分辨率时,保证调整的分辨率与源视频有相同的横纵比。

宽度固定400,高度成比例:

ffmpeg -i input.avi -vf scale=400:400/a

ffmpeg -i input.avi -vf scale=400:-1


相反地,高度固定300,宽度成比例:

ffmpeg -i input.avi -vf scale=-1:300

ffmpeg -i input.avi -vf scale=300*a:300


第五部分

裁剪/填充视频

裁剪视频crop filter

从输入文件中选取你想要的矩形区域到输出文件中,常见用来去视频黑边。

语法:crop:ow[:oh[:x[:y:[:keep_aspect]]]]


举例

裁剪输入视频的左三分之一,中间三分之一,右三分之一:

ffmpeg -i input -vf crop=iw/3:ih :0:0 output

ffmpeg -i input -vf crop=iw/3:ih :iw/3:0 output

ffmpeg -i input -vf crop=iw/3:ih :iw/3*2:0 output

裁剪帧的中心

当我们想裁剪区域在帧的中间时,裁剪filter可以跳过输入x和y值,他们的默认值是

Xdefault  = ( input width - output width)/2

Ydefault  = ( input height - output height)/2

ffmpeg -i input_file -v crop=w:h output_file

裁剪中间一半区域:

ffmpeg -i input.avi -vf crop=iw/2:ih/2 output.avi


举例

比较裁剪后的视频和源视频比较

ffplay -i jidu.mp4 -vf split[a][b];[a]drawbox=x=(iw-300)/2:(ih-300)/2:w=300:h=300:c=yellow[A];[A]pad=2*iw[C];[b]crop=300:300:(iw-300)/2:(ih-300)/2[B];[C][B]overlay=w*2.4:40



自动检测裁剪区域

cropdetect  filter 自动检测黑边区域

ffplay jidu.mp4 -vf cropdetect





然后用检测到的值来裁剪视频

ffplay jidu.mp4 –vf crop=672:272:0:54



填充视频(pad)

在视频帧上增加一快额外额区域,经常用在播放的时候显示不同的横纵比

语法:pad=width[:height:[:x[:y:[:color]]]]



举例

创建一个30个像素的粉色宽度来包围一个SVGA尺寸的图片:

ffmpeg -i photo.jpg -vf pad=860:660:30:30:pink framed_photo.jpg

?




同理可以制作testsrc视频用30个像素粉色包围视频

ffplay  -f lavfi -i testsrc -vf pad=iw+60:ih+60:30:30:pink


4:3到16:9

一些设备只能播放16:9的横纵比,4:3的横纵比必须在水平方向的两边填充成16:9,


高度被保持,宽度等于高度乘以16/9,x(输入文件水平位移)值由表达式(output_width - input_width)/2来计算。


4:3到16:9的通用命令是:

ffmpeg -i input -vf pad=ih*16/9:ih :(ow-iw)/2:0:color output


举例

ffplay  -f lavfi -i testsrc -vf pad=ih*16/9:ih:(ow-iw)/2:0:pink


16:9到4:3

为了用4:3的横纵比来显示16:9的横纵比,填充输入文件的垂直两边,宽度保持不变,高度是宽度的3/4,y值(输入文件的垂直偏移量)是由一个表达式(output_height-input_height)/2计算出来的。


16:9到4:3的通用命令:

ffmpeg -i input -vf pad=iw :iw*3/4:0:(oh-ih)/2:color output


举例

ffplay  -f lavfi -i testsrc=size=320x180 -vf pad=iw:iw*3/4:0:(oh-ih)/2:pink



第六部分

翻转和旋转

翻转

水平翻转语法: -vf hflip

ffplay -f lavfi -i testsrc -vf hflip


垂直翻转语法:-vf vflip

ffplay -f lavfi -i testsrc -vf vflip


旋转

语法:transpose={0,1,2,3}

0:逆时针旋转90°然后垂直翻转

1:顺时针旋转90°

2:逆时针旋转90°

3:顺时针旋转90°然后水平翻转

第七部分

模糊,锐化

模糊

语法:boxblur=luma_r:luma_p[:chroma_r:chram_p[:alpha_r:alpha_p]]

ffplay -f lavfi -i testsrc -vf  boxblur=1:10:4:10

注意:luma_r和alpha_r半径取值范围是0~min(w,h)/2, chroma_r半径的取值范围是0~min(cw/ch)/2

锐化

语法:-vf unsharp=l_msize_x:l_msize_y:l_amount:c_msize_x:c_msize_y:c_amount

所有的参数是可选的,默认值是5:5:1.0:5:5:0.0

l_msize_x:水平亮度矩阵,取值范围3-13,默认值为5

l_msize_y:垂直亮度矩阵,取值范围3-13,默认值为5

l_amount:亮度强度,取值范围-2.0-5.0,负数为模糊效果,默认值1.0

c_msize_x:水平色彩矩阵,取值范围3-13,默认值5

c_msize_y:垂直色彩矩阵,取值范围3-13,默认值5

c_amount:色彩强度,取值范围-2.0-5.0,负数为模糊效果,默认值0.0

举例

使用默认值,亮度矩阵为5x5和亮度值为1.0

ffmpeg -i input -vf unsharp output.mp4

高斯模糊效果(比较强的模糊):

ffplay -f lavfi -i testsrc -vf unsharp=13:13:-2


第八部分

覆盖(画中画)

覆盖

语法:overlay[=x[:y]

所有的参数都是可选,默认值都是0


举例

Logo在左上角

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay pair1.mp4


举例

右上角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=W-w  pair2.mp4

左下角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=0:H-h  pair2.mp4

右下角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=W-w:H-h  pair2.mp4


删除logo

语法:-vf delogo=x:y:w:h[:t[:show]]

x:y 离左上角的坐标

w:h  logo的宽和高

t: 矩形边缘的厚度默认值4

show:若设置为1有一个绿色的矩形,默认值0.

ffplay -i jidu.mp4 -vf delogo=50:51:60:60:100:0

第九部分

添加文本

语法:

drawtext=fontfile=font_f:text=text1[:p3=v3[:p4=v4[…]]]

常用的参数值

x:离左上角的横坐标

y: 离左上角的纵坐标

fontcolor:字体颜色

fontsize:字体大小

text:文本内容

textfile:文本文件

t:时间戳,单位秒

n:帧数开始位置为0

draw/enable:控制文件显示,若值为0不显示,1显示,可以使用函数

简单用法

1、在左上角添加Welcome文字

ffplay -f lavfi -i color=c=white -vf drawtext=fontfile=arial.ttf:text=Welcom

2、在中央添加Good day

ffplay -f lavfi -i color=c=white -vf drawtext="fontfile=arial.ttf:text='Goodday':x=(w-tw)/2:y=(h-th)/2"

3、设置字体颜色和大小

ffplay -f lavfi -i color=c=white -vf drawtext="fontfile=arial.ttf:text='Happy Holidays':x=(w-tw)/2:y=(h-th)/2:fontcolor=green:fontsize=30"


动态文本

用 t (时间秒)变量实现动态文本

1、顶部水平滚动

ffplay -i jidu.mp4 -vf drawtext="fontfile=arial.ttf:text='Dynamic RTL text':x=w-t*50:fontcolor=darkorange:fontsize=30"

2、底部水平滚动

ffplay -i jidu.mp4 -vf drawtext="fontfile=arial.ttf:textfile=textfile.txt:x=w-t*50:y=h-th:fontcolor=darkorange:fontsize=30"

3、垂直从下往上滚动

ffplay jidu.mp4 -vf drawtext="textfile=textfile:fontfile=arial.ttf:x=(w-tw)/2:y=h-t*100:fontcolor=white:fontsize=30“

想实现右上角显示当前时间?



动态文本

在右上角显示当前时间 localtime

ffplay jidu.mp4 -vf drawtext="fontfile=arial.ttf:x=w-tw:fontcolor=white:fontsize=30:text='%{localtime\:%H\\\:%M\\\:%S}'“


每隔3秒显示一次当前时间

ffplay jidu.mp4 -vf drawtext="fontfile=arial.ttf:x=w-tw:fontcolor=white:fontsize=30:text='%{localtime\:%H\\\:%M\\\:%S}':enable=lt(mod(t\,3)\,1)"


第十部分 图片处理

图片支持

FFmpeg支持绝大多数图片处理, 除LJPEG(无损JPEG)之外,其他都能被解码,除了EXR,PIC,PTX之外,所有的都能被编码。

截取一张图片使用 –ss(seek from start)参数.

ffmpeg -ss 01:23:45 -i jidu.mp4 image.jpg

从视频中生成GIF图片

ffmpeg -i jidu.mp4 -t 10 -pix_fmt rgb24 jidu.gif

转换视频为图片(每帧一张图)

ffmpeg -i clip.avi frame%4d.jpg

图片转换为视频

ffmpeg -f image2 -i img%4d.jpg -r 25 video.mp4


裁剪、填充

和视频一样,图片也可以被裁剪和填充

裁剪

ffmpeg -f lavfi -i rgbtestsrc -vf crop=150:150 crop_rg.png

填充

ffmpeg -f lavfi -i smptebars -vf pad=360:280:20:20:orange pad_smpte.jpg


翻转,旋转,覆盖

和视频一样图片同样能翻转,旋转和覆盖

翻转

ffmpeg -i orange.jpg -vf hflip orange_hfilp.jpg

ffmpeg -i orange.jpg -vf vflip orange_vfilp.jpg

旋转

ffmpeg -i image.png -vf transpose=1 image_rotated.png

覆盖

ffmpeg -f lavfi -i rgbtestsrc -s 400x300 rgb .png

ffmpeg -f lavfi -i smptebars smpte.png

ffmpeg -i rgb .png -i smpte.png -filter_complex overlay= (W-w)/2:(H-h)/2  rgb_smpte.png


第十一部分

其他高级技巧

屏幕录像

显示设备名称

ffmpeg -list_devices 1 -f dshow -i dummy

调用摄像头

ffplay -f dshow  -i video="Integrated Camera"

保存为文件

ffmpeg -y -f dshow -s 320x240 -r 25 -i video="Integrated Camera" -b:v 800K -vcodec mpeg4 new.mp4


添加字幕subtitles

语法 –vf subtitles=file


ffmpeg -i jidu.mp4 -vf subtitles=rgb.srt output.mp4

视频颤抖、色彩平衡

视频颤抖

ffplay –i jidu.mp4 -vf crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(n/7)


色彩平衡

ffplay -i jidu.mp4 -vf curves=vintage

色彩变幻

ffplay -i jidu.mp4 -vf hue="H=2*PI*t: s=sin(2*PI*t)+1“

彩色转换黑白

ffplay -i jidu.mp4 -vf lutyuv="u=128:v=128"

设置音频视频播放速度

3倍视频播放视频

ffplay -i jidu.mp4 -vf setpts=PTS/3

?速度播放视频

ffplay -i jidu.mp4  -vf setpts=PTS/(3/4)

2倍速度播放音频

ffplay -i speech.mp3 -af atempo=2


问题:视频和音频同时3/4慢速播放

截图

每隔一秒截一张图

ffmpeg -i input.flv -f image2 -vf fps=fps=1 out%d.png

每隔20秒截一张图

ffmpeg -i input.flv -f image2 -vf fps=fps=1/20 out%d.png


注意:ffmpeg version N-57961-gec8e68c版本最多可以每隔20s截一张图。

多张截图合并到一个文件里(2x3) ?每隔一千帧(秒数=1000/fps25)即40s截一张图

ffmpeg? -i jidu.mp4 -frames 3 -vf "select=not(mod(n\,1000)),scale=320:240,tile=2x3" out.png


马赛克视频

用多个输入文件创建一个马赛克视频:

ffmpeg -i jidu.mp4 -i jidu.flv -i "Day By Day SBS.mp4" -i "Dangerous.mp4" -filter_complex "nullsrc=size=640x480 [base]; [0:v] setpts=PTS-STARTPTS, scale=320x240 [upperleft]; [1:v] setpts=PTS-STARTPTS, scale=320x240 [upperright]; [2:v] setpts=PTS-STARTPTS, scale=320x240 [lowerleft]; [3:v] setpts=PTS-STARTPTS, scale=320x240 [lowerright]; [base][upperleft] overlay=shortest=1 [tmp1]; [tmp1][upperright] overlay=shortest=1:x=320 [tmp2]; [tmp2][lowerleft] overlay=shortest=1:y=240 [tmp3]; [tmp3][lowerright] overlay=shortest=1:x=320:y=240" -c:v libx264 output.mkv


Logo动态移动

1、2秒后logo从左到右移动:

ffplay -i jidu.mp4  -vf movie=logo.png[logo];[in][logo]overlay=x='if(gte(t\,2)\,((t-2)*80)-w\,NAN)':y=0


2、2秒后logo从左到右移动后停止在左上角

ffplay -i jidu.mp4  -vf movie=logo.png[logo];[in][logo]overlay=x='if(gte(((t-2)*80)-w\,W)\,0\,((t-2)*80)-w)':y=0

3、每隔10秒交替出现logo。

ffmpeg -y -t 60 -i jidu.mp4 -i logo.png -i logo2.png -filter_complex "overlay=x=if(lt(mod(t\,20)\,10)\,10\,NAN ):y=10,overlay=x=if(gt(mod(t\,20)\,10)\,W-w-10\,NAN ) :y=10" overlay.mp4


资料

FFmpeg官网: http://www.ffmpeg.org

FFmpeg doc : http://www.ffmpeg.org/documentation.html

FFmpeg wiki : https://trac.ffmpeg.org/wiki

FFmpeg基础: http://wenku.baidu.com/view/296eefcaf90f76c661371af1.html


整理补充 Rov  企鹅:121865214  E-mail:lojy2009@qq.com

欢迎就错、补充和更新。

声明:影聚合仅提供信息展示和存储服务,文章均来自网络和个人,内容仅代表作者本人观点,不代表本站观点。部分内容由AI智能生成,请谨慎参考。如内容如有侵权,请联系cm@rov8.com,我们将第一时间处理。

评论(0)

等待你的第一个评论哦...

影片推荐