Convert Audio to Video using Static Images in Python

In this tutorial, we will see how to convert an Audio File (MP3) to a Video File (MP4) using static images in Python. In other words, convert Audio to Video.

We are going to follow the procedure mentioned below to implement it:

  1. Installing and Loading the Dependencies required.
  2. Creating a class MP3ToMP4.
  3. Getting the length of the MP3 File and list of Images.
  4. Creating a GIF File.
  5. Combining GIF File with MP3.

 

Installing and Loading Dependencies

We’ll need to install the packages mentioned below :

mutagen

mutagen package provides us various methods for handling Audio Files. So, we’ll be using it to find the length of the MP3 File.

PIL

PIL package, short form for Pillow is an Image Processing library that provides us with extensive methods of operations that can be performed on images.  So, we’ll use it for reading images and creating a GIF file.

moviepy

moviepy package is used for tasks related to Video Editing and Processing. So, we’ll use it to combine the Audio File with the GIF File.

We can install these packages easily using the pip module.

pip install mutagen
pip install Pillow
pip install moviepy

After the installation part is done, we will be importing:

  • MP3 module from mutagen.mp3
  • Image module from PIL
  • Path module from pathlib
  • editor module from moviepy
# Loading all the packages required
from mutagen.mp3 import MP3
from PIL import Image
from pathlib import Path
from moviepy import editor

Creating the Class MP3ToMP4:

After importing the required modules, we create a class ‘MP3ToMP4’. Subsequently, we declare and initialize variables in the constructor which would store the paths of the:

  • Root Folder (containing images).
  • Audio (mp3) File.
  • Where the Created Video will be saved along with its Name.

The next step is to call the create_video() method of the class.

class MP3ToMP4:

    def __init__(self, folder_path, audio_path, video_path_name):
        """
        :param folder_path: contains the path of the root folder.
        :param audio_path: contains the path of the audio (mp3 file).
        :param video_path_name: contains the path where the created
                                video will be saved along with the
                                name of the created video.
        """
        self.folder_path = folder_path
        self.audio_path = audio_path
        self.video_path_name = video_path_name

        # Calling the create_video() method.
        self.create_video()

Getting the length of the MP3 File and list of Images

After defining the constructor, we declare and define two more methods:

  • get_length() :

    • This method uses the ‘audio_path’ to load the MP3 File in the ‘song’ variable. After that, it accesses and returns the length of the MP3 File using ‘song.info.length’
  • get_images() :

    • This method firstly sets the path of the folder containing images in the ‘path_images’ variable using the Path module from the pathlib package.
    • Then, it filters out the ‘.png’ filenames and stores them in a list namely, ‘images’.
    • Then, it declares an empty list, namely ‘image_list’.
    • After that, it loops over the image filenames stored in ‘images’, opening every image, resizing it, and appending it to the ‘image_list’.
    • Finally, it returns the ‘image_list’
class MP3ToMP4:

    def get_length(self):
        """
        This method reads an MP3 file and calculates its length
        in seconds.

        :return: length of the MP3 file
        """
        song = MP3(self.audio_path)
        return int(song.info.length)

    def get_images(self):
        """
        This method reads the filenames of the images present
        in the folder_path of type '.png' and stores it in the
        'images' list.

        Then it opens the images, resizes them and appends them
        to another list, 'image_list'

        :return: list of opened images
        """
        path_images = Path(self.folder_path)
        images = list(path_images.glob('*.png'))
        image_list = list()
        for image_name in images:
            image = Image.open(image_name).resize((800, 800), Image.ANTIALIAS)
            image_list.append(image)
        return image_list

Creating a GIF File :

At the end of the constructor, we call the create_video() method which basically converts the list of images to a single GIF File.

It first gets the length of the audio file and stores it in ‘length_audio’ variable. Then in a similar way, it gets the list of images and stores it in ‘image_list’.

Then it uses the length of the audio and the number of images in ‘image_list’ to calculate duration per frame(image) in milliseconds.

After that, it creates a single GIF File for all the images and does so by calling the save() method on the first image in the list. Then, it passes the path and name of the GIF File to be stored, save_all as True, the remaining image_list, and duration as parameters in the save() method.

Finally, it calls the combine_audio() method.

class MP3ToMP4:

    def create_video(self):
        """
        This method calls the get_length() and get_images()
        methods internally. It then calculates the duration
        of each frame. After that, it saves all the opened images
        as a gif using the save() method. Finally, it calls the
        combine_method()

        :return: None
        """
        length_audio = self.get_length()
        image_list = self.get_images()
        duration = int(length_audio / len(image_list)) * 1000
        image_list[0].save(self.folder_path + "temp.gif",
                           save_all=True,
                           append_images=image_list[1:],
                           duration=duration)

        # Calling the combine_audio() method.
        self.combine_audio()

