Last active
September 28, 2024 02:03
-
-
Save alexflint/9609202 to your computer and use it in GitHub Desktop.
Create a video from a sequence of images (or PDFs) in python (using ffmpeg internally)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import tempfile | |
import argparse | |
import subprocess | |
NATURAL_FPS = 30. | |
# Formats convertible by imagemagick: | |
CONVERTIBLE_EXTENSIONS = ['png', 'jpeg', 'jpg', 'pdf', 'pgm', 'bmp'] | |
# Formats readable by ffmpeg: | |
FFMPEG_EXTENSIONS = ['png', 'jpg', 'jpeg'] | |
def extension(path): | |
return os.path.splitext(path)[1][1:].lower() | |
def main(): | |
parser = argparse.ArgumentParser(description='Make a video from a sequence of video frames') | |
parser.add_argument('--limit', type=int, required=False) | |
parser.add_argument('--fps', type=float, default=NATURAL_FPS) | |
parser.add_argument('input', nargs='+', | |
help='Images or PDFs from which to create the video, or a directory '+\ | |
'containing images or pdfs') | |
parser.add_argument('output', type=str) | |
args = parser.parse_args() | |
if os.path.exists(args.output): | |
ext = extension(args.output) | |
if ext in CONVERTIBLE_EXTENSIONS: | |
print 'Error: Cannot overwrite with output: %s' % args.output | |
return -1 | |
# Process input paths | |
input_paths = [] | |
for path in args.input: | |
if os.path.isdir(path): | |
for entry in sorted(os.listdir(path)): | |
if extension(entry) in CONVERTIBLE_EXTENSIONS: | |
input_paths.append(os.path.join(path, entry)) | |
else: | |
input_paths.append(path) | |
if args.limit: | |
input_paths = input_paths[:args.limit] | |
# Pick an intermediate format to convert the frames to | |
temp_ext = extension(input_paths[0]) | |
if temp_ext not in FFMPEG_EXTENSIONS: | |
print '%s files are not readable by ffmpeg: will convert to png.' % temp_ext | |
temp_ext = 'png' | |
# Create symlinks | |
tempdir = tempfile.mkdtemp() | |
index = 0 | |
for index, input_path in enumerate(input_paths): | |
ext = extension(input_path) | |
temp_path = os.path.join(tempdir, '%08d.%s' % (index, temp_ext)) | |
if ext == temp_ext: | |
os.symlink(input_path, temp_path) | |
else: | |
print 'Converting %s to %s' % (input_path, temp_ext) | |
retval = subprocess.call(['convert', input_path, temp_path]) | |
if retval: | |
print 'Unable to convert %s to %s' % (input_path, temp_ext) | |
return -1 | |
# Create video | |
print '\nRunning ffmpeg:' | |
ffmpeg_options = { | |
'-filter:v' : 'setpts=%f*PTS' % (NATURAL_FPS / args.fps), | |
'-b:v' : '1000k', | |
'-f': 'image2', | |
'-i': os.path.join(tempdir, '%%08d.%s' % temp_ext) | |
} | |
command = ['ffmpeg'] | |
for key, value in ffmpeg_options.iteritems(): | |
command.extend((key, str(value))) | |
command.append('-y') # overwrite outputs | |
command.append(args.output) | |
print ' '.join(command) | |
subprocess.call(command) | |
print '\nWrote output to %s' % args.output | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main()) |
Hi!
Do you have a Python 3 port?
I changed all the print statements and am getting this error about Symlinks.
I'm running windows 10
I LOVE how you kept everything using only standard stuff that I already have, but I need it to run of course :-)
I put my PNG images into a folder named inputs... does that work or do I need to name PNG?
I really would like to use this if I can.
Thank you for posting it.
Here is my error:
C:\Python\PycharmProjects\MIDI-Video>python "Make Video.py" inputs output
Traceback (most recent call last):
File "Make Video.py", line 94, in
main()
File "Make Video.py", line 62, in main
os.symlink(input_path, temp_path)
OSError: symbolic link privilege not held
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i test it and got error : usage: player.py [-h] [--limit LIMIT] [--fps FPS] input [input ...] c:/output
player.py: error: too few arguments