我有一个程序,可以生成图像并用它们创建视频。目前的工作是一次创建所有图像,然后在一个子进程中运行FFmpeg并通过stdin管道将图像传送到创建一个视频:
cmd = ['ffmpeg', '-y',
'-s', '{}x{}'.format(OUTPUT_WIDTH, OUTPUT_HEIGHT),
'-r', str(OUTPUT_VIDEO_FPS),
'-an',
'-pix_fmt', colour,
'-c:v', 'rawvideo', '-f', 'rawvideo',
'-i', '-',
'-vcodec', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'medium', OUTPUT_VIDEO_PATH]
out_frames = []
for i in range(num_frames):
out_frame = render_frame(...)
out_frames.append(out_frame)
with _call_subprocess(sp.Popen(cmd, stdin=sp.PIPE, stderr=sp.PIPE, stdout=DEVNULL)) as pipe:
for frame_no, frame in enumerate(out_frames):
pipe.stdin.write(frame)
但是,当我有数千个图像不能全部放入内存时,这就变得不可行了,因为子进程fork call请求了太多内存而失败了。我的解决方案是在程序开始时分叉(避免内存错误),然后在创建帧时将其管道传输到stdin:
^{pr2}$但是,ffmpeg的输出现在已损坏。我很确定这与我现在渲染帧时写入stdin之间有一些处理时间有关-我注意到,如果我使用第一个解决方案,但只需在写入stdin之间添加一些睡眠时间,输出也会损坏!在
cmd = ['ffmpeg', '-y',
'-s', '{}x{}'.format(OUTPUT_WIDTH, OUTPUT_HEIGHT),
'-r', str(OUTPUT_VIDEO_FPS),
'-an',
'-pix_fmt', colour,
'-c:v', 'rawvideo', '-f', 'rawvideo',
'-i', '-',
'-vcodec', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'medium', OUTPUT_VIDEO_PATH]
out_frames = []
for i in range(num_frames):
out_frame = render_frame(...)
out_frames.append(out_frame)
with _call_subprocess(sp.Popen(cmd, stdin=sp.PIPE, stderr=sp.PIPE, stdout=DEVNULL)) as pipe:
for frame_no, frame in enumerate(out_frames):
time.sleep(1) # <------------------- This sleep ruins everything!!
pipe.stdin.write(frame)
然而,我不知道是什么导致了这个问题,或者如何修复它(FFmpeg不知怎么地轮询了一个空管道,然后被破坏了?我甚至不明白子进程通信是如何工作的。任何帮助都将不胜感激。在
不知道这是为什么,但是将
sp.Popen
调用从sp.Popen(cmd, stdin=sp.PIPE, stderr=sp.PIPE, stdout=DEVNULL)
改为sp.Popen(cmd, stdin=sp.PIPE, stderr=DEVNULL, stdout=DEVNULL)
起作用了。我猜这和this SO question about piping issues with stderr有关。在相关问题 更多 >
编程相关推荐