如何为MoviePy中的Pango添加文字描边效果?
MoviePy字幕实现文字描边的替代方案
因为Pango本身没有直接的描边属性,你可以通过以下几种方式模拟或实现文字描边效果:
方法1:双层文字叠加模拟描边
通过渲染两层文字,底层用深色放大版作为描边,上层用正常文字覆盖,快速实现近似描边的效果:
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip # 加载原视频 video = VideoFileClip("input.mp4") # 1. 生成描边层:深色文字+适当缩放 stroke_clip = TextClip('<span foreground="#000000">你的字幕内容</span>', fontsize=52, # 比主文字大2号作为描边宽度 font="Arial", method='pango') stroke_clip = stroke_clip.set_position(("center", "bottom")).set_duration(video.duration) # 2. 生成主文字层:正常颜色和大小 main_text = TextClip('<span foreground="#ffffff">你的字幕内容</span>', fontsize=50, font="Arial", method='pango') main_text = main_text.set_position(("center", "bottom")).set_duration(video.duration) # 叠加视频层 final_video = CompositeVideoClip([video, stroke_clip, main_text]) final_video.write_videofile("output.mp4")
方法2:利用Pango的text-shadow属性模拟描边
Pango的Markup支持CSS的text-shadow属性,通过多方向阴影叠加实现描边:
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip video = VideoFileClip("input.mp4") # 用四个方向的阴影模拟描边,阴影偏移量等于描边宽度 text_clip = TextClip('''<span foreground="#ffffff" style="text-shadow: 2px 2px 0 #000000, -2px -2px 0 #000000, 2px -2px 0 #000000, -2px 2px 0 #000000;">你的字幕内容</span>''', fontsize=50, font="Arial", method='pango') text_clip = text_clip.set_position(("center", "bottom")).set_duration(video.duration) final_video = CompositeVideoClip([video, text_clip]) final_video.write_videofile("output.mp4")
调整text-shadow里的偏移数值(比如把2px改成3px)可以控制描边的粗细。
方法3:用PIL绘制带描边的图片再导入
如果需要更精准的描边控制,可以用PIL先绘制带描边的文字图片,再转为MoviePy的剪辑:
from moviepy.editor import VideoFileClip, ImageClip, CompositeVideoClip from PIL import Image, ImageDraw, ImageFont # 加载原视频 video = VideoFileClip("input.mp4") # 创建透明背景图片 img_size = (800, 100) img = Image.new("RGBA", img_size, (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # 设置字体、文字内容和样式 font = ImageFont.truetype("Arial.ttf", 50) text = "你的字幕内容" stroke_width = 2 stroke_color = "black" fill_color = "white" text_center = (img_size[0]//2, img_size[1]//2) # 绘制描边:八个方向偏移绘制深色文字 offsets = [(dx, dy) for dx in [-stroke_width, 0, stroke_width] for dy in [-stroke_width, 0, stroke_width] if (dx, dy) != (0, 0)] for dx, dy in offsets: draw.text((text_center[0]+dx, text_center[1]+dy), text, font=font, fill=stroke_color, anchor="mm") # 绘制主文字 draw.text(text_center, text, font=font, fill=fill_color, anchor="mm") # 保存图片并导入到MoviePy img.save("stroke_subtitle.png") text_clip = ImageClip("stroke_subtitle.png").set_position(("center", "bottom")).set_duration(video.duration) # 合成视频 final_video = CompositeVideoClip([video, text_clip]) final_video.write_videofile("output.mp4")
内容的提问来源于stack exchange,提问作者user22047429
相关产品推荐
相关产品推荐

