Convert video to high-definition gif dynamic picture (Python code implementation)

How can you write code in Python to convert videos into high-definition motion pictures without relying on expensive third-party tools or enduring low-quality output?

For specific implementation, please refer to this blog post. This technology is very useful for creating presentations, social media content or blog posts, because it allows you to easily convert video clips into clear GIF animations.

Background

Recently, I needed to prepare some dynamic pictures for a PPT defense, and these pictures needed to be extracted from a video. I tried some online tools and paid software, but found that the conversion results were either unclear, watermarked, or required payment. So, I decided to write the code myself to achieve this task.

Technology stack

Before we begin, let’s first understand the technology stack we will be using:

– Python: As a programming language of choice, Python is a powerful and easy-to-use language suitable for processing images and videos.
– OpenCV: This is a library widely used for computer vision tasks and we will use it to process video frames.
– imageio: This library will help us to read video files and save frames as GIF.

Steps

Here are the main steps to convert videos into HD motion pictures:

1. Install the required libraries:

Install the required Python libraries using pip or conda:

 pip install opencv-python imageio

I divided the whole process into three parts for implementation:

Step 1: Convert video to image using opencv

Read the video through VideoCapture, and then imwrite to save the picture. code show as below:

def video_to_image(videoPath,imgPath,save_format = '.jpg',imgNumber = 0,nameLength = 4):
    '''
    params:
        videoPath: video path such as u'E:\Test/123.mp4'
        imgPath: image path, for example r'F:\Test/tu/' #Save the image path, add / slash at the end of the path
        save_format: The saved image format, the default is jpg and can be changed to '.png'
        imgNumber: The number of names saved in the image defaults to 0.
    '''
    print("How to convert video to picture")
    if imgPath[-1] != '/':imgPath + '/'
    capture = cv2.VideoCapture(videoPath)
    frame_num = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
    suc = capture.isOpened() # Whether it was successfully opened
    frame_count = imgNumber # The number of pictures to start from
    while suc:
        try:
           frame_count + = 1
           suc, frame = capture.read()
           cv2.imwrite(imgPath + str(frame_count).zfill(4) + save_format, frame)
           # The zfill() method returns a string of specified length. The original string is right-aligned and filled with 0s in front.
           #:str.zfill(width) parameter width
           if frame_num == frame_count:
               suc=False
        except:
            break
    capture.release()
    print("Video to picture conversion ends! ")
In the second step, the picture set exported from the video is converted into a gif picture

The imageio.get_writer used writes pictures as a gif file stream.

imageio.get_writer(uri = gifname,mode = "I",fps = 25)

These three parameters respectively represent:

uri: The name of the synthesized gif animation, which can be changed at will.
mode: operating mode, I means multiple images, no need to change.
fps: Frame rate, which is the number of frames transmitted per second. The larger the value, the faster the GIF playback speed. 

code show as below:

def image_to_gif(st_imagename=1,end_imagename=1,gifname = "demo.gif"):
    import imageio
    '''
    uri: The name of the synthesized gif animation, which can be changed at will.
    mode: operating mode, I means multiple images, no need to change.
    fps: Frame rate, which is the number of frames transmitted per second. The larger the value, the faster the GIF playback speed.
    gifname: saved gif name
    '''
    os.chdir(os.getcwd())
    if not os.path.exists("images"):
        os.makedirs("images")

    with imageio.get_writer(uri = gifname,mode = "I",fps = 25) as writer:
        for i in range(st_imagename, end_imagename + 1): #How many images to choose?
            print(f"Processing the {i}th picture")
            filename = str(i).zfill(4)
            file_path = os.path.join(os.getcwd(),'images',filename)
            writer.append_data(imageio.imread(file_path + ".jpg"))
The last step is to integrate the above two steps to convert the video into a gif image

The following is the code for the third step

def video_to_gif(videoPath,resultName,fps=25):
    '''
    :param videoPath: Video path absolute path. And the path should not contain Chinese characters
    :param resultName: output gif file name
    :param fps: saved gif frame rate, fps defaults to 25
    '''
    sample = [chr(i) for i in range(97,97 + 26)] + [str(i) for i in range(10)]
    random_name = "_" + "".join(random.sample(sample,10)) #Used to temporarily store data images
    #shutil.rmtree(file_path) #Delete
    if not os.path.exists(random_name):
        os.makedirs(random_name)
    tmp_path = os.path.join(os.getcwd(),random_name) + '/'
    print("step 1 loading:video_to_image start")
    video_to_image(videoPath,tmp_path) #Video conversion completed
    print("step 1 finished:video_to_image end")
    image_nums = len(os.listdir(tmp_path))
    image_nums = 375 if image_nums > 375 else image_nums #TODO The default upper limit is 15s, that is: 25 * 15 = 375 photos
    print("step 2 loading:image_to_gif start")
    image_to_gif(st_imagename=1,end_imagename=image_nums,gifname = resultName)
    print("step 2 finished:image_to_gif end")
    shutil.rmtree(random_name)
    print("All Finished")

