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

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

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

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.