From 97c3ed1fbe8dd02e9d252dbda4f060a8de1cc2bd Mon Sep 17 00:00:00 2001 From: linyqh Date: Sat, 16 Nov 2024 00:30:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(video=5Fprocessor=5Fv2):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=A7=86=E9=A2=91=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= =?UTF-8?q?-=20=E5=9C=A8=E6=8F=90=E5=8F=96=E5=85=B3=E9=94=AE=E5=B8=A7?= =?UTF-8?q?=E6=97=B6=E6=B7=BB=E5=8A=A0=20tqdm=20=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E6=9D=A1=20-=20=E7=A7=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E8=A1=8C=E5=92=8C=E5=A4=9A=E4=BD=99=E7=9A=84?= =?UTF-8?q?=E6=8D=A2=E8=A1=8C=E7=AC=A6=20-=20=E6=B7=BB=E5=8A=A0=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=8D=95=E8=8E=B7=E5=92=8C=E8=AF=A6=E7=BB=86=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=20-?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=B4=E6=97=B6=E6=96=87=E4=BB=B6=E6=B8=85?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E6=9C=BA=E5=88=B6=20-=20=E9=87=8A=E6=94=BE=E8=B5=84?= =?UTF-8?q?=E6=BA=90=EF=BC=8C=E5=8C=85=E6=8B=AC=E8=A7=86=E9=A2=91=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8F=A5=E6=9F=84=E5=92=8C=E4=B8=B4=E6=97=B6=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/utils/video_processor_v2.py | 61 ++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/app/utils/video_processor_v2.py b/app/utils/video_processor_v2.py index 038064a..6b59182 100644 --- a/app/utils/video_processor_v2.py +++ b/app/utils/video_processor_v2.py @@ -83,7 +83,7 @@ class VideoProcessor: keyframes = [] keyframe_indices = [] - for i in range(len(shot_boundaries)): + for i in tqdm(range(len(shot_boundaries)), desc="提取关键帧"): start = shot_boundaries[i - 1] if i > 0 else 0 end = shot_boundaries[i] shot_frames = frames[start:end] @@ -217,11 +217,10 @@ class VideoProcessor: if not frames: raise ValueError(f"跳过 {skip_seconds} 秒后没有剩余帧可以处理") - logger.info("\n检测场景边界...") + logger.info("检测场景边界...") shot_boundaries = self.detect_shot_boundaries(frames, threshold) logger.info(f"检测到 {len(shot_boundaries)} 个场景边界") - logger.info("\n提取关键帧...") keyframes, keyframe_indices = self.extract_keyframes(frames, shot_boundaries) adjusted_indices = [idx + skip_frames for idx in keyframe_indices] @@ -247,6 +246,9 @@ class VideoProcessor: os.makedirs(mini_frames_dir, exist_ok=True) os.makedirs(hd_frames_dir, exist_ok=True) + mini_processor = None + compressed_video = None + try: # 1. 压缩视频 video_name = os.path.splitext(os.path.basename(self.video_path))[0] @@ -268,20 +270,61 @@ class VideoProcessor: # 3. 从原始视频提取高清关键帧 logger.info("\n步骤3: 提取高清关键帧...") - frame_numbers = mini_processor.extract_numbers_from_folder(mini_frames_dir) + frame_numbers = self.extract_numbers_from_folder(mini_frames_dir) + + if not frame_numbers: + raise ValueError("未能从压缩视频中提取到有效的关键帧") + self.extract_frames_by_numbers(frame_numbers, hd_frames_dir) - logger.info(f"\n处理完成!") - logger.info(f"高清关键帧保存在: {hd_frames_dir}") + logger.info(f"处理完成!高清关键帧保存在: {hd_frames_dir}") + + except Exception as e: + import traceback + logger.error(f"视频处理失败: \n{traceback.format_exc()}") + raise finally: + # 释放资源 + if mini_processor: + mini_processor.cap.release() + del mini_processor + + # 确保视频文件句柄被释放 + if hasattr(self, 'cap'): + self.cap.release() + + # 等待资源释放 + import time + time.sleep(0.5) + if not keep_temp: - import shutil try: - shutil.rmtree(temp_dir) + # 先删除压缩视频文件 + if compressed_video and os.path.exists(compressed_video): + try: + os.remove(compressed_video) + except Exception as e: + logger.warning(f"删除压缩视频失败: {e}") + + # 再删除临时目录 + import shutil + if os.path.exists(temp_dir): + max_retries = 3 + for i in range(max_retries): + try: + shutil.rmtree(temp_dir) + break + except Exception as e: + if i == max_retries - 1: + logger.warning(f"清理临时文件失败: {e}") + else: + time.sleep(1) # 等待1秒后重试 + continue + logger.info("临时文件已清理") except Exception as e: - logger.info(f"清理临时文件时出错: {e}") + logger.warning(f"清理临时文件时出错: {e}") if __name__ == "__main__":