FFmpeg将多张图片合成视频

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wangshuainan/article/details/77914508
FFmpeg将多张图片合成视频
从不同目录下多张图合成视频
Pipe
Concat
容易误解的几个命令
FFmpeg将多张图片合成视频
首先要计算出视频的总帧数:

总帧数 = duration * fps 。

duration是我们设定的视频的长度,fps是视频每秒的帧数。

第二步将所有的图片文件放到一个临时目录,并且制定一个命名规则(可正则的):
例如图片的素材是image0.jpg image1.jpg image2.jpg

然后可以执行命令合成视频了:

带音频:

ffmpeg -threads2 -y -r 10 -i /tmpdir/image%04d.jpg -i audio.mp3 -absf aac_adtstoasc output.mp4
1
参数的解释含义:

-threads 2 以两个线程进行运行, 加快处理的速度。

-y 对输出文件进行覆盖

-r 10 fps设置为10帧/秒(不同位置有不同含义,后面再解释)

-i /tmpdir/image%04d.jpg 输入图片文件,图片文件保存为 image0001.jpg image0002.jpg ….

-i audio.mp3 输入的音频文件

-absf aac_adtstoasc 将结果的音频格式转为faac格式时需要这个选项。将音频格式转为faac是因为在iphone上某些音频格式的视频无法播放,例如mp3. 但faac格式的音频的视频在iphone上可以播放。-absf 的意思是设置一个bitstream filter进行某些转换。可以用ffmpeg -bsfs 查看所有支持的bitstream filter。 bitstream filter和 aac_adtstoasc的具体含义我也说不上。但是如果不用这个选项又会导致转换失败。

不带音频

ffmpeg -loop 1 -f image2 -i /tmpdir/image%04d.jpg -vcodec libx264 -r 10 -t 10 test.mp4
1
-loop 1循环读输入 0读完就不读了
-vcode 编码格式libx264
-b 指定200k码率
-t 输出视频总时长:

这样运行命令就可以生成视频了;

从不同目录下多张图合成视频
上面命令需要从指定文件夹下的特殊命名规则的一组图中去做输入文件;有没有更好的方式呢?比如我有一些图片的存储路径,能不能不拷贝到一个文件夹下再操作,答案是有的。

  1. 使用管道Pipe
  2. 使用Concat命令

Pipe
You can use cat or other tools to pipe to ffmpeg:
cat读取多张图片输入到一个“全局管道文件”中,然后后面ffmpeg命令从全局管道中(指定-f image2pipe)读取输入文件,生成视频。

cat Desktop/aa/img1.jpg Desktop/aa/img2.jpg Desktop/aa/img3.jpg | ffmpeg -loop 0 -f image2pipe -r 3 -b 200k -s 640*360 -t 12 -i log.pipe -y Desktop/oup.mkv
1
这个命令在linux、Mac OS、Windows上都是可行的,但是在安卓中不行,可能是ffmpeg找不到那个“全局管道”。
那么我们可以自己创建一个管道,然后告诉ffmpeg管道在哪?

创建管道:

mkfifo Desktop/pic.pipe
1
向管道输入文件:

cat Desktop/aa/img1.jpg Desktop/aa/img2.jpg > Desktop/pic.pipe
1
使用ffmpeg读取管道,生成视频:

ffmpeg -loop 0 -f image2pipe -r 3 -b 200k -s 640*360 -t 12 -i Desktop/pic.pipe -y Desktop/oup.mp4
1
这里pic.pipe的路径子安安卓上要换成安卓的路径:Environment.getExternalStorageDirectory().getAbsolutePath()下面

管道文件非常,非常强大,更多管道知识:

【Linux】mkfifo命令创建命名管道实现进程之间通信
【Linux】进程间通信-命名管道FIFO

Concat
首先,创建个input.txt文件,填写图片信息:

file 文件路径
duration 这张图播放时长

file ‘/Users/wangshuainan/Desktop/aa/imga.jpg’
duration 5
file ‘/Users/wangshuainan/Desktop/aa/imgb.jpg’
duration 1
file ‘/Users/wangshuainan/Desktop/aa/imgc.jpg’
duration 3
file ‘/Users/wangshuainan/Desktop/aa/imgc.jpg’
1
2
3
4
5
6
7
注意!!! 最后一个图要重复写一遍,但不用加duration。

然后run ffmpeg command:

ffmpeg -f concat -safe 0 -i Desktop/input.txt -vsync vfr -pix_fmt yuv420p Desktop/output.mp4
1
这里命令里要加上-safe 0,不然会报unsafe file name的error,不要问我怎么知道的。

参考:

https://trac.ffmpeg.org/wiki/Slideshow

容易误解的几个命令:
下面解释下几个特殊命令的特殊含义:
-t duration
用做输入选项(在-i之前),是限制读取输入文件的的时长;
用做输出选项(before an output url),超过这个时间停止写输出文件;
比如:循环读取一个输入文件时(-loop 1),当到时间就会停止输出,生成一个duration时长的视频。但是如果没有循环选项,而且输入文件短于这个时长时,就会随着输入文件结束就结束,生成视频,视频时长小于duration。所以我们可以看出 -t 并不仅仅是输出文件时长。
当用“管道”时,也不太一样,管道读了之后,里面内容就没了,所以没持续的输入,这个-loop,-t 都是“不起作用的”,除非管道一直有内容。

-t duration (input/output)
When used as an input option (before -i), limit the duration of data read from the input file.

When used as an output option (before an output url), stop writing the output after its duration reaches duration.

duration must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.

-to and -t are mutually exclusive and -t has priority.
1
2
3
4
5
6
7
8
-r fps
帧率,可以指定两个帧率,输入帧率,输出帧率;
输入帧率:-i之前,设定读入帧率,比如 -r 0.5 ,也就是说1秒要播0.5个图片,那么一个图也就是要播2s;
输出频率:-i之后,真正的输出视频播放帧率,不写话,是默认和输入频率一样。比如设 -r 30 ,对应上面的设定,一个图播2
s,那么输出文件播放时,这2s内,都是这张图,但是播放了60帧。

You can specify two frame rates: input and output.

Set input frame rate with the -framerate input option (before -i). The default for reading inputs is -framerate 25 which will be set if no -framerate is specified.
The output frame rate for the video stream by setting -r after -i or by using the fps filter. If you want the input and output frame rates to be the same, then just declare an input -framerate and the output will inherit the same value (meaning you can omit the -r).
By using a separate frame rate for the input and output you can control the duration at which each input is displayed and tell ffmpeg the frame rate you want for the output file. This is useful if your player cannot handle a non-standard frame rate. If the input -framerate is lower than the output -r then ffmpeg will duplicate frames to reach your desired output frame rate. If the input -framerate is higher than the output -r then ffmpeg will drop frames to reach your desired output frame rate.

In this example each image will have a duration of 5 seconds (the inverse of 1/5 frames per second). The video stream will have a frame rate of 30 fps by duplicating the frames accordingly:

ffmpeg -framerate 1/5 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
1
参考:

FFmpeg官网:
http://ffmpeg.org/ffmpeg.html

https://trac.ffmpeg.org/wiki/Slideshow
————————————————
版权声明:本文为CSDN博主「wangshuainan」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangshuainan/article/details/77914508

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章