1 FFmpeg介绍
FFmpeg项目由 Fabrice Bellard在2000年创立。到目前为止,FFmpeg项目的开发者仍然与VLC、MPV、dav1d、x264等多媒体开源项目有着广泛的重叠。Ffmpeg(FastForward Mpeg)是一款遵循GPL的开源软件,在音视频处理方面表现十分优秀,几乎囊括了现存所有的视音频格式的编码,解码、转码、混合、过滤及播放。作为最受欢迎的视频和图像处理软件,它被来自各行各业的不同公司所广泛使用。同时也是一款跨平台的软件,完美兼容Linux、Windows、Mac OSX等平台。其实它由3大部件组成,号称音视频处理工具三剑客:
- Ffmpeg:由命令行组成,用于多媒体格式转换
- Ffplay:基于ffmpeg开源代码库libraries做的多媒体播放器
- Ffprobe:基于ffmpeg做的多媒体流分析器
Ffmpeg 应该是 FFmpeg 工具集中最核心的利器,支持多种多样的编码器、解码器、封装格式、滤镜功能。FFmpeg框架的基本组成包含AVFormat、AVCodec、AVFilter、AVDevice、AVUtil等模块库,结构图如下:
(1)AVFormat–FFmpeg的封装模块
AVFormat中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装,如MP4、FLV、KV、TS等文件封装格式,RTMP、RTSP、MMS、HLS等网络协议封装格式。FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。
(2)AVCodec–FFmpeg的编解码模块
AVCodec中实现了目前多媒体领域绝大多数常用的编解码格式,即支持编码,也支持解码。AVCodec除了支持MPEG4、AAC、MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器;H.265(HEVC)编码,需要使用x264编码器;MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块。
(3)AVFilter–FFmpeg的滤镜模块
AVFilter库提供了一个通用的音频、视频、字幕等滤镜处理框架。在AVFilter中,滤镜框架可以有多个输入和多个输出。
(4)swresample–FFmpeg的音频转换计算模块
swresample模块提供了高级别的音频重采样API。例如允许操作音频采样、音频通道布局转换与布局调整。
(5)swscale–FFmpeg的视频图像转换计算模块
swscale模块提供了高级别的图像转换API,例如它允许进行图像缩放和像素格式转换,常见于将图像从1080p转换成720p或者480p等的缩放,或者将图像数据从YUV420p转换成YUYV,或者YUV转RGB等图像格式转换。
2 conda环境安装ffmpeg
(1)annoconda环境安装
安装方法详见:annoconda安装
(2)ffmpeg安装
conda install ffmpeg
3 ffmpeg命令
FFMPEG提供的命令行(CLI)工具ffmpeg,其使用方法如下(方括号表示可选项,花括号表示必选项目):
ffmpeg [global options] {[infile options]['-i' 'infile'] ...} {[outfile options] 'outfile' ...}
参数选项由三部分组成:可选的一组全局参数、一组或多组输入文件参数、一组或多组输出文件参数,其中,每组输入文件参数以‘-i’为结束标记;每组输出文件参数以输出文件名为结束标记。
(1)能力集列表
-
-formats:列出支持的文件格式。
-
-codecs:列出支持的编解码器。
-
-decoders:列出支持的解码器。
-
-encoders:列出支持的编码器。
-
-protocols:列出支持的协议。
-
-bsfs:列出支持的比特流过滤器。
-
-filters:列出支持的滤镜。
-
-pix_fmts:列出支持的图像采样格式。
-
-sample_fmts:列出支持的声音采样格式。
使用方法:
ffmpeg configure -encoders
(2)常用输入选项
-
-i filename:指定输入文件名。
-
-f fmt:强制设定文件格式,需使用能力集列表中的名称(缺省是根据扩展名选择的)。
-
-ss hh:mm:ss[.xxx]:设定输入文件的起始时间点,启动后将跳转到此时间点然后开始读取数据。
对于输入,以下选项通常是自动识别的,但也可以强制设定。
-
-c codec:指定解码器,需使用能力集列表中的名称。
-
-acodec codec:指定声音的解码器,需使用能力集列表中的名称。
-
-vcodec codec:指定视频的解码器,需使用能力集列表中的名称。
-
-b:v bitrate:设定视频流的比特率,整数,单位bps。
-
-r fps:设定视频流的帧率,整数,单位fps。
-
-s WxH : 设定视频的画面大小。也可以通过挂载画面缩放滤镜实现。
-
-pix_fmt format:设定视频流的图像格式(如RGB还是YUV)。
-
-ar sample rate:设定音频流的采样率,整数,单位Hz。
-
-ab bitrate:设定音频流的比特率,整数,单位bps。
-
-ac channels:设置音频流的声道数目。
(3)常用输出选项
-
-f fmt:强制设定文件格式,需使用能力集列表中的名称(缺省是根据扩展名选择的)。
-
-c codec:指定编码器,需使用能力集列表中的名称(编码器设定为”copy“表示不进行编解码)。
-
-acodec codec:指定声音的编码器,需使用能力集列表中的名称(编码器设定为”copy“表示不进行编解码)。
-
-vcodec codec:指定视频的编码器,需使用能力集列表中的名称(编解码器设定为”copy“表示不进行编解码)。
-
-r fps:设定视频编码器的帧率,整数,单位fps。
-
-pix_fmt format:设置视频编码器使用的图像格式(如RGB还是YUV)。
-
-ar sample rate:设定音频编码器的采样率,整数,单位Hz。
-
-b bitrate:设定音视频编码器输出的比特率,整数,单位bps。
-
-ab bitrate:设定音频编码器输出的比特率,整数,单位bps。
-
-ac channels:设置音频编码器的声道数目。
-
-an 忽略任何音频流。
-
-vn 忽略任何视频流。
-
-t hh:mm:ss[.xxx]:设定输出文件的时间长度。
-
-to hh:mm:ss[.xxx]:如果没有设定输出文件的时间长度的画可以设定终止时间点。
(4)流标识
FFMPEG的某些选项可以对一个特定的媒体流起作用,这种情况下需要在选项后面增加一个流标识。流标识允许以下几种格式:
-
流序号。譬如“:1”表示第二个流。
-
流类型。譬如“:a“表示音频流,流类型可以和流序号合并使用,譬如“:a:1”表示第二个音频流。
-
节目。节目和流序号可以合并使用。
-
流标识。流标识是一个内部标识号。
假如要设定第二个音频流为copy,则需要指定-codec:a:1 copy
(5)音频选项
-
-aframes:等价于frames:a,输出选项,用于指定输出的音频帧数目。
-
-aq:等价于q:a,老版本为qscale:a,用于设定音频质量。
-
-atag:等价于tag:a,用于设定音频流的标签。
-
-af:等价于filter:a,用于设定一个声音的后处理过滤链,其参数为一个描述声音后处理链的字符串。
(6)视频选项
-
-vframes:等价于frames:v,输出选项,用于指定输出的视频帧数目。
-
-aspect:设置宽高比,如4:3、16:9、1.3333、1.7777等。
-
-bits_per_raw_sample:设置每个像素点的比特数。
-
-vstats:产生video统计信息。
-
-vf:等价于filter:v,用于设定一个图像的后处理过滤链,其参数为一个描述图像后处理链的字符串。
-
-vtag:等价于tag:v,用于设定视频流的标签。
-
-force_fps:强制设定视频帧率。
-
-force_key_frames:显式控制关键帧的插入,参数为字符串,可以是一个时间戳,也可以是一个“expr:”前缀的表达式。如“-force_key_frames 0:05:00”、“-force_key_frames expr:gte(t,n_forced*5)”
(7)高级选项
-
-re:要求按照既定速率处理输入数据,这个速率即是输入文件的帧率。
-
-map:指定输出文件的流映射关系。例如 “-map 1:0 -map 1:1”要求将第二个输入文件的第一个流和第二个流写入到输出文件。如果没有-map选项,ffmpeg采用缺省的映射关系。
4 ffmpeg使用示例
(1)视频播放
- 播放视频
ffplay input.mp4
- 播放完自动退出
ffplay -autoexit input.mp4
- 设置视频的屏幕高宽比
ffmpeg -i input.mp4 -aspect 16:9 output.mp4
(2)视频压缩与拼接
- 视频压缩
ffmpeg -i demo.mp4 -vcodec h264 -vf scale=640:-2 -threads 4 result.mp4
ffmpeg -i demo.mp4 -strict -2 -vcodec h264 result.mp4
- 将4个视频拼接成一个很长的视频(无声音)
ffmpeg -i 0.mp4 -i 1.mp4 -i 2.mp4 -i 3.mp4 -filter_complex '[0:0][1:0] [2:0][3:0] concat=n=4:v=1 [v]' -map '[v]' output.mp4
- 将3个视频拼接成一个很长的视频(有声音)
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -filter_complex '[0:0][0:1] [1:0][1:1] [2:0][2:1] concat=n=3:v=1:a=1 [v][a]' -map '[v]' -map '[a]’ output.mp4
- 横向拼接2个视频
ffmpeg -i 0.mp4 -i 1.mp4 -filter_complex "[0:v]pad=iw*2:ih*1[a];[a][1:v]overlay=w" out.mp4
- 竖向拼接2个视频
ffmpeg -i 0.mp4 -i 1.mp4 -filter_complex "[0:v]pad=iw:ih*2[a];[a][1:v]overlay=0:h" out_2.mp4
- 横向拼接3个视频
ffmpeg -i 0.mp4 -i 1.mp4 -filter_complex "[0:v]pad=iw:ih*2[a];[a][1:v]overlay=0:h" out_2.mp4
- 竖向拼接3个视频
ffmpeg -i 0.mp4 -i 1.mp4 -i 2.mp4 -filter_complex "[0:v]pad=iw:ih*3[a];[a][1:v]overlay=0:h[b];[b][2:v]overlay=0:2.0*h" out_v4.mp4
- 4个视频2x2方式排列
ffmpeg -i 0.mp4 -i 1.mp4 -i 2.mp4 -i 3.mp4 -filter_complex "[0:v]pad=iw*2:ih*2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" out.mp4
(2)视频帧操作
- 查看每帧的信息
ffprobe -v error -show_frames gemfield.mp4
- 从一个视频文件中抽取一帧图像
ffmpeg -y -i demo.mp4 -ss 00:03:22.000 -vframes 1 -an result.jpg
- 查看视频总帧数
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 gemfield.mp4
- 查看视频总帧数
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 gemfield.mp4
- 查看 key frame 帧数
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 -skip_frame nokey gemfield.mp4
- 查看 key frame 所在的时间
ffprobe -v error -skip_frame nokey -select_streams v:0 -show_entries frame=pkt_pts_time -of csv=print_section=0 gemfield.mp4
- 查看 key frame 分布的情况
ffprobe -v error -show_frames gemfield.mp4 | grep pict_type
- 查看 key frame 所在的帧数
ffprobe -v error -select_streams v -show_frames -show_entries frame=pict_type -of csv gemfield.mp4 | grep -n I | cut -d ':' -f 1
- 重新设置 key frame interval
ffmpeg -i gemfield.mp4 -vcodec libx264 -x264-params keyint=1:scenecut=0 -acodec copy out.mp4
- 查看视频波特率
ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 gemfield.mp4
(3)图片与视频
- 从一个视频生成一个分辨率修改为640*640的新视频
ffmpeg -i demo.avi -vf scale=640:640 result.avi
- 从视频中抽取视频(让视频静音)
ffmpeg -i video_input.mp4 -an -video_output.mp4
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
- 截取一张352x240尺寸大小的,格式为jpg的图片
ffmpeg -i test.asf -y -f image2 -t 0.001 -s 352x240 a.jpg
- 把视频的前30帧转换成一个Animated Gif
ffmpeg -i test.asf -vframes 30 -y -f gif a.gif
- 截取指定时间的缩微图
ffmpeg -i test.avi -y -f image2 -ss 8 -t 0.001 -s 350x240 test.jpg
- 将一个avi文件转成mp4格式
ffmpeg -i demo.avi -acodec copy -vcodec copy result.mp4
- 为视频增加字幕
ffmpeg -i video.mp4 -i subtitles.srt -c:v copy -c:a copy -preset veryfast -c:s mov_text -map 0 -map 1 output.mp4
- 转换文件为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
- 将一个mp4文件的音视频流实时转码之后发送给某个远程设备,远程设备可以通过http获取的sdp文件来接收rtp媒体数据。
ffmpeg -re -i demo.mp4 -acodec copy -vcodec libx264 -s 480x270 -map 0:0 -f rtp rtp://10.10.10.100:1234 -map 0:1 -f rtp rtp://10.10.10.100:1238 > /var/www/live.sdp
- 使用ffmpeg录像屏幕
ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -vd x11:0,0 -s 1024x768 ~/test.avi
- 重新调整视频尺寸大小
ffmpeg -vcodec mpeg4 -b 1000 -r 10 -g 300 -i ~/test.avi -s 800×600 ~/test-800-600.avi
- 把摄像头的实时视频录制下来,存储为文件
ffmpeg -f video4linux -s 320*240 -r 10 -i /dev/video0 test.asf
- 图片转视频(规则的名称)
ffmpeg -f image2 -i 'in%6d.jpg' -vcodec libx264 -r 25 -b 200k test.mp4
- 图片转视频(不规则的名称)
方法1:不规则图片名称合成视频文件
ffmpeg -framerate 10 -pattern_type glob -i '*.jpg' out.mp4
cat *.png | ffmpeg -f image2pipe -i - output.mp4
方法2:先动手把不规则文件重命名规则图片名。
def getTpyeFile(filelist, type):
res = []
for item in filelist:
name, suf = os.path.splitext(item) # 文件名,后缀
if suf == type:
res.append(item)
return res
pwd = os.getcwd() # 返回当前目录的绝对路径
dirs = os.listdir() # 当前目录下所有的文件名组成的数组
typefiles = getTpyeFile(dirs, '.jpg')
for i in range(0,len(typefiles)):
os.rename(typefiles[i],"./%d.jpg" % (i)) #将文件以数字规则命令
将需要合成的图片放在txt中,通过读取txt文件合并成视频。
ffmpeg -f concat -i files.txt output.mp4
- 压缩视频文件
ffmpeg -i video_input.mp4 -r 24 video_output.mp4
- 通过压缩音频来降低视频文件的体积
ffmpeg -i video_input.mp4 -c:v libx264 -ac 2 -c:a aac -strict -2 -b:a 128k -crf 28 video_output.mp4
(4)音频处理
- 音频播放
ffplay demo.ape
- 显示波形图
ffplay -showmode 1 demo.ape
- 显示频谱图
ffplay -showmode 2 demo.ape
- 从视频中抽取音频
ffmpeg -i video.mp4 -vn audio.mp3
- 指定编码比特率从视频中抽取音频
ffmpeg -i video.mp4 -vn -ab 128k audio.mp3
- 为音频增加封面图片
ffmpeg -loop 1 -i image.jpg -i audio.wav -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest output.mp4
- 使用alsa接口录制一段音频存放到某个wav文件中
ffmpeg -f alsa -i hw:0 -t 100 result.wav
- 使用alsa接口搭建一个个人网络电台
ffmpeg -f alsa -i default -acodec aac -strict -2 -b:a 128k -r 44100 /var/www/data/main.m3u8
- 压缩媒体文件
ffmpeg -i audio_input.mp3 -ab 128k audio_output.mp3
ffmpeg -i audio_input.mp3 -b:a 192k audio_output.mp3
(5)格式转换
- MPEG4编码转成H264编码
ffmpeg -i input.mp4 -strict -2 -vcodec h264 output.mp4
- H264编码转成MPEG4编码
ffmpeg -i input.mp4 -strict -2 -vcodec mpeg4 output.mp4
- webp转换成jpg
ffmpeg -i in.webp out.jpg
- webp转换成png
ffmpeg -i in.webp out.png
- jpg转换成png
ffmpeg -i in.jpg out.png
- jpg转换成webp
ffmpeg -i in.jpg out.webp
- png转换成webp
ffmpeg -i in.png out.webp
- png转换成jpg
ffmpeg -i in.png out.jpg
(6)其它指令
- 查看FFmpeg支持的编码器
ffmpeg configure -encoders
- 查看FFmpeg支持的解码器
ffmpeg configure -decoders
- 查看FFmpeg支持的通信协议
ffmpeg configure -protocols
- 查看FFmpeg所支持的音视频编码格式、文件封装格式与流媒体传输协议
ffmpeg configure --help
- 从开始裁剪媒体文件
ffmpeg -i input_video.mp4 -t 5 output_video.mp4
ffmpeg -i input_audio.wav -t 00:00:05 output_audio.wav
- 剪辑中间一段媒体文件
通过 -ss 给出一个开始时间,-to 给出结束时间
ffmpeg -i input_audio.mp3 -ss 00:01:14 output_audio.mp3
ffmpeg -i input_audio.wav -ss 00:00:30 -t 10 output_audio.wav
ffmpeg -i input_video.h264 -ss 00:01:30 -to 00:01:40 output_video.h264
ffmpeg -i input_audio.ogg -ss 5 output_audio.ogg