管道PIL图像到ffmpeg stdin - Python

blu*_*ers 13 python ffmpeg python-imaging-library phantomjs

我正在尝试将html5视频转换为mp4视频,并且我是通过PhantomJS随着时间的推移进行屏幕拍摄

我也使用PIL裁剪图像,所以最终我的代码大致是:

while time() < end_time:
    screenshot_list.append(phantom.get_screenshot_as_base64())
.
.
for screenshot in screenshot_list:
    im = Image.open(BytesIO(base64.b64decode(screenshot)))
    im = im.crop((left, top, right, bottom))
Run Code Online (Sandbox Code Playgroud)

现在我正在保存以删除所有这些图像并使用保存文件中的ffmpeg:

os.system('ffmpeg -r {fps} -f image2 -s {width}x{height} -i {screenshots_dir}%04d.png -vf scale={width}:-2 '
      '-vcodec libx264 -crf 25 -vb 20M -pix_fmt yuv420p {output}'.format(fps=fps, width=width,
                                                                  screenshots_dir=screenshots_dir,
                                                                  height=height, output=output))
Run Code Online (Sandbox Code Playgroud)

但我想要而不是使用那些保存的文件,能够将PIL.Images直接传递给ffmpeg,我该怎么做?

blu*_*ers 9

赏金消失了,但我找到了解决方案.

在获取所有屏幕截图作为base64字符串之后,我将它们写入具有以下代码的子进程中

import subprocess as sp

# Generating all of the screenshots as base64 
# in a variable called screenshot_list

cmd_out = ['ffmpeg',
           '-f', 'image2pipe',
           '-vcodec', 'png',
           '-r', '30',  # FPS 
           '-i', '-',  # Indicated input comes from pipe 
           '-vcodec', 'png',
           '-qscale', '0',
           '/home/user1/output_dir/video.mp4']

pipe = sp.Popen(cmd_out, stdin=sp.PIPE)

for screenshot in screenshot_list:
    im = Image.open(BytesIO(base64.b64decode(screenshot)))
    im.save(pipe.stdin, 'PNG')

pipe.stdin.close()
pipe.wait()

# Make sure all went well
if pipe.returncode != 0:
    raise sp.CalledProcessError(pipe.returncode, cmd_out)
Run Code Online (Sandbox Code Playgroud)

如果执行时间有问题,您可以将图像保存为JPEG,并使用适当的编解码器,但我设法达到的最高质量是使用这些设置

  • 感谢您的回答 - 非常有帮助!我认为在您的 cmd_out 列表中,第二个 vcodec 行(适用于输出)应该是“-vcodec”、“libx264”、“而不是“-vcodec”、“png”、“,不是吗? (2认同)