Browse Source

直接返回mp4格式文件路径

xujunwei 5 months atrás
parent
commit
844d0f4d08
1 changed files with 71 additions and 21 deletions
  1. 71 21
      app.py

+ 71 - 21
app.py

@@ -319,9 +319,23 @@ def yolov12_predict(params: PredictParams):
             if field not in ['model'] and value is not None:
                 predict_kwargs[field] = value
         
-        # 确保保存结果
+        # 确保保存结果,并强制使用MP4格式
         predict_kwargs['save'] = True
         
+        # 如果输入是视频,强制设置输出格式为MP4
+        source = params.source
+        if source:
+            import os
+            source_ext = os.path.splitext(source)[1].lower()
+            video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.webm', '.flv', '.wmv']
+            
+            if source_ext in video_extensions:
+                # 对于视频输入,设置项目名和实验名以确保输出路径
+                if not predict_kwargs.get('project'):
+                    predict_kwargs['project'] = 'runs/detect'
+                if not predict_kwargs.get('name'):
+                    predict_kwargs['name'] = 'predict'
+        
         results = model.predict(**predict_kwargs)
         logging.info("模型预测完成")
         
@@ -458,27 +472,63 @@ def yolov12_predict(params: PredictParams):
                             except (FileNotFoundError, subprocess.SubprocessError) as e:
                                 logging.error(f"ffmpeg不可用: {e}")
                                 
-                                # 如果ffmpeg不可用,尝试使用OpenCV
-                                try:
-                                    import cv2
-                                    cap = cv2.VideoCapture(video_file)
-                                    fps = cap.get(cv2.CAP_PROP_FPS)
-                                    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
-                                    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
-                                    
-                                    # 尝试不同的编码器
-                                    fourcc_options = ['H264', 'avc1', 'mp4v']
-                                    out = None
-                                    
-                                    for fourcc in fourcc_options:
-                                        try:
-                                            codec = cv2.VideoWriter_fourcc(*fourcc)
-                                            out = cv2.VideoWriter(output_mp4, codec, fps, (width, height))
+                                                                    # 如果ffmpeg不可用,尝试使用OpenCV
+                                    try:
+                                        import cv2
+                                        cap = cv2.VideoCapture(video_file)
+                                        fps = cap.get(cv2.CAP_PROP_FPS)
+                                        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+                                        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+                                        
+                                        # 强制使用H264编码器,如果失败则使用XVID
+                                        fourcc_options = ['H264', 'avc1']
+                                        out = None
+                                        
+                                        for fourcc in fourcc_options:
+                                            try:
+                                                codec = cv2.VideoWriter_fourcc(*fourcc)
+                                                out = cv2.VideoWriter(output_mp4, codec, fps, (width, height))
+                                                if out.isOpened():
+                                                    logging.info(f"使用OpenCV编码器 {fourcc}")
+                                                    break
+                                            except:
+                                                continue
+                                        
+                                        # 如果H264和avc1都失败,使用XVID生成AVI,然后用ffmpeg转换
+                                        if not out or not out.isOpened():
+                                            logging.warning("H264编码器不可用,使用XVID生成AVI")
+                                            temp_avi = video_file.rsplit('.', 1)[0] + '_temp.avi'
+                                            xvid_codec = cv2.VideoWriter_fourcc(*'XVID')
+                                            out = cv2.VideoWriter(temp_avi, xvid_codec, fps, (width, height))
+                                            
                                             if out.isOpened():
-                                                logging.info(f"使用OpenCV编码器 {fourcc}")
-                                                break
-                                        except:
-                                            continue
+                                                while cap.isOpened():
+                                                    ret, frame = cap.read()
+                                                    if not ret:
+                                                        break
+                                                    out.write(frame)
+                                                
+                                                cap.release()
+                                                out.release()
+                                                
+                                                # 尝试用ffmpeg将AVI转换为MP4
+                                                try:
+                                                    cmd = [
+                                                        'ffmpeg', '-i', temp_avi,
+                                                        '-c:v', 'libx264',
+                                                        '-preset', 'ultrafast',
+                                                        '-crf', '28',
+                                                        '-pix_fmt', 'yuv420p',
+                                                        '-y', output_mp4
+                                                    ]
+                                                    result = subprocess.run(cmd, capture_output=True, text=True)
+                                                    if result.returncode == 0:
+                                                        os.remove(temp_avi)
+                                                        logging.info(f"通过AVI中转成功生成MP4: {output_mp4}")
+                                                    else:
+                                                        logging.error(f"AVI转MP4失败: {result.stderr}")
+                                                except Exception as e:
+                                                    logging.error(f"ffmpeg不可用,保持AVI格式: {e}")
                                     
                                     if out and out.isOpened():
                                         while cap.isOpened():