调用MoviePy的TextClip触发TypeError:预期str/bytes/PathLike而非tuple
问题描述
我尝试将编辑后的视频片段拼接成最终影片,目标是为每个片段添加主播名称文字叠加层后再拼接。以下是我的代码:
PATH_TO_VALID_CLIPS = 'VideoCompilation/ClipData/valid_clips.txt' PATH_TO_RAW_CLIPS = 'VideoCompilation\VideoFiles\\raw_clips' FONT_PATH = 'E:\Projects\TwitchMontage\VideoCompilation\Fonts\Twitchy.TV Font\Twitchy.TV.ttf' def read_valid_clips_list(): #read valid clips file = open(PATH_TO_VALID_CLIPS, 'r') list = file.readlines() return list def get_clip_data(filename): file = open('VideoCompilation\ClipData\clips_data.json') clips_data = json.load(file) return clips_data[filename] def create_clips(list): clips = [] for filename in list: filename = filename.strip() video_file_path = os.path.join(PATH_TO_RAW_CLIPS, filename) clip = VideoFileClip(video_file_path) clip = clip.fx(vfx.fadein, .1).fx(vfx.fadeout, .15) clip = add_text_overlay(clip, filename) clips.append(clip) return clips def create_draft(clips): draft = concatenate_videoclips(clips, method='compose') draft.write_videofile("VideoCompilation/VideoFiles/videos/draft.mp4") return draft def add_text_overlay(clip, file): clip_data = get_clip_data(file) streamerName = str(clip_data.get('streamerName')) text_clip = TextClip(txt = streamerName, size = (400,0), color = (145, 70, 255)) tc_width, tc_height = text_clip.size text_clip = text_clip.set_position(0, tc_height) text_clip = text_clip.set_duration(2) clip = CompositeVideoClip([clip, text_clip]) return clip def create_movie(): list = read_valid_clips_list() clips = create_clips(list) draft = create_draft(clips) return draft movie = create_movie()
运行时出现如下错误回溯:
[Running] python -u "e:\Projects\TwitchMontage\VideoCompilation\src\create_video.py" Traceback (most recent call last): File "e:\Projects\TwitchMontage\VideoCompilation\src\create_video.py", line 60, in <module> movie = create_movie() File "e:\Projects\TwitchMontage\VideoCompilation\src\create_video.py", line 55, in create_movie clips = create_clips(list) File "e:\Projects\TwitchMontage\VideoCompilation\src\create_video.py", line 30, in create_clips clip = add_text_overlay(clip, filename) File "e:\Projects\TwitchMontage\VideoCompilation\src\create_video.py", line 45, in add_text_overlay text_clip = TextClip(txt = "streamerName", size = (400,0), color = (145, 70, 255)) File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\site-packages\moviepy\video\VideoClip.py", line 1137, in __init__ subprocess_call(cmd, logger=None) File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\site-packages\moviepy\tools.py", line 46, in subprocess_call proc = sp.Popen(cmd, **popen_params) File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 854, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 1247, in _execute_child args = list2cmdline(args) File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 549, in list2cmdline for arg in map(os.fsdecode, seq): File "C:\Users\Alejandro\AppData\Local\Programs\Python\Python38\lib\os.py", line 816, in fsdecode filename = fspath(filename) # Does type-checking of `filename`. TypeError: expected str, bytes or os.PathLike object, not tuple
问题分析与修复
错误根源
- 颜色参数格式错误:
TextClip的color参数不能传RGB元组,必须是字符串格式(比如十六进制值"#9146ff"或颜色名称"purple"),元组会导致内部ffmpeg命令解析失败,触发类型错误。 - 路径转义问题:Windows路径用反斜杠
\会被Python当作转义字符,导致字体路径无法正确识别。 - 未指定自定义字体:定义了
FONT_PATH但没在TextClip中使用,可能导致默认字体渲染异常。 - 文本位置与时长不合理:
set_position(0, tc_height)把文字放到了视频可视区域外;set_duration(2)强制文字只显示2秒,不符合视频片段实际时长。 - 文件资源未释放:直接打开文件后未关闭,存在资源泄漏风险。
修复后的代码
import os import json from moviepy.editor import VideoFileClip, CompositeVideoClip, TextClip, concatenate_videoclips import moviepy.video.fx.all as vfx PATH_TO_VALID_CLIPS = 'VideoCompilation/ClipData/valid_clips.txt' PATH_TO_RAW_CLIPS = 'VideoCompilation/VideoFiles/raw_clips' # 修正路径转义,用正斜杠替代反斜杠 FONT_PATH = 'E:/Projects/TwitchMontage/VideoCompilation/Fonts/Twitchy.TV Font/Twitchy.TV.ttf' def read_valid_clips_list(): # 用with语句自动关闭文件 with open(PATH_TO_VALID_CLIPS, 'r') as file: return [line.strip() for line in file.readlines()] def get_clip_data(filename): # 用with语句自动关闭文件 with open('VideoCompilation/ClipData/clips_data.json') as file: clips_data = json.load(file) return clips_data[filename] def create_clips(clips_list): clips = [] for filename in clips_list: video_file_path = os.path.join(PATH_TO_RAW_CLIPS, filename) clip = VideoFileClip(video_file_path) clip = clip.fx(vfx.fadein, 0.1).fx(vfx.fadeout, 0.15) clip = add_text_overlay(clip, filename) clips.append(clip) return clips def create_draft(clips): draft = concatenate_videoclips(clips, method='compose') draft.write_videofile("VideoCompilation/VideoFiles/videos/draft.mp4") return draft def add_text_overlay(clip, file): clip_data = get_clip_data(file) streamer_name = str(clip_data.get('streamerName', '')) # 修正颜色格式,指定自定义字体,用fontsize控制文字大小 text_clip = TextClip( txt=streamer_name, font=FONT_PATH, fontsize=40, color="#9146ff" ) # 设置文字在左下角,添加边距避免贴边 text_clip = text_clip.set_position(("left", "bottom"), relative=True).margin(left=20, bottom=20) # 文字时长与原视频保持一致 text_clip = text_clip.set_duration(clip.duration) return CompositeVideoClip([clip, text_clip]) def create_movie(): clips_list = read_valid_clips_list() clips = create_clips(clips_list) draft = create_draft(clips) return draft movie = create_movie()
关键修复说明
- 将RGB颜色元组改为十六进制字符串,符合
TextClip参数要求。 - 统一用正斜杠写文件路径,避免转义问题。
- 在
TextClip中指定自定义字体,确保文字渲染符合预期。 - 调整文字位置到视频可视区域,设置与原视频相同的时长。
- 使用
with语句管理文件,自动释放资源。 - 变量名改为PEP8规范格式,提升代码可读性。
内容的提问来源于stack exchange,提问作者Alejandro
相关产品推荐
相关产品推荐