The code of the entire project has been uploaded to: askxiaozhang/Python_tools: To provide some like practical tools that png turn to gif or mp4 turn to gif by Python. (github.com)

Brothers and sisters in need can go to Fork and star. Everyone is welcome to join this project and contribute to open source! ~

Below is the entire project code:

import string
import imageio
import os
import cv2
import shutil
import base64
import random

def video_to_image(videoPath,imgPath,save_format = '.jpg',imgNumber = 0,nameLength = 4):
    '''
    params:
        videoPath: video path such as u'E:\Test/123.mp4'
        imgPath: image path, for example r'F:\Test/tu/' #Save the image path, add / slash at the end of the path
        save_format: The saved image format, the default is jpg and can be changed to '.png'
        imgNumber: The number of names saved in the image defaults to 0.
    '''
    print("How to convert video to picture")
    if imgPath[-1] != '/':imgPath + '/'
    capture = cv2.VideoCapture(videoPath)
    frame_num = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
    suc = capture.isOpened() # Whether it was successfully opened
    frame_count = imgNumber # The number of pictures to start from
    while suc:
        try:
           frame_count + = 1
           suc, frame = capture.read()
           cv2.imwrite(imgPath + str(frame_count).zfill(4) + save_format, frame)
           # The zfill() method returns a string of specified length. The original string is right-aligned and filled with 0s in front.
           #:str.zfill(width) parameter width
           if frame_num == frame_count:
               suc=False
        except:
            break
    capture.release()
    print("Video to picture conversion ends! ")

def image_to_gif(file_path,st_imagename=1,end_imagename=1,gifname = "demo.gif"):

    import imageio
    '''
    uri: The name of the synthesized gif animation, which can be changed at will.
    mode: operating mode, I means multiple images, no need to change.
    fps: Frame rate, which is the number of frames transmitted per second. The larger the value, the faster the GIF playback speed.
    gifname: saved gif name
    '''
    # os.chdir(os.getcwd())
    # if not os.path.exists("images"):
    # os.makedirs("images")

    with imageio.get_writer(uri = gifname,mode = "I",fps = 25) as writer:
        for i in range(st_imagename, end_imagename + 1): #How many images to choose?
            print(f"Processing the {i}th picture")
            filename = str(i).zfill(4)
            #file_path = os.path.join(os.getcwd(),'images',filename)
            file_path2 = file_path + filename + ".jpg"
            writer.append_data(imageio.imread(file_path2))
def video_to_gif(videoPath,resultName,fps=25):
    '''
    :param videoPath: Video path absolute path. And the path should not contain Chinese characters
    :param resultName: output gif file name
    :param fps: saved gif frame rate, fps defaults to 25
    '''
    sample = [chr(i) for i in range(97,97 + 26)] + [str(i) for i in range(10)]
    random_name = "_" + "".join(random.sample(sample,10)) #Used to temporarily store data images
    #shutil.rmtree(file_path) #Delete
    if not os.path.exists(random_name):
        os.makedirs(random_name)
    tmp_path = os.path.join(os.getcwd(),random_name) + '/'
    print("step 1 loading:video_to_image start")
    video_to_image(videoPath,tmp_path) #Video conversion completed
    print("step 1 finished:video_to_image end")
    image_nums = len(os.listdir(tmp_path))
    image_nums = 375 if image_nums > 375 else image_nums #TODO The default upper limit is 15s, that is: 25 * 15 = 375 photos
    print("step 2 loading:image_to_gif start")
    image_to_gif(tmp_path,st_imagename=1,end_imagename=image_nums,gifname = resultName)
    print("step 2 finished:image_to_gif end")
    shutil.rmtree(random_name)
    print("All Finished")

if __name__ == '__main__':
    video_to_gif(r"E:\Python_tools\Python_tools\video\test.mp4","test1.gif")

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Python entry skill treeHomepageOverview 363451 people are learning the system