Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Converting MP4 Video to Optimized Looping GIFs with Python

Tech 1

Prreequisites: Installing the Required Packages

Set up the Python environment with these packages before starting:

pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install imageio -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

Phase 1: Generating an Initial GIF with MoviePy

MoviePy handles the video-to-GIF conversion. The snippet below clips a segment, rescales it, and exports at a reduced framerate to keep file size manageabel.

from moviepy.editor import VideoFileClip

source_path = "E:\\videos\\input\\sample.mp4"
clip = VideoFileClip(source_path)

# Extract a 5-second segment and scale down to 50%
trimmed = clip.subclip((0, 0), (0, 5)).resize(0.5)

# Export with targeted frame skipping
trimmed.write_gif("E:\\videos\\output\\sample_raw.gif", fps=12)
print('Raw GIF created.')

Phase 2: Compressing, Smoothing, and Enabling Looping

Raw GIFs often suffer from jerky playback, large file size, and missing loop behavior. The following approach rebuilds frames to fix these problems.

Using Imageio with Pillow for Controlled Compression

This method reads the existing GIF, resizes each frame, normalizes timing, and ensures infinite looping.

import imageio
from PIL import Image, ImageSequence

MAX_DIM = 480
frame_collection = []

original = Image.open("E:\\videos\\output\\sample_raw.gif")

for frame in ImageSequence.Iterator(original):
    frame = frame.convert('RGBA')
    width, height = frame.size
    if max(width, height) > MAX_DIM:
        frame.thumbnail((MAX_DIM, MAX_DIM))
    frame_collection.append(frame)

# Set a uniform frame delay equivalent to ~24 fps (in milliseconds)
frame_delay = 1000 / 24

imageio.mimsave(
    "E:\\videos\\compressed\\sample_looping.gif",
    frame_collection,
    duration=frame_delay,
    loop=0
)
print('Compressed looping GIF saved.')

Pillow-Only Compression with Loop Fix

When you don't need fine-tuned timing adjustments, Pillow alone can resize frames and enforce looping.

from PIL import Image, ImageSequence

TARGET_SIZE = 400
frames = []

src_image = Image.open("E:\\videos\\output\\sample_raw.gif")

for page in ImageSequence.Iterator(src_image):
    page = page.convert('RGBA')
    w, h = page.size
    if max(w, h) > TARGET_SIZE:
        page.thumbnail((TARGET_SIZE, TARGET_SIZE))
    frames.append(page)

frames[0].save(
    "E:\\videos\\compressed\\sample_pillow.gif",
    save_all=True,
    append_images=frames[1:],
    loop=0
)
print('Pillow-based GIF ready.')

Key Adjustments Explained

  • Choppy playback usually stems from missing or inconsistent frame timing metadata. Assigning a fixed delay (1000/24 ms) produces smoother motion.
  • Excessive file size is controlled by three levers: lowering output resolution, applying scaling factors (like 0.5), and skipping frames via the fps parameter during export.
  • Color mode selection affects compression: RGBA often yields smaller files than RGB in practice.
  • Single-loop problem is resolved by explicitly setting loop=0 in the saving step—even when the API suggests it should be the default.
Tags: Pythongif

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.