diff --git a/apps/worker/video_processing/processor.py b/apps/worker/video_processing/processor.py index 7af9dbf6b..236b602c5 100644 --- a/apps/worker/video_processing/processor.py +++ b/apps/worker/video_processing/processor.py @@ -61,18 +61,27 @@ class VideoProcessor: # 确保输出目录存在 os.makedirs(os.path.dirname(output_path), exist_ok=True) + # P2-6 Fix: 使用 try-finally 确保临时文件清理 + concat_file = None try: - # 创建临时文件列表 - concat_file = os.path.join(self.temp_dir, f"concat_{os.getpid()}.txt") - with open(concat_file, "w") as f: - for path in input_paths: - # FFmpeg concat demuxer 格式 - f.write(f"file '{os.path.abspath(path)}'\n") + # 使用 NamedTemporaryFile 确保临时文件正确清理 + concat_file = tempfile.NamedTemporaryFile( + mode="w", + suffix=".txt", + prefix="ffmpeg_concat_", + dir=self.temp_dir, + delete=True, + ) + for path in input_paths: + # FFmpeg concat demuxer 格式 + concat_file.write(f"file '{os.path.abspath(path)}'\n") + concat_file.flush() + concat_file_path = concat_file.name # 使用 FFmpeg 拼接视频 width, height = resolution ( - ffmpeg.input(concat_file, format="concat", safe=0) + ffmpeg.input(concat_file_path, format="concat", safe=0) .output( output_path, vcodec="libx264", @@ -86,9 +95,6 @@ class VideoProcessor: .run(capture_stdout=True, capture_stderr=True) ) - # 清理临时文件 - os.remove(concat_file) - # 获取视频元数据 probe = ffmpeg.probe(output_path) video_info = next(s for s in probe["streams"] if s["codec_type"] == "video") @@ -120,6 +126,13 @@ class VideoProcessor: except ffmpeg.Error as e: stderr = e.stderr.decode() if e.stderr else "" raise RuntimeError(f"FFmpeg error: {stderr}") from e + finally: + # P2-6 Fix: 确保临时文件在所有情况下都被清理 + if concat_file is not None: + try: + concat_file.close() + except Exception: + pass # 忽略关闭时的错误 def generate_thumbnail( self,