Fundamentals 8 min read

Create Stunning 9‑Grid Short Videos with Python in One Click

Learn how to use Python's moviepy and Pillow libraries to automatically split a video into nine segments, arrange them into a stylish 9‑grid layout, add background music, and export the result as a polished short video, complete with step‑by‑step code examples.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Create Stunning 9‑Grid Short Videos with Python in One Click

1. Scenario

If you often browse Douyin and WeChat Moments, you may have noticed the popularity of 9‑grid short videos.

From 9‑grid images to 9‑grid videos, the latter feels more personalized and stylish.

Besides traditional editing software, is there a faster way? For example, one‑click or batch generation?

In this article we use Python to generate 9‑grid short videos, elegantly helping you showcase a cool post.

2. Preparation

Before starting, install two dependencies via pip:

Video processing: moviepy

Image processing: PIL

# Install two dependencies
# Video processing
pip3 install moviepy

# Image processing
pip3 install Pillow

3. Implementation

First, prepare a raw video file.

We will convert the raw video into a 9‑grid video in six steps.

1. Create processing folders

def mkdir_folder(file_path):
    """
    Create a folder if it does not exist.
    """
    if os.path.exists(file_path):
        return
    os.mkdir(file_path)

# Create temporary and output folders
mkdir_folder(self.path_temp)
mkdir_folder(self.path_output)

2. Extract audio and basic video info

self.video_raw_clip = VideoFileClip(file_path)

# Width, height
self.video_width, self.video_height = self.video_raw_clip.w, self.video_raw_clip.h

# Frame rate
self.fps = self.video_raw_clip.fps

# Duration
self.during = self.video_raw_clip.duration
def get_audio_from_video(video_raw_clip, output_path):
    """
    Extract audio from video.
    """
    audio = video_raw_clip.audio
    audio.write_audiofile(output_path)
    return output_path

3. Process video frames

i = 1
for frame in self.video_raw_clip.iter_frames():
    image = Image.fromarray(frame)
    frame_file_complete_path = self.path_temp + "%04d.jpg" % i
    i += 1

Each frame is cropped into nine images, spaced as needed, and pasted onto a white canvas.

# 1. Split into 9 images, calculate each size
item_width = int(self.video_width / 3)
item_height = int(self.video_height / 3)

# 2. New canvas size
item_width_new = self.video_width + self.item_space * 2
item_height_new = self.video_height + self.item_space * 2

# 3. Create new white background
new_image = Image.new(image.mode, (item_width_new, item_height_new), color='white')
# 4. Crop and paste
for i in range(3):
    for j in range(3):
        box = (j * item_width, i * item_height,
               (j + 1) * item_width, (i + 1) * item_height)
        crop_image = image.crop(box)
        x = 0 if j == 0 else (item_width + self.item_space) * j
        y = 0 if i == 0 else (item_height + self.item_space) * i
        new_image.paste(crop_image, (int(x), int(y)))
        new_image.save(frame_file_complete_path)

4. Assemble images back into video

def pics_to_video(pics_path, output_path, fps):
    """
    Convert images to video.
    """
    image_paths = list(map(lambda x: pics_path + x, os.listdir(pics_path)))
    # Ensure correct order
    image_paths = sort_strings_with_emb_numbers(image_paths)
    # Keep only jpg files
    image_paths = list(filter(lambda p: p.endswith('.jpg'), image_paths))
    clip = ImageSequenceClip(image_paths, fps=fps)
    clip.write_videofile(output_path)

5. Add background music

def video_with_audio(path_video_raw, path_bgm_raw, output):
    """
    Combine video with audio.
    """
    videoclip = VideoFileClip(path_video_raw)
    audioclip = AudioFileClip(path_bgm_raw)
    videoclip.set_audio(audioclip).write_videofile(
        output, codec='libx264', audio_codec='aac',
        temp_audiofile='temp-audio.m4a', remove_temp=True)

6. Delete temporary files

def remove_folder(file_path):
    """
    Delete folder.
    """
    shutil.rmtree(file_path)

# Delete temporary folder
remove_folder(self.path_temp)

7. Result

The final output is a video transformed into a 9‑grid format.

4. Conclusion

By following these steps, we have turned a regular video into a stylish 9‑grid short video.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Video processingmoviepy
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.