You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用MoviePy实现文本超出屏幕时自动换行?

在MoviePy中实现文本自动换行的解决方案

MoviePy本身并没有内置的文本自动换行功能,不过我们可以通过手动计算文本宽度来实现这个需求,或者用一些替代方案达到同样的效果。下面给你两种可行的方法:

方法一:手动计算文本宽度,插入换行符

这个思路是把文本拆分成单词,逐个计算每个单词的宽度,当累积宽度超过设定的最大允许宽度时,就插入换行符。我们可以用PIL的ImageFont来计算文本宽度,配合MoviePy的TextClip使用:

from moviepy.editor import TextClip
from PIL import ImageFont

def wrap_text(text, font_path, font_size, max_width):
    # 加载指定字体
    font = ImageFont.truetype(font_path, font_size)
    words = text.split(' ')
    wrapped_lines = []
    current_line = []
    current_width = 0
    
    for word in words:
        # 计算当前单词的宽度
        word_width, _ = font.getsize(word)
        # 如果当前行已有内容,还要加上空格的宽度
        if current_line:
            space_width, _ = font.getsize(' ')
            current_width += space_width
        
        # 如果加入当前单词后不超过最大宽度,就继续添加到当前行
        if current_width + word_width <= max_width:
            current_line.append(word)
            current_width += word_width
        else:
            # 当前行已满,把它加入结果列表,然后开始新的一行
            wrapped_lines.append(' '.join(current_line))
            current_line = [word]
            current_width = word_width
    
    # 别忘了把最后一行也加入结果
    if current_line:
        wrapped_lines.append(' '.join(current_line))
    
    return '\n'.join(wrapped_lines)

# 实际使用示例
original_text = "这里是一段很长的测试文本,当它的长度超出视频屏幕的边界时,我们希望它能自动换行显示,而不是被截断或者溢出屏幕"
font_path = "simhei.ttf"  # 替换成你本地的字体文件路径
font_size = 40
screen_width = 1920  # 你的视频分辨率宽度,比如1080p是1920
max_text_width = screen_width * 0.9  # 留10%的边距,避免贴边

# 获取处理后的带换行的文本
wrapped_text = wrap_text(original_text, font_path, font_size, max_text_width)
# 创建TextClip
text_clip = TextClip(wrapped_text, font=font_path, fontsize=font_size, color='white')

方法二:用PIL生成带换行的图片,再转为ImageClip

如果觉得手动计算有点麻烦,也可以先通过PIL绘制一张已经自动换行的文本图片,再把这张图片导入MoviePy作为ImageClip使用,效果是一样的:

from PIL import Image, ImageDraw, ImageFont
from moviepy.editor import ImageClip

def create_wrapped_text_image(text, font_path, font_size, max_width, text_color='white', bg_color='black'):
    font = ImageFont.truetype(font_path, font_size)
    # 先拆分文本为多行(逻辑和方法一类似)
    lines = []
    words = text.split(' ')
    current_line = []
    current_width = 0
    
    for word in words:
        word_width, _ = font.getsize(word)
        if current_line:
            space_width, _ = font.getsize(' ')
            current_width += space_width
        if current_width + word_width <= max_width:
            current_line.append(word)
            current_width += word_width
        else:
            lines.append(' '.join(current_line))
            current_line = [word]
            current_width = word_width
    if current_line:
        lines.append(' '.join(current_line))
    
    # 计算图片需要的高度(每行的高度乘以行数)
    line_height = font.getsize('A')[1]
    img_height = line_height * len(lines)
    # 创建空白图片
    img = Image.new('RGB', (max_width, img_height), bg_color)
    draw = ImageDraw.Draw(img)
    
    # 逐行绘制文本
    y_offset = 0
    for line in lines:
        draw.text((0, y_offset), line, font=font, fill=text_color)
        y_offset += line_height
    
    # 保存临时图片(也可以直接用PIL对象转,不过保存后导入更直观)
    img.save('wrapped_text_temp.png')
    return ImageClip('wrapped_text_temp.png')

# 使用示例
original_text = "这里是一段很长的测试文本,当它的长度超出视频屏幕的边界时,我们希望它能自动换行显示,而不是被截断或者溢出屏幕"
font_path = "simhei.ttf"
font_size = 40
max_text_width = int(1920 * 0.9)

text_clip = create_wrapped_text_image(original_text, font_path, font_size, max_text_width)

注意事项

  • 记得替换代码中的font_path为你本地实际的字体文件路径,比如Windows下可以用"C:/Windows/Fonts/simhei.ttf",Mac下路径类似"/Library/Fonts/SimHei.ttf"
  • max_width要根据你的视频分辨率调整,比如720p的屏幕宽度是1280,对应的max_text_width可以设为1280*0.9
  • 如果你的文本包含中文,一定要用支持中文的字体,不然会显示乱码

内容的提问来源于stack exchange,提问作者Triple tree

火山引擎 最新活动