2passes法生成高质量动图
ffmpeg开发者有提供一种2passes生成高质量动图的方法
不过个人来说有一些理由导致不会用这个方法:
- 2pass会执行两遍编码,太麻烦了,速度也会慢很多。
- 这个方法不知道是否支持了webp,gif动图的最大问题是体积实在太大了
- 动图其实并不需要太高的画质,gif的体积来说甚至比直接截取视频的大小还要大。不如直接用视频格式
使用2passes方法需要手动输入很多参数,因此推荐编写一个脚本:
#!/bin/sh
start_time=12:23
duration=35
palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos"
ffmpeg -v warning -ss $start_time -t $duration -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -v warning -ss $start_time -t $duration -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2
-
-ss
指定开始截取的时间 -
-t
指定截取的时长 - 也可以用
-to
指定截取结束的时间 - 如果不指定截取时间,会默认截取整个视频
- fps 指定帧率
- scale 指定缩放相关的参数 320:-1 是只指定了宽是320,高为-1就是相当于不指定,会按比例自动计算
- flags指定插值算法 lanczos是精度比较高的插值算法,比默认的算法要好一些。
libwebp生成webp动图
因为gif动图体积太大,色彩也不行,所以我还是更喜欢webp的动图,毕竟是google推行的技术,所有chrome内核的浏览器应该都支持了。。
ffmpeg的libwebp应该是用谷歌的libwebp来开发的,具体可以看看谷歌这边有哪些功能 https://github.com/webmproject/libwebp
具体如下使用就行了,因为ffmpeg会根据你的产物后缀名自动选择编码器,所以你也不需要特别指定
ffmpeg -v warning -i input.mkv -ss 121.371 -to 141.35 -loop 0 -vf "fps=8,scale=iw/3:ih/3" out.webp
- loop 是指定webp动图的循环次数的,0表示无线循环播放
使用subtitles filter生成带字幕的webp动图
如果你是内置字幕的视频,或者外挂字幕的视频,上面的命令生成的动图不会带字幕
内置字幕的好处是减少了文件数目,而且可以控制字幕开关,如果是内嵌也就是字幕被渲染到视频里面,那就是我这种收藏的最不喜欢的一类。总体来说最方便的还是外挂字幕了。
如果你的字幕是内置字幕,你只需要按照下面的指定 subtitles=input.mkv
,指定文件名后,ffmpeg就会自动寻找字幕了,也可以再指定 si,也就是多条字幕的时候指定具体哪一条
ffmpeg -v warning -i input.mkv -ss 121.371 -to 141.35 -loop 0 -vf "fps=8,scale=iw/3:ih/3,subtitles='input.mkv'" out.webp
如果你的字幕是外挂字幕,那么只要指定字幕为外挂字幕路径,si为0表示这条弹幕
ffmpeg -v warning -i input.mkv -ss 121.371 -to 141.35 -loop 0 -vf "fps=8,scale=iw/3:ih/3,subtitles='input.ass':si=0" out.webp
[图片上传失败...(image-8aa786-1621162166468)]
调整字幕到正确的时间
注意以上方法,生成的带字幕动图,字幕会从0秒的部分开始.
这是因为ffmepg在对视频seek之后会重置时间戳,所以我们可以用copyts 选项拷贝时间戳,然后重设时间戳解决这个问题
ffmpeg -v warning -copyts -i input.mkv -ss 121.371 -to 141.35 -loop 0 -vf "fps=8,scale=iw/3:ih/3,subtitles='input.mkv'" -ss 121.371 out.webp