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

使用MoviePy添加字幕时脚本崩溃的问题求助

MoviePy添加SRT字幕崩溃问题解决

问题情况

使用MoviePy生成.srt字幕并添加到视频时出现崩溃:无字幕视频通过_match_audio_duration()可正常导出,字幕文件已生成但脚本在添加字幕环节报错,实际崩溃根源在SubtitlesClip初始化步骤,而非最初以为的CompositeVideoClip代码行。

报错信息

Traceback (most recent call last):
  File "*directory*", line 86, in <module>
    editor.add_captions_to_video()
  File "*directory*", line 69, in add_captions_to_video
    captions = SubtitlesClip(self.caption_path)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "*directory*", line 55, in __init__
    self.duration = max([tb for ((ta,tb), txt) in self.subtitles])
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "*directory*", line 55, in <listcomp>
    self.duration = max([tb for ((ta,tb), txt) in self.subtitles])
                                 ^^^^^^^
TypeError: cannot unpack non-iterable NoneType object
Exception ignored in: <function FFMPEG_VideoReader.__del__ at 0x000002097E824400>
Traceback (most recent call last):
  File "*directory*", line 199, in __del__
    self.close()
  File "*directory*", line 190, in close
    self.proc.terminate()
  File "*directory*", line 1642, in terminate
    _winapi.TerminateProcess(self._handle, 1)
OSError: [WinError 6] The handle is invalid

完整代码

import os
import subprocess
import time
import moviepy.editor as mp
import pyttsx3
from moviepy.video.tools.subtitles import SubtitlesClip

class VideoEditor:
    def __init__(self, input_text_path, input_video_path, output_dir):
        self.input_text_path = input_text_path
        self.input_video_path = input_video_path
        self.output_dir = output_dir

        self.text = ""
        self.audio_path = ""
        self.video_path = ""
        self.caption_path = ""

    def _convert_text_to_audio(self):
        # Read text from file
        with open(self.input_text_path, "r") as f:
            self.text = f.read()

        # Set up pyttsx3
        engine = pyttsx3.init()

        # Convert text to speech and save as MP3
        self.audio_path = os.path.join(self.output_dir, "audio.mp3")
        engine.save_to_file(self.text, self.audio_path)
        engine.runAndWait()

    def _match_audio_duration(self):
        # Set up moviepy
        input_clip = mp.VideoFileClip(self.input_video_path)
        audio_clip = mp.AudioFileClip(self.audio_path)
        if audio_clip.duration > input_clip.duration:
            input_clip = input_clip.fx(mp.vfx.loop, duration=audio_clip.duration)

        # Add audio to video
        final_clip = input_clip.set_audio(audio_clip)

        # Cut video to match audio duration
        final_clip = final_clip.subclip(0, audio_clip.duration)

        # Save output video
        self.video_path = os.path.join(self.output_dir, "output_video.mp4")
        final_clip.write_videofile(self.video_path, fps=24)

    def _create_captions(self):
        # Create captions from text
        self.caption_path = os.path.join(self.output_dir, "captions.srt")
        caption_txt = ""
        for i, line in enumerate(self.text.splitlines()):
            start = i * 3
            end = (i + 1) * 3
            caption_txt += f"{start}00 --> {end}00\n{line}\n\n"
        with open(self.caption_path, "w") as f:
            f.write(caption_txt)

    def add_captions_to_video(self):
        self._convert_text_to_audio()
        self._match_audio_duration()
        self._create_captions()

        # Set up moviepy
        input_clip = mp.VideoFileClip(self.video_path)

        # Create TextClip for captions
        captions = SubtitlesClip(self.caption_path)

        caption_clip = captions.set_position(("center", "bottom"))

        # Overlay captions on video
        final_clip = mp.CompositeVideoClip([input_clip, caption_clip.set_position(("center", "bottom"))])

        # Save output video
        output_path = os.path.join(self.output_dir, "output_video_captions.mp4")
        final_clip.write_videofile(output_path, fps=24)

问题根源

崩溃的核心原因是生成的SRT字幕格式完全不符合标准:

  • SRT要求时间格式为HH:MM:SS,mmm(小时:分钟:秒,毫秒),但当前代码生成的是00 --> 300这类无效格式
  • SRT每条字幕必须以递增的数字序号开头,当前代码用start = i*3作为序号,逻辑错误

以上两点导致SubtitlesClip无法解析字幕文件,返回None进而触发unpack错误。

解决方案

1. 修正SRT生成逻辑

修改_create_captions方法,生成符合标准的SRT格式:

def _create_captions(self):
    # Create captions from text
    self.caption_path = os.path.join(self.output_dir, "captions.srt")
    caption_txt = ""
    lines = self.text.splitlines()
    for i, line in enumerate(lines):
        # 计算每条字幕的起止时间(按每条3秒计算)
        start_sec = i * 3
        end_sec = (i + 1) * 3

        # 转换为SRT标准时间格式:HH:MM:SS,mmm
        def format_time(seconds):
            hours = int(seconds // 3600)
            minutes = int((seconds % 3600) // 60)
            secs = int(seconds % 60)
            millis = int((seconds - int(seconds)) * 1000)
            return f"{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}"

        start_time = format_time(start_sec)
        end_time = format_time(end_sec)

        # 拼接SRT条目:序号 + 时间轴 + 文本
        caption_txt += f"{i+1}\n{start_time} --> {end_time}\n{line}\n\n"
    
    with open(self.caption_path, "w", encoding="utf-8") as f:
        f.write(caption_txt)

2. 完善SubtitlesClip初始化

SubtitlesClip需要传入一个生成文本剪辑的函数来定义字幕样式,否则可能出现渲染问题。修改add_captions_to_video中的对应部分:

def add_captions_to_video(self):
    self._convert_text_to_audio()
    self._match_audio_duration()
    self._create_captions()

    # Set up moviepy
    input_clip = mp.VideoFileClip(self.video_path)

    # 自定义字幕样式函数
    def make_text_clip(txt):
        return mp.TextClip(txt, fontsize=24, color="white", font="Arial", stroke_color="black", stroke_width=1)

    # 使用自定义样式初始化SubtitlesClip
    captions = SubtitlesClip(self.caption_path, make_text_clip)

    caption_clip = captions.set_position(("center", "bottom"))

    # Overlay captions on video
    final_clip = mp.CompositeVideoClip([input_clip, caption_clip])

    # Save output video
    output_path = os.path.join(self.output_dir, "output_video_captions.mp4")
    final_clip.write_videofile(output_path, fps=24)

验证要点

  • 生成的SRT文件需符合以下结构:
1
00:00:00,000 --> 00:00:03,000
第一条文本内容

2
00:00:03,000 --> 00:00:06,000
第二条文本内容
  • 确保字体存在,若使用非系统字体需指定完整路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:10:05