Combining GIF File with MP3 (Convert Audio to Video)

After the creation of the GIF File, the combine_audio() method firstly loads it and then loads the Audio (MP3) File. Then, it combines the Audio File with the GIF File by calling the set_audio() method on the video object. Finally, it writes the created video to the path specified.

class MP3ToMP4:

    def combine_audio(self):
        """
        This method attaches the audio to the gif file created.
        It opens the gif file and mp3 file and then uses
        set_audio() method to attach the audio. Finally, it
        saves the video to the specified video_path_name

        :return: None
        """
        video = editor.VideoFileClip(self.folder_path + "temp.gif")
        audio = editor.AudioFileClip(self.audio_path)
        final_video = video.set_audio(audio)
        final_video.write_videofile(self.video_path_name, fps=60)

In the main section of the code, we take the values of the path of the folder, path of the audio, and path of the video to be created along with its name as input. Then, they are passed as parameters when the constructor of MP3ToMP4 class is invoked during execution.

if __name__ == '__main__':
    # Taking the input for the paths of the variables mentioned below.
    folder_path = input("Enter the Path of the Folder containing Images: ")
    audio_path = input("Enter the Path of the MP3 file: ")
    video_path_name = input("Enter the Path followed by name of the Video to be created: ")

    # Invoking the parameterized constructor of the MP3ToMP4 class.
    MP3ToMP4(folder_path, audio_path, video_path_name)

Complete Python Code

# Loading all the packages required
from mutagen.mp3 import MP3
from PIL import Image
from pathlib import Path
from moviepy import editor

'''
Creating class MP3ToMP4 which contains methods to convert
an audio to a video using a list of images.
'''


class MP3ToMP4:

    def __init__(self, folder_path, audio_path, video_path_name):
        """
        :param folder_path: contains the path of the root folder.
        :param audio_path: contains the path of the audio (mp3 file).
        :param video_path_name: contains the path where the created
                                video will be saved along with the
                                name of the created video.
        """
        self.folder_path = folder_path
        self.audio_path = audio_path
        self.video_path_name = video_path_name

        # Calling the create_video() method.
        self.create_video()

    def get_length(self):
        """
        This method reads an MP3 file and calculates its length
        in seconds.

        :return: length of the MP3 file
        """
        song = MP3(self.audio_path)
        return int(song.info.length)

    def get_images(self):
        """
        This method reads the filenames of the images present
        in the folder_path of type '.png' and stores it in the
        'images' list.

        Then it opens the images, resizes them and appends them
        to another list, 'image_list'

        :return: list of opened images
        """
        path_images = Path(self.folder_path)
        images = list(path_images.glob('*.png'))
        image_list = list()
        for image_name in images:
            image = Image.open(image_name).resize((800, 800), Image.ANTIALIAS)
            image_list.append(image)
        return image_list

    def create_video(self):
        """
        This method calls the get_length() and get_images()
        methods internally. It then calculates the duration
        of each frame. After that, it saves all the opened images
        as a gif using the save() method. Finally it calls the
        combine_method()

        :return: None
        """
        length_audio = self.get_length()
        image_list = self.get_images()
        duration = int(length_audio / len(image_list)) * 1000
        image_list[0].save(self.folder_path + "temp.gif",
                           save_all=True,
                           append_images=image_list[1:],
                           duration=duration)

        # Calling the combine_audio() method.
        self.combine_audio()

    def combine_audio(self):
        """
        This method attaches the audio to the gif file created.
        It opens the gif file and mp3 file and then uses
        set_audio() method to attach the audio. Finally, it
        saves the video to the specified video_path_name

        :return: None
        """
        video = editor.VideoFileClip(self.folder_path + "temp.gif")
        audio = editor.AudioFileClip(self.audio_path)
        final_video = video.set_audio(audio)
        final_video.write_videofile(self.video_path_name, fps=60)


if __name__ == '__main__':
    # Taking the input for the paths of the variables mentioned below.
    folder_path = input("Enter the Path of the Folder containing Images: ")
    audio_path = input("Enter the Path of the MP3 file: ")
    video_path_name = input("Enter the Path followed by name of the Video to be created: ")

    # Invoking the parameterized constructor of the MP3ToMP4 class.
    MP3ToMP4(folder_path, audio_path, video_path_name)

Input:

Convert Audio to Video using Static Images in Python

Input Images:

image to video in python

Output:

Output

Output Video:

Thank you for devoting your valuable time reading this article. You may check out these other articles as well:

Leave a Reply

Your email address will not be published. Required fields are marked *