Search code examples
pythonffmpegvideo-processingpyffmpeg

ffmpeg put multiple pictures into different frames


my array in Python looks like this [['0.3251', '6.5712', '12.8174', '13.3979', '13.9784', '14.5357', '14.9537', '15.1394', '15.5109', '16.3236', '16.5094', '16.6951', '17.2524', '17.6704', '18.0419']] and I need to put put one image on that exact same second like in that array with ffmpeg. How can I do that? For an example I want a video with a song on first 0.3251s of the video i want to put img1 second 6.5712s of the video i want to put img2 and so on.


Solution

  • Unfortunately I do not know much about Python but here is an example of a Windows batch file how you can create a video with images and sound by using FFmpeg.

    This example uses mp3 file with sound, three jpg files with images and two of your starting points: 0.3251 and 6.5712. First image will be displayed since start of the output video to 0.3251, second image will be displayed from 0.3251 to 6.5712, third image will be displayed from 6.5712 to the end of the sound. You can easily add more input images and starting points by following the same pattern (I included one example at the end of this post).

    ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex ^
     ^"[1:v]trim=duration=0.3251[a]; ^
       [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; ^
       [a][b]concat[c]; ^
       [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
       [c][d]concat[video]^" ^
      -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4
    

    -i tells FFmpeg to use the following input as the source of stream(s) for the next operations.

    input.mp3 is the input file with a sound.

    inputX.jpg are the input files with an images.

    -loop tells FFmpeg to loop the next input image.

    -filter_complex tells FFmpeg to use the following filters.

    trim is the type of filter to set the duration of specific image, it can be used with duration option or with start and end options (this is where you need to paste values of your starting points).

    concat is the type of filter to merge two previous parts of video into one part that can be used for the next concat operation.

    -map tells FFmpeg what streams (video and audio) should be used to create the output file.

    -c tells FFmpeg what codecs should be used to encode video and audio to create the output file.

    -shortest tells the FFmpeg to use the shortest input stream as the duration of the output (in this case it is the input file with a sound as all images are in infinite loops).

    ^ is Windows batch specific character used to be able to split one long command to a several lines of code. You can delete all ^ and use one long command instead:

    ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex "[1:v]trim=duration=0.3251[a]; [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; [a][b]concat[c]; [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; [c][d]concat[video]" -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4
    

    How to add the next image?

    You need to add one more image as the input and change last few lines in the current set of filters:

       [a][b]concat[c]; ^
       [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
       [c][d]concat[video]^" ^
    

    with:

       [a][b]concat[c]; ^
       [3:v]trim=start=6.5712:end=12.8174,setpts=PTS-STARTPTS[d]; ^
       [c][d]concat[e]; ^
       [4:v]trim=start=12.8174,setpts=PTS-STARTPTS[f]; ^
       [e][f]concat[video]^" ^
    

    The letters [a], [b], [c] are the names of the variables - you can use any combination of letters here, not just one letter. For example: [aa][ab]concat[ac] would also work and [video] is a also a variable name used in this command.