How To Create Video Inside Text Effect Using Python

Hello folks, in this tutorial I will create a video-inside-text effect using Python. The video will play in the background but it will be visible only through the overlaid text.

My method can be applied to multiple videos of any resolution and duration. Take a look at the final output.

Usually, people use tools like Adobe After Effects, Adobe Premiere Pro or Davinci Resolve to create this kind of effect. They are awesome software but you have to put in a lot of manual effort to get the job done.

Therefore, I am going to use Python to automate inserting a video in a text string. Once the initial setup is done, we can run the same Python script on a large number of videos in one shot.

Note – You can download the Python code and other needed files from this link.

Put image inside text

First, let me show you how to put an image inside a static text sequence. It will help you in understanding the technique.

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont
from moviepy.editor import VideoFileClip, CompositeVideoClip

# Load your image 
image = Image.open("input_image.jpg")
image = image.convert("RGBA")

# display image
image
video inside text

After loading the image I have converted it to an “RGBA” mode which means it will have Red, Green, Blue, and Alpha (transparency) channels.

Next, I will create a blank image of the same dimensions as the one above. On this image, I will put the text string and use this image as a layer that will be later overlaid on the input image.

# Choose a font and size for the text
font_path = "ChrustyRock-ORLA.ttf"  # replace with the path to your font file
font_size = 100  # replace with your desired font size
font = ImageFont.truetype(font_path, font_size)

Here I have specified the path to a .ttf font file and set a font size. Then I created a font object that will be used to draw text.

# Create a new blank image with a black background
text_image = Image.new("RGBA", image.size, (0, 0, 0, 255))

# Create drawing context
draw = ImageDraw.Draw(text_image)

# Define text and position
text = "Your Text"  # replace with your text
_, _, text_width, text_height = draw.textbbox(xy = (0,0), text=text, font=font)
text_x = (text_image.width - text_width) / 2
text_y = (text_image.height - text_height) / 2

Now I can specify the text overlaid on the image and calculate how big it will be in pixels, given the specified font. We then use these dimensions to compute the position of where the text should be placed to be centered on the image.

# Add text to the new blank image
draw.text((text_x, text_y), text, font=font, fill=(255, 255, 255, 255))

# Display image
text_image
video inside text

Using the drawing context, I added the text to text_image with the calculated x and y positions in white color.

Now I will create a mask image to put the text on top of the input image. I will use a grayscale mask image with the same size as the original image. Then, the same text is drawn onto the mask in white (255).

This mask will define where the original image will show through – only where the text is.

# Create a mask using the text_image and apply it onto the original image
mask = Image.new("L", image.size, 0)
mask_draw = ImageDraw.Draw(mask)
mask_draw.text((text_x, text_y), text, font=font, fill=255)

# Composite the original image onto the text image using the created mask
result = Image.composite(image, text_image, mask)

result
image inside text

If you can see carefully, the image appears through the text. We have to use the same technique and apply it to all the frames of the video and then combine the processed frames back together to create a video that will appear inside the text.

Add video inside text

I will use a stock video for this demo. You can find this video in my downloadable material. Feel free to change the font size as per your taste.

# Load the video
video_path = 'drone_footage.mp4'
video = VideoFileClip(video_path)

# Define a function that will be applied to each frame
def add_text_to_frame(frame):

    font_size = 232
    
    # convert frame (numpy array) to PIL image  
    pil_frame = Image.fromarray(frame)

    # Load the custom font
    font = ImageFont.truetype(font_path, font_size)

    # Create drawing context
    text_image = Image.new("RGBA", pil_frame.size, (0, 0, 0, 255))

    # Create drawing context
    draw = ImageDraw.Draw(text_image)

    # Define text and position
    text = "MAGIC"  # replace with your text
    _, _, text_width, text_height = draw.textbbox(xy = (0,0), text = text, font = font)

    text_x = (text_image.width - text_width) / 2
    text_y = (text_image.height - text_height) / 2

    # Add text to the new blank image
    draw.text((text_x, text_y), text, font=font, fill=(255, 255, 255, 255))

    # Create a mask using the text_image and apply it onto the original image
    mask = Image.new("L", pil_frame.size, 0)
    mask_draw = ImageDraw.Draw(mask)
    mask_draw.text((text_x, text_y), text, font=font, fill=255)

    # Composite the original image onto the text image using the created mask
    result = Image.composite(pil_frame, text_image, mask)

    # Convert the result back to a frame
    new_frame = np.array(result)[:,:,:3]

    return new_frame

# Apply the function to each frame
modified_video = video.fl_image(add_text_to_frame)

# Write the result to a file
output_path = 'video_in_text.mp4'
modified_video.write_videofile(output_path, codec='libx264', audio_codec='aac')

We can make it even more interesting by moving the text as well in addition to the video playing in the background. For example, we can use the typewriter effect on our text or make the text scroll horizontally.

Leave a Reply

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