我最近的工作涉及以编程方式制作视频。在python中,典型的工作流程看起来像这样:
import subprocess, Image, ImageDraw
for i in range(frames_per_second * video_duration_seconds):
img = createFrame(i)
img.save("%07d.png" % i)
subprocess.call(["ffmpeg","-y","-r",str(frames_per_second),"-i", "%07d.png","-vcodec","mpeg4", "-qscale","5", "-r", str(frames_per_second), "video.avi"])
此工作流程为视频中的每个帧创建一个图像并将其保存到磁盘。保存完所有图像后,调用ffmpeg从所有图像构建视频。
将图像保存到磁盘(而非在内存中创建图像)会占用此处的大部分周期,并且似乎不需要。有没有办法执行相同的功能,但没有将图像保存到磁盘?因此,将调用ffmpeg并构建图像并在构造后立即将其提供给ffmpeg。
答案 0 :(得分:55)
好的我工作了。感谢LordNeckbeard建议使用image2pipe。我不得不使用jpg编码而不是png because image2pipe with png doesn't work on my verision of ffmpeg。第一个脚本与你的问题代码基本相同,只是我实现了一个简单的图像创建,只创建从黑色到红色的图像。我还添加了一些代码来执行时间。
连续执行
import subprocess, Image
fps, duration = 24, 100
for i in range(fps * duration):
im = Image.new("RGB", (300, 300), (i, 1, 1))
im.save("%07d.jpg" % i)
subprocess.call(["ffmpeg","-y","-r",str(fps),"-i", "%07d.jpg","-vcodec","mpeg4", "-qscale","5", "-r", str(fps), "video.avi"])
并行执行(没有图像保存到磁盘)
import Image
from subprocess import Popen, PIPE
fps, duration = 24, 100
p = Popen(['ffmpeg', '-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '24', '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', '-r', '24', 'video.avi'], stdin=PIPE)
for i in range(fps * duration):
im = Image.new("RGB", (300, 300), (i, 1, 1))
im.save(p.stdin, 'JPEG')
p.stdin.close()
p.wait()
结果很有意思,我运行了每个脚本3次来比较性能: 的串行:强>
12.9062321186
12.8965060711
12.9360799789
并行:
8.67797684669
8.57139396667
8.38926696777
因此,似乎并行版本的速度提高了约1.5倍。
答案 1 :(得分:0)
imageio直接支持此功能。它使用FFMPEG和Video Acceleration API,非常快:
import imageio
writer = imageio.get_writer('video.avi', fps=fps)
for i in range(frames_per_second * video_duration_seconds):
img = createFrame(i)
writer.append_data(img)
writer.close()