I'm trying to convert an html5 video to mp4 video and am doing so by screen shooting through PhantomJS over time
I'm also cropping the images using PIL so eventually my code is roughly:
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))
Right now I'm saving to disc all those images and using ffmpeg from saved files:
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))
But I want instead of using those saved files, to be able to pipe the PIL.Images directy to ffmpeg, how can I do that?
Bounty is gone, but I found the solution.
After acquiring all of the screenshots as base64 strings I write them into a subprocess with the following code
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)
If execution time is an issue, you can save the images as JPEGs instead, and use appropriate codecs for that, but the highest quality I managed to achieve was with these settings
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With