Can I pass a list of image into the input method of ffmpeg-python

4.8k views Asked by At

My task involves using ffmpeg to create video from image sequence. the code belows solves the problem.

import ffmpeg

video = ffmpeg.input('/path/to/images/*.jpg', pattern_type='glob',framerate=20).output(video.mp4).run()

However since the image data we are getting follows the pattern

1.jpg,
2.jpg,
3.jpg
.
.
20.jpg
.
.
100.jpg

the video get created with the glob pattern 1.jpg, 100.jpg, 11.jpg, 12.jpg, ... 2.jpg, 20.jpg, 21.jpg ... which is very unpleasant to watch.

Is there anyway I can pass a list or anything else aside a path/glob pattern where the images are sorted in order. Also as a bonus I will be happy if I can choose which files to add as an the input method input()

1

There are 1 answers

4
Rotem On BEST ANSWER

You may use Concat demuxer:

  • Create a file mylist.txt with all the image files in the following format:

     file '/path/to/images/1.jpg'
     file '/path/to/images/2.jpg'
     file '/path/to/images/3.jpg'
     file '/path/to/images/20.jpg'
     file '/path/to/images/100.jpg'
    

    You may create mylist.txt manually, or create the text file using Python code.

  • Use the following command (you may select different codec):

     ffmpeg.input('mylist.txt', r='20', f='concat', safe='0').output('video.mp4', vcodec='libx264').run()
    

Second option:
Writing JPEG data into stdin PIPE of FFmpeg sub-process.

  • Create a list of JPEG file names (Python list).
  • Execute FFmpeg sub-process, with stdin PIPE as input, and jpeg_pipe input format.
  • Iterate the list, read the content of each file and write it to stdin PIPE.
  • Close stdin PIPE.

Here is a code sample:

import ffmpeg

# List of JPEG files
jpeg_files = ['/tmp/0001.jpg', '/tmp/0002.jpg', '/tmp/0003.jpg', '/tmp/0004.jpg', '/tmp/0005.jpg']

# Execute FFmpeg sub-process, with stdin pipe as input, and jpeg_pipe input format
process = ffmpeg.input('pipe:', r='20', f='jpeg_pipe').output('/tmp/video.mp4', vcodec='libx264').overwrite_output().run_async(pipe_stdin=True)

# Iterate jpeg_files, read the content of each file and write it to stdin
for in_file in jpeg_files:
    with open(in_file, 'rb') as f:
        # Read the JPEG file content to jpeg_data (bytes array)
        jpeg_data = f.read()

        # Write JPEG data to stdin pipe of FFmpeg process
        process.stdin.write(jpeg_data)

# Close stdin pipe - FFmpeg fininsh encoding the output file.
process.stdin.close()
process.wait()