Skip to content

Instantly share code, notes, and snippets.

@mankind
Last active May 27, 2024 09:38
Show Gist options
  • Save mankind/d96d31497a43d3fabe8c636235ab6eda to your computer and use it in GitHub Desktop.
Save mankind/d96d31497a43d3fabe8c636235ab6eda to your computer and use it in GitHub Desktop.
"""
https://pjoshi15.com/scrolling-text-python/
How to Create Scrolling Text Animation with Python
Scrolling text in a video or gif can add lots of value to the content and present key information in a small amount of space. To create our scrolling text animation video, we’ll use OpenCV (cv2) paired with the Python Imaging Library (PIL) in this article. Our code will also allow the users to adjust the speed of the scrolling text and also the direction of movement of the text. Ready to get started creating scrolling text animation with Python? Let’s start with right-to-left text.
Python function for creating scrolling text video
Below is a Python function that takes in inputs like a text string, speed of animation, direction of scrolling animation and a few other parameters to create a video of scrolling text either left-to-right or right-to-left.
Inside the function, we have set the width and height of the video to 300 and 200 pixels, respectively. The video background color has been set to black (0,0,0) and the color of the text is going to be white (255, 255, 255). The font that we are using for the text is Arial font, so make sure you have the arial.tff file in the working directory. Feel free to change these parameters as per your requirement.
"""
def create_scrolling_text_video(text, font_path, font_size, speed, output_file, direction='left'):
image_width=300
image_height=200
text_color=(255, 255, 255) # scrolling text color
bg_color=(0, 0, 0) # background color
font = ImageFont.truetype(font_path, font_size)
# get size of the input text string
text_width, text_height = font.getsize(text)
# number of frames
num_frames = text_width + image_width
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
video_writer = cv2.VideoWriter(output_file, fourcc, speed, (image_width, image_height))
# create frames for text scrolling
for i in range(num_frames):
img = Image.new("RGB", (image_width, image_height), bg_color)
draw = ImageDraw.Draw(img)
if direction == 'left':
x = image_width - i
elif direction == 'right':
x = -(image_width - i)
else:
raise ValueError("Invalid direction. Choose either 'left' or 'right'.")
y = (image_height - text_height) // 2
draw.text((x, y), text, font=font, fill=text_color)
# Convert the image to an OpenCV frame
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
video_writer.write(frame)
video_writer.release()
"""
The number of frames has been set equal to the sum of the frame width and the input text string width. This will allow the entire text string to pass the frame from first character till the last character.
Then on each frame, at the center, the text is overlayed. After that all the frames are combined to create an mp4 video and then it is saved at the specified location in your system.
Horizontal scrolling text animation: right-to-left
Now we will call the above function to create a short video of scrolling text from right-to-left. The input text string is “This is a scrolling text animation example”.
"""
text = "This is a scrolling text animation example."
font_path = "arial.ttf" # Path to your desired font file (e.g., arial.ttf or path to any other TTF font file)
font_size = 32
speed = 90 # Higher value makes the text scroll faster
output_file = "scrolling_text.mp4"
create_scrolling_text_video(text, font_path, font_size, speed, output_file, direction = "left")
"""
Horizontal scrolling text animation: left-to-right
Let’s change the direction of the scrolling text and make it left-to-right. All we have to do is pass ‘left’ as the value for the ‘direction’ argument.
"""
text = "This is a scrolling text animation example."
font_path = "arial.ttf" # Path to your desired font file (e.g., arial.ttf or path to any other TTF font file)
font_size = 26
speed = 90 # Higher value makes the text scroll faster
output_file = "scrolling_text_right.mp4"
create_scrolling_text_video(text, font_path, font_size, speed, output_file, direction = "right")
"""
Horizontal scrolling text animation: both directions
Now let’s modify the scrolling text animation function and implement dual text scrolling animation from both the directions.
"""
# this code uses llama
#
"""
The num_frames variable is not pre-selected in the provided code. It is an input parameter that represents the desired number of frames for the scrolling text animation. The code assumes that the caller will provide an appropriate value for num_frames based on the desired duration and frame rate of the animation.
Regarding the for loop, the provided code does handle the loop using the moviepy package. The TextClip object created in the code represents the scrolling text animation, and its duration is set using the set_duration() method. The CompositeVideoClip object combines the text clip with the background clip, and the write_videofile() method is used to write the final video file.
Why num_frames is a pre-selected number:
In the provided code, num_frames is indeed a pre-selected number. This is because the MoviePy library doesn't require you to explicitly create each frame like OpenCV does. Instead, you can specify the duration of the clip and let MoviePy handle the frame generation. The set_duration method is used to set the duration of the TextClip, and MoviePy will automatically generate the required number of frames based on the specified duration and FPS.
Handling the for i in range(num_frames): loop:
You're right; the provided code doesn't directly translate the for i in range(num_frames): loop from OpenCV to MoviePy. This is because MoviePy's TextClip and CompositeVideoClip classes handle the animation and frame generation internally.
To achieve a similar effect, you can use MoviePy's animate method to animate the text clip's position over time. Here's an updated code snippet that demonstrates how to scroll the text across the video:
In this updated code, we use the animate method to animate the text clip's position over time. The animate_text function returns the x-coordinate of the text clip based on the current time t. This will create a scrolling effect where the text moves across the video.
"""
##
# adapting the code to use moviepy
from moviepy.editor import TextClip, ColorClip, CompositeVideoClip
# Define the text, font, and other parameters
text = "Your text here"
font = "Your font here"
text_height = 50
bg_color = (255, 255, 255) # White background
text_color = (0, 0, 0) # Black text
fps = 30
duration = 5 # seconds
image_width = 640 # Width of the video frame
image_height = 480 # Height of the video frame
# Create a blank video clip with the desired background color
bg_clip = ColorClip(size=(image_width, image_height), color=bg_color, duration=duration)
# Create a text clip
text_clip = TextClip(text, font=font, color=text_color, size=text_height, align='center')
# Animate the text clip's position over time
def animate_text(t):
if direction == 'left':
x = image_width - t * fps
elif direction == 'right':
x = -image_width + t * fps
else:
raise ValueError("Invalid direction. Choose either 'left' or 'right'.")
"""
image_height is used to calculate the y-coordinate of the text, (image_height - text_height) // 2, which centers the text vertically.
You should define image_height based on your specific video resolution or image size
"""
y = (image_height - text_height) // 2 # Keep the y-coordinate constant
return x, y
# https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html#moviepy.video.VideoClip.VideoClip.set_position
# # clip's position is horizontally centered, and moving up !
# clip.set_position(lambda t: ('center', 50+t) )
text_clip = text_clip.set_position(lambda t: animate_text(t) )
# text_clip = text_clip.set_position(animate_text)
# Combine the text clip and the background clip
video_clip = CompositeVideoClip([bg_clip, text_clip])
# Write the video clip to a file
video_clip.write_videofile("scrolling_text.mp4", fps=fps)
## another approach using @Mixtral-8x7B-Chat
"""
This code creates a TextClip instance, which scrolls from right to left if the direction argument is set to 'left' and from left to right if the direction argument is set to 'right'.
The key difference between the original code and the refactored code is that the refactored code uses TextClip to manage the scrolling text and the time, while the original code uses a loop to create each frame.
In the refactored code, the text_scrolling_clip function takes care of the scrolling by setting the start time of the TextClip and calculating the position of the text.
The mplfig_to_npimage function is used to convert the TextClip instance into a numpy array (image) which is then added to the background color (bg_color) using the + operator.
Finally, the write_videofile method is used to generate the output video.
Note: The mplfig_to_npimage function is used to work around some TextClip positioning issues. In some cases, using set_position and resize directly might not work as expected, so this function is used to ensure proper positioning.
from moviepy.video.io.bindings import mplfig_to_npimage
https://zulko.github.io/moviepy/getting_started/working_with_matplotlib.html#simple-matplotlib-example
"""
from moviepy.editor import TextClip
from moviepy.video.io.bindings import mplfig_to_npimage
def text_scrolling_clip(text, image_width, image_height, bg_color, text_color, font, direction, num_frames):
text_clip = TextClip(text, font=font, color=text_color)
text_clip = text_clip.set_position(lambda t: (image_width - t * 2, (image_height - text_clip.size[1]) // 2))
if direction == 'left':
text_clip = text_clip.set_start(-num_frames)
composite_clip = (
mplfig_to_npimage(
plt.gcf()
).set_duration(num_frames / fps)
+ text_clip
)
return composite_clip
# Usage example
num_frames = 100
fps = 24
text = "This is a moving text"
image_width = 1280
image_height = 720
bg_color = (255, 255, 255)
text_color = (0, 0, 0)
font = "Arial"
direction = 'left'
clip = text_scrolling_clip(text, image_width, image_height, bg_color, text_color, font, direction, num_frames)
clip.write_videofile("text_scrolling.mp4", fps=fps)
"""
https://pjoshi15.com/create-typewriter-effect-animation-using-python/
Create Typewriter Effect Animation Using Python
Typing animation is an eye-catching video effect in today’s times of reels and short videos. In this tutorial, I will teach you how to create a typewriter animation using Python.
Once you know how to implement this animation, you can then use it to create interactive and dynamic presentations, illustrations, and social media content.
Understanding the Typewriter Effect
The typewriter effect animation is a popular aesthetic choice that simulates the appearance of text being typed onto the screen one character at a time. Often used in videos, presentations, and web-based projects, this effect helps deliver messages uniquely and engagingly.
When we talk about typing animation using Python, we’re referring to creating a script that simulates the typing process. Python libraries such as OpenCV, Pillow, and numpy facilitate implementing the typing effect. By leveraging these libraries, we can produce interactive text-based applications as well as visuals for a variety of content.
Applying the typing animation in video requires a somewhat different approach compared to static text-based applications.
For video, we may have to employ frame-by-frame processing to create the typing effect, allowing us to time the appearance of each character precisely.
Setting Up Python for Animation
First, ensure that you have Python 3.x installed on your system. If you’re unsure which version you have run python --version or python3 --version in your command prompt or terminal.
If you need a newer version, download it from the official Python website.
With Python ready, let’s install the necessary third-party packages. Run the following commands in your terminal or command prompt:
"""
# pip install -U opencv-python
# pip install pillow
"""
Creating Text Typing Animation using Python
Creating typing animation using Python is relatively straightforward, and we’ll guide you through it step by step.
By using this approach, you can give your videos, presentations, or other applications a professional touch with an eye-catching typing effect.
Let’s load the libraries
"""
# import cv2
# import numpy as np
# from PIL import ImageFont, ImageDraw, Image
"""
Define Function to Create Typing Animation
This Python function will create the typewriter effect animation and add that animation to a video. The text font size, video duration, and frames per second in the video can be controlled by the user.
We can also add colors and sound to this video, but let’s keep it aside for some other tutorial.
"""
def create_video_with_typewriter_effect(text, output_filename, fontsize=30, video_fps=30, video_duration=10):
font = ImageFont.truetype("arial.ttf", fontsize)
# dimensions of video
video_width = 800
video_height = 60
video_size = (video_width, video_height)
video = cv2.VideoWriter(output_filename,
cv2.VideoWriter_fourcc(*'mp4v'),
video_fps,
video_size)
# Calculate the text width and height
text_width, text_height = font.getsize(text)
# Video settings
text_fade_duration = 1 # seconds
text_typing_duration = video_duration - text_fade_duration
# Calculate the number of frames for the typewriter effect
num_typing_frames = int(text_typing_duration * video_fps)
num_fade_frames = int(text_fade_duration * video_fps)
# Typing effect
for frame_idx in range(num_typing_frames):
frame = np.zeros((video_height, video_width, 3), dtype=np.uint8)
frame_pil = Image.fromarray(frame)
draw = ImageDraw.Draw(frame_pil)
current_text = text[:int(len(text) * frame_idx / num_typing_frames)]
draw.text((10, 10), current_text, font=font, fill=(255, 255, 255, 255))
video.write(np.array(frame_pil))
# Fade out effect
for frame_idx in range(num_fade_frames):
frame = np.zeros((video_height, video_width, 3), dtype=np.uint8)
frame_pil = Image.fromarray(frame)
draw = ImageDraw.Draw(frame_pil)
alpha = 255 - int(255 * frame_idx / num_fade_frames)
draw.text((10, 10), text, font=font, fill=(255, 255, 255, alpha))
video.write(np.array(frame_pil))
video.release()
"""
Pass an input sentence to the function above along with a file name for the output video. The typing effect will be applied to this input sentence.
If you want to change the speed of the typing animation effect then you can also pass different values of video_fps and video_duration arguments to the function
"""
text = "This is a typewriter animation created using Python."
output_filename = "typewriter_animation.mp4"
create_video_with_typewriter_effect(text, output_filename)
"""
Finally, we get the following output video of typewriter-effect animation built using Python.
End Notes
In this article, we’ve explored an exciting technique of creating typewriter-effect animations using Python.
"""
# Generate YouTube Shorts Videos using Python
# https://pjoshi15.com/generate-youtube-shorts-python/
# import cv2
# import os
def create_video_from_images(images_folder, output_video, fps=10, duration=6):
images = sorted(os.listdir(images_folder))
# create path to the input images
img_path = os.path.join(images_folder, images[0])
# load image
frame = cv2.imread(img_path)
# extract dimensions of the image
height, width, channels = frame.shape
video_writer = cv2.VideoWriter(output_video,
cv2.VideoWriter_fourcc(*'mp4v'),
fps,
(width, height))
# total number of frames for the video
frames_per_image = fps * duration
for image in images:
img_path = os.path.join(images_folder, image)
frame = cv2.imread(img_path)
for _ in range(frames_per_image):
video_writer.write(frame)
video_writer.release()
print(f"Video {output_video} created successfully")
# generate video
create_video_from_images("/images", "out.mp4")
### moviepy implementation
from moviepy.editor import ImageClip, concatenate_videoclips
import os
def create_video_from_images(images_folder, output_video, fps=10, duration=6):
# Get a list of image files in the folder
image_files = [img for img in os.listdir(images_folder) if img.endswith(".png")]
# Create video clips from the images
clips = [ImageClip(os.path.join(images_folder, img)).set_duration(duration) for img in image_files]
# Concatenate the clips into a single video
final_clip = concatenate_videoclips(clips, method="compose")
# Write the video to the specified output file
final_clip.write_videofile(output_video, fps=fps, codec="libx264")
print(f"Video {output_video} created successfully")
# Example usage
images_folder = "path/to/your/images"
output_video = "output_video.mp4"
create_video_from_images(images_folder, output_video)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment