如何用FFMpeg生成视频( 二 )


解决办法有两种:一是降低帧率(不推荐),二是增加图片数量(推荐) 。
我一开始是通过降低帧率来提高时长(我的需求是同一张图片要显示10秒左右),因为25FPS就是一秒25张图片,那如果设置为0.1FPS,等同于1张图片10秒,测试如下:
$ ffmpeg -r 0.1 -i img001.jpg -vcodec libx264 -pix_fmt yuv420p one_img_to_video_small_rate.mp4复制代码通过下图,可以看到延长时长的目的确实达到了,但是这种方式生成的MP4其实是有问题的,不仅剪辑软件无法支持(比如剪映),在添加音频、字幕的时候也非常奇怪(血的教训) 。

如何用FFMpeg生成视频

文章插图
 
第二种方式是增加图片数量,这也是我使用剪映之后发现的,因为与剪映拖动图片增加视频长度的原理是一致的:
如何用FFMpeg生成视频

文章插图
 
批量增加图片可以随便写个脚本就可以得到,但是图片的数量需要计算一下,比如一个时长10秒,帧率25FPS的视频就需要 10 x 25 = 250张图片:
# 输入为多张图片时,可使用这种写法# %03d 其实就是 001、002、003...100$ cd img_to_video$ ffmpeg -r 25 -i img/img%03d.jpg -vcodec libx264 -pix_fmt yuv420p multi_img_to_video.mp4复制代码这里可能有人会疑惑,为什么每次我都会带上 -pix_fmt yuv420p参数?这其实也是一个坑,因为如果不加这个参数,有些软件没办法识别生成的MP4文件,比如mac 的QuickTime Player 。
原因可以从官方文档得到,因为我们生成视频的方式其实是通过图像序列(一系列的图片)的方式,对应的编码类型为image2,这也是为什么有时在一些文章上可以看到他们的命令比上述命令多了 -f image2参数(加不加都无所谓) 。在这种编码下,默认的pix_fmt参数并不是yuv420p,而是通过第一张图片得到,而JPG图片用的都是RGB,所以最终生成的视频无法识别 。
3.2 视频添加音频通过上面的方式生成的视频是没有声音的,所以我们需要通过FFMpeg为其加上音频 。
有时候我们得到的音频格式并不是MP3,而是WAV,这时我们可以通过下面的命令进行转换:
$ ffmpeg -i input.wav -vn -ar 44100 -ac 2 -b:a 192k output.mp3-i: 上文也提到过,即我们的输入文件-vn:禁用视频,确保没有视频被包括在内-ar:设置音频采样频率 。对于输出流,它默认设置为相应的输入流的频率 。对于输入流,这个选项只对音频抓取设备和原始解复用器有意义,并被映射到相应的解复用器选项中 。-ac:设置音频通道的数量 。这里为2是为了确保它是立体声(2个通道) 。对于输出流,它默认设置为输入音频通道的数量 。对于输入流,这个选项只对音频抓取设备和原始解复用器有意义,并被映射到相应的解复用器选项中 。-b:a:将音频比特率(audio bitrate)转换为精确的192kbit/秒复制代码上面的解释涉及到解复用这个术语,那什么是解复用呢?当我们打开一个多媒体文件之后,第一步就是解复用,称之为Demux 。为什么需要这一步,这一步究竟是做什么的?我们知道在一个多媒体文件中,既包括音频也包括视频,而且音频和视频都是分开进行压缩的,因为音频和视频的压缩算法不一样,既然压缩算法不一样,那么肯定解码也不一样,所以需要对音频和视频分别进行解码 。虽然音频和视频是分开进行压缩的,但是为了传输过程的方便,还是将压缩过的音频和视频捆绑在一起进行传输 。所以我们解码的第一步就是将这些绑在一起的音频和视频流分开来,也就是传说中的**解复用 。**简单来说,解复用这一步就是将音频流和视频流分开,方便后续解码 。
转换之后就可以为视频添加音频了,这里使用的视频是上文生成的图片视频(注意添加音频也能用wav格式,只不过我习惯用mp3)
# 拷贝视频$ cp img_to_video/multi_img_to_video.mp4 add_audio/input.mp4# 添加音频有多种方式:# 方式一:流拷贝(不推荐)# 这种方式没有编解码的过程,只有解复用,所以速度很快,目前亲测不成功,不太建议$ ffmpeg -i input.mp4 -i input.mp3 -codec copy audio_copy.mp4# 方式二:手动选择特定流(不推荐,亲测无效)$ ffmpeg -i input.mp4 -i input.mp3 -map 0:v -map 1:a -c copy audio_manually.mp4# 方式三:重新编码(亲测有效)$ ffmpeg -i input.mp4 -i input.mp3 -c:a aac -c:v libx264 audio_recode.mp4# 有时候我们的音频长度大于视频长度,比如本次音频长度为20s,视频长度为10s,使用上面的命令会把视频长度拉长到20s# 如果想要音频长度与视频长度保持一致,可加上 -shortest 参数$ ffmpeg -i input.mp4 -i input.mp3 -c:a aac -c:v libx264-shortest audio_recode_short.mp4复制代码


推荐阅读