【注意】最后更新于 June 2, 2019,文中内容可能已过时,请谨慎使用。
一些ffmpeg处理视频笔记。
裁剪黑边
主要使用 ffmpeg 的 crop
以及 cropdetect
参数。
视频左上角为坐标(0,0),单位为像素。
1
2
3
4
5
6
7
8
9
10
11
12
|
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 为默认值,更多请移步 [官方文档](https://www.ffmpeg.org/ffmpeg-filters.html#cropdetect)
|
关于 crop,第一个 1840 表示裁剪出来的矩形长1840像素,宽1072像素,从(40,0)坐标处开始裁剪。crop官方文档。
除了使用 ffmpeg 的 cropdetect 参数外,可以截取一张视频图片,使用 GIMP 等图像工具,手动测量得到需要的参数。
以 GIMP 为例:
1. 拉出参考线,Ctrl+鼠标滚轮放大,M 移动工具;
2. Shift + M 换到测量工具,Ctrl 拉出水平垂直测量线。
去水印
和裁剪黑边类似,使用 delogo
命令,官方文档。
同样需要定位位置,使用上面提到的 GIMP 测量坐标。
delogo=x=1742:y=992:w=132:h=40
,如其意,x y坐标起点(左上角0、0),w h宽和高。
一次可以定义多个去水印位置,使用 ,
分隔,放置在滤镜参数里面。例子如下:
1
2
3
4
|
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-scripts/blob/master/speed_up_video.sh
视频
1.7 倍速:
1
2
3
|
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来完成,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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
|
音视频提取与合并
提取
1
2
3
4
|
# 提取视频
ffmpeg -i input.mp4 -c:v copy -an video.mp4
# 提取音频
ffmpeg -i input.mp4 -c:a copy -vn audio.m4a
|
其中 v 视频,a 音频。
合并
1
2
3
4
5
6
7
8
9
|
# 视频 音频 (字幕)分别单文件
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,
添加如下参数
1
2
3
4
5
6
7
8
|
# 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 后可能会遇到下面的报错,
1
|
Too many packets buffered for output stream 0:1.
|
只需要多加一个 -max_muxing_queue_size 1024
参数在其中即可解决,详见这里。
添加参数 -hide_banner 即可。
- libx265 2pass 遇到如下错误,卡住不动
1
2
3
|
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 相同容器复制一份,使用新生成的文件成功缩放压制。
1
|
[swscaler @ 0x558c475f32c0] Warning: data is not aligned! This can lead to a speed loss
|
修改 宽度 为 16 的倍数。参考文档。