You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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
问题分析与修复

错误根源

  1. 颜色参数格式错误:TextClip的color参数不能传RGB元组,必须是字符串格式(比如十六进制值"#9146ff"或颜色名称"purple"),元组会导致内部ffmpeg命令解析失败,触发类型错误。
  2. 路径转义问题:Windows路径用反斜杠\会被Python当作转义字符,导致字体路径无法正确识别。
  3. 未指定自定义字体:定义了FONT_PATH但没在TextClip中使用,可能导致默认字体渲染异常。
  4. 文本位置与时长不合理:set_position(0, tc_height)把文字放到了视频可视区域外;set_duration(2)强制文字只显示2秒,不符合视频片段实际时长。
  5. 文件资源未释放:直接打开文件后未关闭,存在资源泄漏风险。

修复后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 22:06:34