一些ffmpeg处理视频笔记。
裁剪黑边
主要使用 ffmpeg 的 crop 以及 cropdetect 参数。
视频左上角为坐标(0,0),单位为像素。
- ffmpeg -i input.mp4 -vf "cropdetect=24:16:0" dummy.mp4
- # 可以得到如下所示信息
- # [Parsed_cropdetect_0 @ 0x7fab586781c0] x1:36 x2:1883 y1:0 y2:1079 w:1840 h:1072 x:40 y:4 pts:3584 t:0.233333 crop=1840:1072:40:4
- # Ctrl + C 停止,复制 crop=1840:1072:40:4 用于后面步骤
- # 注意视频黑边 是否会变化,否则需取舍使用哪些参数。
- # 也可以使用 ffplay 预览,不用'压制'即可得到 crop 信息。
- ffplay input.mp4 -vf cropdetect=24:16:0
- # 后面的参数 24 16 0 为默认值,更多请移步 [官方文档]([url]https://www.ffmpeg.org/ffmpeg-filters.html#cropdetect[/url])
复制代码
关于 crop,第一个 1840 表示裁剪出来的矩形长1840像素,宽1072像素,从(40,0)坐标处开始裁剪。crop官方文档。
除了使用 ffmpeg 的 cropdetect 参数外,可以截取一张视频图片,使用 GIMP 等图像工具,手动测量得到需要的参数。 以 GIMP 为例: 1. 拉出参考线,Ctrl+鼠标滚轮放大,M 移动工具; 2. Shift + M 换到测量工具,Ctrl 拉出水平垂直测量线。
notes-for-ffmpeg-2019-6-2-18-7-13.png
notes-for-ffmpeg-2019-6-2-18-7-28.png
去水印
和裁剪黑边类似,使用 delogo 命令,官方文档。
同样需要定位位置,使用上面提到的 GIMP 测量坐标。 delogo=x=1742:y=992:w=132:h=40,如其意,x y坐标起点(左上角0、0),w h宽和高。 一次可以定义多个去水印位置,使用 , 分隔,放置在滤镜参数里面。例子如下:
ffmpeg -y -i in.mp4 -vf "delogo=x=1472:y=35:w=408:h=42,delogo=x=1742:y=992:w=132:h=40,crop=1840:1040:40:0" \
-metadata comment='made by rachpt' -max_muxing_queue_size 1024 out.mp4
两个水印,加上裁剪黑边。
效果对比如下:
倍速
详见:
https://github.com/rachpt/shell- ... r/speed_up_video.sh
视频
1.7 倍速:
- ffmpeg -i "$i" -r 30 -c:v libx264 -preset fast \
- -filter_complex "[0:v]setpts=10/17 *PTS[v];[0:a]atempo=1.7[a]" \
- -map "[v]" -map "[a]" "../encode/$i" -y
复制代码
音频
如上,[0:a]atempo=1.7[a]。
字幕
使用shell来完成,
- for i in `grep -Eo '([0-9]{2}:){2}[0-9]{2},[0-9]{3}' "$file"` ;do
- a=${i:0:2};
- b=${i:3:2};
- c=${i:6:2};
- d=${i:9:3};
- # 匹配视频 1.7 倍速
- total=`echo "scale=0;((($a*60+$b)*60+$c)*1000+$d)/1.7"|bc`;
- e=$((total % 1000));f=$((total / 1000));
- g=$((f % 60));
- h=$((f / 60));x=$((h % 60));
- y=$((h / 60)) ;
- j=`printf "%02d:%02d:%02d,%03d\n" $y $x $g $e`;
- sed -i "s/$i/$j/" "$file";
- done
- # 最后封装在一起参数
- ffmpeg -i in.mp4 -i sub.srt -c:s mov_text -c:v copy -c:a copy out.mp4
复制代码
音视频提取与合并
提取
- # 提取视频
- ffmpeg -i input.mp4 -c:v copy -an video.mp4
- # 提取音频
- ffmpeg -i input.mp4 -c:a copy -vn audio.m4a
复制代码
其中 v 视频,a 音频。
合并
- # 视频 音频 (字幕)分别单文件
- ffmpeg -i input.mp4 -i audio.m4a -i sub.srt -c:v copy -c:a copy -c:s mov_text output.mp4
- # 视频里面有音轨,需要替换音轨
- ffmpeg -i input.mp4 -i audio.m4a -c:v copy -c:a copy -map 0✌️0 -map 1🅰️0 output.mp4
- # 追加音轨,再加一个 -map 0🅰️0
- # 封装多字幕
- ffmpeg -i input.mp4 -i chs.srt -i eng.srt -c copy -map 0:0 -map 0:1 -map 1:0 -map 2:0 \
- -c:s mov_text -c:s mov_text output.mp4
复制代码
map 参数第一个表示 输出文件,0 第一个,1 第二个,v/a 和上面提到的一样,表示视频 / 音频,最后面的数字表示输入文件里面的第几个视频 / 音频 轨道。通常一个视频 一个视频轨道一个音频轨道,这个需要自己看 mediainfo。
删除压制信息
删除视频文件 mediainfo 里面的 Writing library 和 Encoding settings, 添加如下参数
- # x265
- -x265-params no-info=1
- # x264 (ffmpeg 4.0+)
- -bsf:v 'filter_units=remove_types=6'
- # 删除 General 里面的附加信息
- -map_metadata -1
复制代码
参考文档一,文档二。
停止播放
ffplay 使用 -t 时间 可以只播放一小段,但是并不会到时间后退出播放,而是会处于等待状态。 添加 -autoexit 参数即可解决该问题。
其他
使用 -ss 0:0:0 -t 1:0:0 后可能会遇到下面的报错,
- Too many packets buffered for output stream 0:1.
复制代码
只需要多加一个 -max_muxing_queue_size 1024 参数在其中即可解决,详见这里。
隐藏 版本信息编译参数
添加参数 -hide_banner 即可。
libx265 2pass 遇到如下错误,卡住不动
- cur_dts is invalid (this is harmless if it occurs once at the start per stream)
- 在不同机器上,不同版本 ffmpeg 使用相同的压制命令却不会遇到这个问题。
- 另外,换用 libx264 不会遇到此问题。
复制代码
多番查证,可能是原视频某些信息不全所致。 最终发现是 使用的 缩放 (-s 1280x720 或者 滤镜 - vf scale=-2:720) 参数导致的,去掉缩放,2pass 不会遇到此问题。
最后曲线救国,先将原文件使用 ffmpeg -c copy 相同容器复制一份,使用新生成的文件成功缩放压制。
缩放警告
- [swscaler @ 0x558c475f32c0] Warning: data is not aligned! This can lead to a speed loss
复制代码
修改 宽度 为 16 的倍数。参考文档。