posts - 11,  comments - 0,  views - 663
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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)

单个字幕移动可参照,字符动态效果

posted on   msms123  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示