Objective

This article will guide you through the steps of creating a video slideshow based on a list of images. The process does not entail using any editing software, but using a PHP script allowing you to create videos programmatically. If you follow this article you will learn the basics for creating your image to video converter.

The objective of this tutorial is to turn these 5 images into a video:

london-01.jpg
london-02.jpg
london-03.jpg
london-04.jpg
london-05.jpg

I will propose 2 alternatives for this:

Why should I care where the video is created?

Video processing is a resource expensive task that consumes memory and CPU. Depending on your usage estimate you might need to consider upgrading your servers or creating a dedicated cluster of servers for video processing.

On the other hand, using a cloud-based video API solution allows you to have a scale-proof, pay-as-you-go platform you don't need to worry about. Depending on your volume, you may fall into the free-tier and you don't have any cost.

This means that you can now focus exclusively on writing reusable code without having to worry about managing infrastructure.

Read more about what you should take into consideration when editing video with PHP scripts.

Self-hosted solution with FFMPEG and PHP

Create video from images with FFMPEG + PHP

There are many ways to do this, but I went with the two I think are the easiest. As you may know, FFMPEG is a powerful set of tools that can convert and process videos. But such power comes with a step learning curve, sometimes cryptic parameters and some frustration by newbies.

The examples below work for turning JPEG, PNG and WEBP still images into a video slideshow. You just need to replace the JPG file in the example codes with your PNG file, to turn the ffmpeg images to video.

Option 1: with no transitions

I will pass each of the 5 input images to ffmpeg in this format:

-loop 1 -t 2 -i london-0X.jpg

Then, I'll tell ffmpeg to concat them all into a output stream:

-filter_complex "[0][1][2][3][4] concat=n=5 [out]"

And finally, I'll save the output stream into output.mp4:

-map "[out]" output.mp4 -y

All together now:

ffmpeg \
    -loop 1 -t 2 -i london-01.jpg \
    -loop 1 -t 3 -i london-02.jpg \
    -loop 1 -t 2 -i london-03.jpg \
    -loop 1 -t 3 -i london-04.jpg \
    -loop 1 -t 4 -i london-05.jpg \
    -filter_complex "[0][1][2][3][4] concat=n=5 [out]" \
    -map "[out]" output.mp4 -y

Now let's make the call from PHP:

<?php
    $cmd = "ffmpeg \
    -loop 1 -t 2 -i london-01.jpg \
    -loop 1 -t 3 -i london-02.jpg \
    -loop 1 -t 2 -i london-03.jpg \
    -loop 1 -t 3 -i london-04.jpg \
    -loop 1 -t 4 -i london-05.jpg \
    -filter_complex \"[0][1][2][3][4] concat=n=5 [out]\" \
    -map \"[out]\" output.mp4";

    $r = exec($cmd);

You must make sure ffmpeg is in the same folder than your script or it's in a directory included in the PATH.

The resulting video is a slideshow of images, each with slide with different durations (2, 3, 2, 3 and 4 seconds):

Option 2: with transitions

Adding transitions is a little bit more tricky because we must fade each image with the next one. I will use the xfade filter to apply the transition, in this format:

[input1][input2] xfade=transition={transition_name}:duration={duration}:offset={offset}

Because this encoding is a little bit more complex, we must tell FFMPEG what codec and format to use to make sure the output is compatible with most of the video players, for example with QuickTime:

-pix_fmt yuv420p -vcodec libx264

All together now:

ffmpeg \
    -loop 1 -t 5 -i london-01.jpg \
    -loop 1 -t 5 -i london-02.jpg \
    -loop 1 -t 5 -i london-03.jpg \
    -loop 1 -t 5 -i london-04.jpg \
    -loop 1 -t 5 -i london-05.jpg \
    -filter_complex " \
        [0][1] xfade=transition=slideup:duration=1:offset=4 [a]; \
        [a][2] xfade=transition=slideright:duration=1:offset=8 [b]; \
        [b][3] xfade=transition=slidedown:duration=1:offset=12 [c]; \
        [c][4] xfade=transition=slideleft:duration=1:offset=16 [out] \
        " \
    -pix_fmt yuv420p -vcodec libx264 \
    -map "[out]" output.mp4 -y

