moviepy==1.0.2
整塊字幕移動
# 字幕整塊平移🆗
from moviepy.editor import VideoFileClip, CompositeVideoClip, ImageClip
from PIL import Image, ImageFont, ImageDraw
import numpy as np
def wrap_text(text, font, max_width):
"""
自動換行函式:根據指定的最大寬度對文字進行折行
:param text: 字幕文字
:param font: PIL字型物件
:param max_width: 每行最大寬度
:return: 換行後的文字列表
"""
lines = []
current_line = ""
for char in text: # 中文按字元處理
test_line = current_line + char
line_width = font.getbbox(test_line)[2] # 使用 getbbox(文字邊界) 獲取寬度
if line_width <= max_width:
current_line = test_line
else:
lines.append(current_line)
current_line = char
if current_line: # 新增最後一行
lines.append(current_line)
return lines
def generate_subtitle_image(text, font_path, font_size, video_width, video_height, white_space):
"""
生成帶有字幕的影像,自動換行
:param text: 字幕文字
:param font_path: 字型路徑
:param font_size: 字型大小
:param video_width: 影片寬度
:param video_height: 影片高度
:param white_space: 影片左右留白
:return: 帶有字幕的影像(numpy陣列)
"""
font = ImageFont.truetype(font_path, font_size)
max_width = video_width - white_space # 留左右邊距
# 自動換行
wrapped_text = wrap_text(text, font, max_width)
# 建立字幕影像
image = Image.new("RGBA", (video_width, video_height), (255, 255, 255, 0)) # 透明背景
draw = ImageDraw.Draw(image)
# 繪製字幕:居中顯示,每行水平居中,底部顯示
line_height = font.getbbox("測試")[3] # 使用 getbbox 獲取行高
y_position = video_height - line_height * len(wrapped_text) - 20 # 字幕距底部20畫素
for line in wrapped_text:
text_width = font.getbbox(line)[2]
x_position = (video_width - text_width) // 2 # 居中
draw.text((x_position, y_position), line, font=font, fill="white")
y_position += line_height
return np.array(image)
def add_scroll_effect(subtitle_image, video_clip, duration=3):
"""
給字幕新增平移效果(從上至下)
:param subtitle_image: 字幕影像(numpy陣列)
:param video_clip: 影片剪輯
:param duration: 平移的持續時間
:return: 帶平移效果的字幕剪輯
"""
subtitle_clip = ImageClip(subtitle_image, duration=duration)
# 獲取字幕的最終y座標(影片底部附近)
final_y_position = video_clip.h - subtitle_clip.h - 20 # 字幕停留在影片底部
# 設定字幕從頂部滑入,平移至底部
subtitle_clip = subtitle_clip.set_position(lambda t: ("center", min(final_y_position, -subtitle_clip.h + t * (video_clip.h + subtitle_clip.h) / duration)))
return subtitle_clip
def output(subtitle_clip, video_clip, output_path):
# 合成影片
composite_clip = CompositeVideoClip([video_clip, subtitle_clip])
# 輸出影片
composite_clip.write_videofile(output_path, codec="libx264", fps=24)
if __name__ == '__main__':
# 影片路徑
video_path = "1127.mp4"
output_path = "output_with_falling_subtitles.mp4"
# 載入影片並獲取寬高
video_clip = VideoFileClip(video_path)
video_width, video_height = video_clip.w, video_clip.h
# 字幕文字
subtitle_text = "這是一個字幕示例,平移到影片底部"
# 字幕樣式
custom_font_path = r"C:\Windows\Fonts\msyh.ttc" # 替換為實際字型路徑
font_size = 50
white_space = 20 # 字幕左右留白
# 生成字幕影像
subtitle_image = generate_subtitle_image(
subtitle_text, custom_font_path, font_size, video_width, video_height, white_space
)
# 給字幕新增平移效果
subtitle_clip = add_scroll_effect(subtitle_image, video_clip)
# 合成影片並應用字幕效果
output(subtitle_clip, video_clip, output_path)
從右到左
#整個字幕從右到左🆗
from moviepy.editor import VideoFileClip, CompositeVideoClip, ImageClip
from PIL import Image, ImageFont, ImageDraw
import numpy as np
def wrap_text(text, font, max_width):
"""
自動換行函式:根據指定的最大寬度對文字進行折行
:param text: 字幕文字
:param font: PIL字型物件
:param max_width: 每行最大寬度
:return: 換行後的文字列表
"""
lines = []
current_line = ""
for char in text: # 中文按字元處理
test_line = current_line + char
line_width = font.getbbox(test_line)[2] # 使用 getbbox(文字邊界) 獲取寬度
if line_width <= max_width:
current_line = test_line
else:
lines.append(current_line)
current_line = char
if current_line: # 新增最後一行
lines.append(current_line)
return lines
def generate_subtitle_image(text, font_path, font_size, video_width, video_height, white_space):
"""
生成帶有字幕的影像,自動換行
:param text: 字幕文字
:param font_path: 字型路徑
:param font_size: 字型大小
:param video_width: 影片寬度
:param video_height: 影片高度
:param white_space: 影片左右留白
:return: 帶有字幕的影像(numpy陣列)
"""
font = ImageFont.truetype(font_path, font_size)
max_width = video_width - white_space # 留左右邊距
# 自動換行
wrapped_text = wrap_text(text, font, max_width)
# 建立字幕影像
image = Image.new("RGBA", (video_width, video_height), (255, 255, 255, 0)) # 透明背景
draw = ImageDraw.Draw(image)
# 繪製字幕:居中顯示,每行水平居中,底部顯示
line_height = font.getbbox("測試")[3] # 使用 getbbox 獲取行高
y_position = video_height - line_height * len(wrapped_text) - 20 # 字幕距底部20畫素
for line in wrapped_text:
text_width = font.getbbox(line)[2]
x_position = (video_width - text_width) // 2 # 居中
draw.text((x_position, y_position), line, font=font, fill="white")
y_position += line_height
return np.array(image)
def add_scroll_effect(subtitle_image, video_clip, text, font_path, font_size, white_space, duration=5, stay_duration=5):
"""
給字幕新增從右到左滾動效果,並最終固定在影片底部
:param subtitle_image: 字幕影像(numpy陣列)
:param video_clip: 影片剪輯
:param text: 字幕文字
:param font_path: 字型路徑
:param font_size: 字型大小
:param white_space: 字幕左右留白
:param duration: 滾動持續時間
:param stay_duration: 字幕停留時間(以秒為單位)
:return: 帶滾動效果的字幕剪輯
"""
subtitle_clip = ImageClip(subtitle_image, duration=duration + stay_duration)
# 設定字幕初始位置在螢幕右邊,使用 `set_position` 來實現滾動
def scroll_position(t):
max_x_position = video_clip.w + subtitle_clip.w
if t < duration: # 在滾動時間內,字幕從右到左
return max_x_position - (max_x_position * t / duration), video_clip.h - subtitle_clip.h - 20
else: # 滾動結束後,字幕保持在底部
return (video_clip.w - subtitle_clip.w) // 2, video_clip.h - subtitle_clip.h - 20
# 設定字幕開始時間和持續時間
subtitle_clip = subtitle_clip.set_position(scroll_position).set_start(0).set_duration(duration + stay_duration)
return subtitle_clip
def output(subtitle_clip, video_clip, output_path):
# 合成影片
composite_clip = CompositeVideoClip([video_clip, subtitle_clip])
# 輸出影片
composite_clip.write_videofile(output_path, codec="libx264", fps=24)
if __name__ == '__main__':
# 影片路徑
video_path = "1127.mp4"
output_path = "output_with_falling_subtitles.mp4"
# 載入影片並獲取寬高
video_clip = VideoFileClip(video_path)
video_width, video_height = video_clip.w, video_clip.h
# 字幕文字
subtitle_text = "ewrqwrwgf這是一個字幕示例,平移到影片底部"
# 字幕樣式
custom_font_path = r"C:\Windows\Fonts\msyh.ttc" # 替換為實際字型路徑
font_size = 50
white_space = 20 # 字幕左右留白
# 生成字幕影像
subtitle_image = generate_subtitle_image(subtitle_text, custom_font_path, font_size, video_width, video_height, white_space)
# 給字幕新增平移效果
subtitle_clip = add_scroll_effect(subtitle_image, video_clip, subtitle_text, custom_font_path, font_size, white_space, stay_duration=10)
# 合成影片並應用字幕效果
output(subtitle_clip, video_clip, output_path)
單個字幕移動可參照,字元動態效果