梳理下 FFmpeg 的一些有用的命令

最近在探索图像处理类应用端到端耗时如何量化,最终方案是:

录视频 -> FFmpeg 分帧 -> 根据帧数量化耗时。

另外,平时自己从网上爬取 m3u8 视频,也会用到 FFmpeg。

所以,这里梳理下 FFmpeg 的一些比较有用的命令。

图片

格式转换

jpg -> yuv

ffmpeg -y -i x.jpg -pix_fmt nv21 x.yuv

yuv -> jpg

ffmpeg -f rawvideo -video_size 720x1280 -pix_fmt nv21 -i x.yuv x.jpg

编辑

缩放

ffmpeg -i in.jpg -vf scale=320:240 out.png

如果需要宽/高自适应缩放,传入 -1 即可;

背景透明

ffmpeg -i mask.png -vf 'colorkey=0xFFFFFF:similarity=0.5:blend=0' out.png
  • similarity: 相似度,范围 [0, 1];0 表示仅匹配前面指定的颜色,1 表示匹配一切颜色;(一般 0.5 效果较好)

  • blend: 混合度,范围 [0, 1];0 表示要么完全透明,要么完全不透明;更高的值表示会有半透明的像素;

详见 colorkey 滤镜;

音频

调整音频参数

调整音频音量

ffmpeg -i input.wav -filter:a "volume=1.5" output.wav

调整音频码率

ffmpeg -i input.mp3 -b:a 400k output.mp3

调整音频采样率

ffmpeg -i input.mp3 -ar 44100 output.mp3

其他

音频截取

ffmpeg -i in.mp3 -ss 00:01:30 -to 00:02:30 -c copy out.mp3

给音频添加封面

ffmpeg -i input.mp3 -i cover.png -c copy -metadata:s:v title="Album cover" -metadata:s:v comment="Cover.." out.mp3

音频 -> 波形图

ffmpeg -i x.mp3 -filter_complex "showwavespic=s=640x240:split_channels=1" -frames:v 1 wave.png

动画

GIF

图片序列 -> gif

ffmpeg -f image2 -framerate 5 -i x-%3d.jpg x.gif
  • x-%3d 表示 jpg 图片名都是 x- 前缀,后跟三位数字。

视频 -> gif

ffmpeg -i x.mp4 -r 15 drawtext="enable='between(t,10,5*60)': text='我是字幕': x=(w-text_w)/2: y=(h-text_h-10) fontfile=/usr/share/fonts/xxx.ttf fontcolor=white: fontsize=15: shadowcolor=black@0.5: shadowx=2: shadowy=2:" x.gif
  • -r 15:帧率,跟动画连续性、文件大小都正相关;

  • enable='between(t,10,5*60)':从第 10 秒开始,5 分钟结束;

  • x=(w-text_w)/2: y=(h-text_h-10):文字位置(水平居中,距底部 10 像素);

视频

视频合成

图片序列 -> 视频

ffmpeg -r 5 -i x-%3d.jpg -c:v libx264 -vf fps=25 -pix_fmt yuv420p xxx.mp4

图片序列+音频 -> 视频

ffmpeg -loop 1 -t 6 -i x-%3d.jpg -i x.mp3 -c:v libx264 -c:a aac -b:a 192k -shortest xxx.mp4

音频与视频混合

ffmpeg -i xxx.wav -i xxx.avi xyz.mp4

视频序列合并

ffmpeg -f concat -i list.txt -c copy x.mp4

list.txt 每行记录一个视频:

file1.mp4’
file2.mp4’
file3.mp4’
...

视频提取图

视频 -> 图片序列

ffmpeg -t 10 -i x.mp4 -r 15 -s 272x352 -f image2 x-%03d.jpg

截取视频某时刻的帧

ffmpeg -i x.mp4 -ss 00:00:03.210 -vframes 1 x.png

同时使用 blackframe 滤镜可过滤黑色的帧:

ffmpeg -ss 0 -i input.mp4 -vframes 1 -f image2 -vf "blackframe=0,metadata=select:key=lavfi.blackframe.pblack:value=50:function=less" out.jpg

视频每秒截取一帧

ffmpeg -i x.mp4 -vf fps=1 x-%d.png

视频提取音频

去除视频里的音频

ffmpeg -i input.mp4 -an output.mp4

导出视频里的音频

ffmpeg -i xxx.avi -vn -ar 44100 -ac 2 -ab 192k -f mp3 xxx.mp3

视频提取视频

视频片段截取

ffmpeg -i x.mp4 -ss 00:00:03 -t 00:00:08 -async 1 xxx.mp4

注意:t 是时长,不是结束时间!

视频裁剪

ffmpeg -i input.mp4 -filter:v "crop=w:h:x:y" output.mp4

视频参数修改

调整视频分辨率

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

调整视频码率

ffmpeg -i input.mp4 -b:v 400k output.mp4

调整视频中音频播放速度

ffmpeg -i input.mp4 -filter:a "atempo=2.0" -vn output.mp4
  • atempo 取值为 0.5-2.0;

调整视频播放速度

ffmpeg -i video.mpg -vf "setpts=0.5*PTS" highspeed.mpg
  • PTS 倍数 < 1 表示加速

视频水印

给视频添加静态水印

添加水印主要是使用 overlay 滤镜:

ffmpeg -i x.mp4 -i logo.png -filter_complex "overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2" xxx.mp4
  • mian_wmain_h 表示视频宽高;

  • overlay_woverlay_h 表示水印图宽高;

  • 通过 enable='between(t,0,20)' 可指定水印出现的时间;

给视频添加移动水印

ffmpeg -i x.mp4 -i logo.png -filter_complex "overlay='if(gte(t,1), -w+(t-1)*200, NAN)':'if(gte(t,1), -h+(t-1)*200, NAN)'" xxx.mp4

去掉视频的水印

去水印主要是使用 delogo 滤镜,enable 可以指定运用的时间范围:

ffmpeg -i input.mp4 -vf "delogo=x=12:y=34:w=353:h=93:enable='between(t,5,10)'" -c:a copy output.mp4

也可以同时指定多个区域,声明多个 delogo 滤镜即可:

ffmpeg -i input.mp4 -vf "delogo=x=56:y=78:w=353:h=93:enable='between(t,5,10)',delogo=x=100:y=24:w=100:h=72:enable='between(t,15,20)'" -c:a copy output.mp4

视频背景音乐

给视频添加背景音乐

ffmpeg -i input.mp4 -i bg.mp3 -filter_complex "[1:a]aloop=loop=-1:size=2e+09[out];[out][0:a]amix" -t 10 out.mp4

替换原视频中的音频

ffmpeg -i video.mp4 -i audio.wav -map 0:v -map 1:a -c:v copy -shortest output.mp4
  • -map:选择 input 中的哪条流进入 output;

  • -shortest:输出时长以输入时长最小的为准;

给视频添加背景音乐

ffmpeg -i video.mkv -i audio.mp3 -map 0 -map 1:a -c:v copy -shortest output.mkv

绿幕视频

绿幕合成

ffmpeg -i origin.mp4 -i green_bg.mp4 -filter-complex "[1:v]chromakey=Green:0.5:0.2[ckout];[0:v][ckout]overlay[out]" output.mp4

绿幕合成就是将 alpha 为 0 的像素替换为特定颜色(一般为绿色),ffmpeg -colors 可查询 FFmpeg 支持的颜色。

这里核心是 chromakey 滤镜,参数与 colorkey 滤镜类似;

这个滤镜除了能处理视频,还能处理单张 YUV 图。

如果是 RGB 的图,需要用 colorkey 滤镜。

绿幕剔除

ffmpeg -i input.mp4 -vf 'colorkey=0x00FF00:similarity=0.5:blend=0.3' -c copy -c:v vp9 -f webm output.webm

跟图片透明背景类似,这里同样使用 colorkey 滤镜,相关参数不再赘述;

输出格式指定为 webm,是因为它支持 alpha 通道视频。

视频特效

淡入淡出

fade 滤镜可以实现视频淡入淡出的特效,而 afade 滤镜则用于音频:

ffmpeg -i x.mov -vf "fade=t=in:st=0:d=2, fade=t=out:st=6:d=2" -af "volume=2.0, afade=t=in:st=0:d=2, afade=t=out:st=6:d=2" -c:v libx264 -c:a aac -b:a 128k xxx.mp4
  • t=in 表示淡入特效,t=out 表示淡出特效;

  • st=0 表示特效开始时间,d=2 表示特效持续时长;

流媒体处理

m3u8 下载

ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "http://abc.com/xxx.m3u8" -c copy xxx.mp4

格式转换

VCD -> mp4

ffmpeg -i x.VOB x.mp4

.

.

.

广告时间

通过组合上面的命令,可实现一些小工具,如:自制表情包,小视频下载,视频提取音乐、视频编辑等。

有兴趣的可以参考下我的 Videa 项目。