I used 4 different transitions, one for each slide. You can check the available transitions in the xfade FFMPEG documentation

Now let's make the call from PHP:

<?php
    $cmd = "ffmpeg \
    -loop 1 -t 5 -i london-01.jpg \
    -loop 1 -t 5 -i london-02.jpg \
    -loop 1 -t 5 -i london-03.jpg \
    -loop 1 -t 5 -i london-04.jpg \
    -loop 1 -t 5 -i london-05.jpg \
    -filter_complex \" \
        [0][1] xfade=transition=slideup:duration=1:offset=4 [a]; \
        [a][2] xfade=transition=slideright:duration=1:offset=8 [b]; \
        [b][3] xfade=transition=slidedown:duration=1:offset=12 [c]; \
        [c][4] xfade=transition=slideleft:duration=1:offset=16 [out] \
        \" \
    -pix_fmt yuv420p -vcodec libx264 \
    -map \"[out]\" output.mp4 -y";

    $r = exec($cmd);

The resulting video looks like this:

As a bonus, if you continue reading, at the end of the article, I will show you how you can add a background music.
😉

Cloud-hosted solution with JSON2Video and PHP

Now, let's do the same but serverless, fully-scalable and with maintainable code.

With JSON2Video you use an abstraction to make things much easier:

The best thing in terms of development is that you can easily describe your video programmatically without knowing cryptic parameters like -t 5, -pix_fmt yuv420p or concat=n=5. And one month later, you (or someone in your team) will still be able to understand the code.

Create video from images with PHP + JSON2Video

Agreed, it's longer than the FFMPEG version, but you must admit that it's way easier to understand and maintain.

The result is the same but you don't need back-end resources and your code is easier to maintain:

BONUS TRACK: Add a background music

As promised, here it is how to convert image and audio to video with FFMPEG and PHP.

Adding audio with FFMPEG can be easier or harder depending on what you want to achieve. A simple background music with no sync with the jpeg images is pretty straight forward as we will see below. Something more sophisticated, like different audios sync'ed with the slideshow can be much more complex and require a longer FFMPEG command.

To add the audio to the video slideshow of images, I'm adding an additional input source to the FFMPEG command:

-i music.mp3

And I'm finally mapping this input source (input #5, remember it starts counting from 0) into the final output video. Because the audio file is longer (2 minutes) than the video slideshow, I must tell FFMPEG to set the video length to the shorter between the video stream and the audio stream:

-map 5:a -shortest

The final command is:

<?php
    $cmd = "ffmpeg \
    -loop 1 -t 5 -i london-01.jpg \
    -loop 1 -t 5 -i london-02.jpg \
    -loop 1 -t 5 -i london-03.jpg \
    -loop 1 -t 5 -i london-04.jpg \
    -loop 1 -t 5 -i london-05.jpg \
    -i music.mp3 \
    -filter_complex \" \
        [0][1] xfade=transition=slideup:duration=1:offset=4 [a]; \
        [a][2] xfade=transition=slideright:duration=1:offset=8 [b]; \
        [b][3] xfade=transition=slidedown:duration=1:offset=12 [c]; \
        [c][4] xfade=transition=slideleft:duration=1:offset=16 [out] \
        \" \
    -pix_fmt yuv420p -vcodec libx264 \
    -map \"[out]\" -map 5:a -shortest output.mp4 -y";

    $r = exec($cmd);

This is the result:

Final thoughts on creating a video from images

As you read above, the basics of creating a MP4 slideshow from images are pretty simple with FFMPEG. However, if you are really planning to turn this into a production project with real users that could scale with several users simultaneously, you should take into consideration SaaS alternatives like JSON2Video. The headache of running a high-performance, ready-to-scale server cluster is something you should not underestimate.

On the other hand, using FFMPEG requires extensive experience. If your code needs to be maintained by a team of developers this could be a handicap. JSON2Video allows you to solve this as well providing a simple and readable interface to video editing.

Published on January 9th, 2022

Author
David Bosch
David Bosch David is an experienced engineer, now collaborating with JSON2Video.