Просмотр исходного кода

直接返回mp4格式文件路径

xujunwei 5 месяцев назад
Родитель
Сommit
aede5cd45a
1 измененных файлов с 109 добавлено и 72 удалено
  1. 109 72
      app.py

+ 109 - 72
app.py

@@ -180,6 +180,21 @@ def start_gradio():
 # FastAPI部分
 app_fastapi = FastAPI()
 
+@app_fastapi.get("/")
+def read_root():
+    """根路径,返回摄像头检测页面"""
+    return FileResponse("camera_detect.html")
+
+@app_fastapi.get("/camera")
+def camera_page():
+    """摄像头检测页面"""
+    return FileResponse("camera_detect.html")
+
+@app_fastapi.get("/test-mp4")
+def test_mp4_page():
+    """MP4播放测试页面"""
+    return FileResponse("test_browser_mp4.html")
+
 class TrainParams(BaseModel):
     """
     用于接收/yolov12/train接口的训练参数,所有参数均需前端传入。
@@ -344,93 +359,115 @@ def yolov12_predict(params: PredictParams):
                         for ext in ['*.avi', '*.webm', '*.mov']:
                             video_files.extend(glob.glob(os.path.join(save_dir, ext)))
                         
-                        # 如果找到非MP4视频文件,转换为MP4
+                        # 如果找到非MP4视频文件,直接使用ffmpeg转换为MP4
                         for video_file in video_files:
                             output_mp4 = video_file.rsplit('.', 1)[0] + '.mp4'
                             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))
+                                import subprocess
                                 
-                                # 尝试不同的MP4编码器(按兼容性排序)
-                                fourcc_options = ['avc1', 'H264', 'mp4v']
-                                out = None
+                                # 使用ffmpeg转换为浏览器兼容的MP4格式
+                                cmd = [
+                                    'ffmpeg', '-i', video_file,
+                                    '-c:v', 'libx264',        # H.264编码器
+                                    '-preset', 'fast',        # 快速编码
+                                    '-crf', '23',            # 质量设置
+                                    '-movflags', '+faststart', # 优化网络播放
+                                    '-pix_fmt', 'yuv420p',   # 兼容性像素格式
+                                    '-y', output_mp4
+                                ]
                                 
-                                for fourcc in fourcc_options:
-                                    try:
-                                        fourcc_code = cv2.VideoWriter_fourcc(*fourcc)
-                                        out = cv2.VideoWriter(output_mp4, fourcc_code, fps, (width, height))
-                                        if out.isOpened():
-                                            logging.info(f"使用编码器 {fourcc} 创建MP4文件")
-                                            break
-                                    except:
-                                        continue
+                                logging.info(f"使用ffmpeg转换视频: {video_file} -> {output_mp4}")
+                                result = subprocess.run(cmd, capture_output=True, text=True)
                                 
-                                if out and out.isOpened():
-                                    while cap.isOpened():
-                                        ret, frame = cap.read()
-                                        if not ret:
-                                            break
-                                        out.write(frame)
+                                if result.returncode == 0:
+                                    # 验证生成的MP4文件
+                                    verify_cmd = [
+                                        'ffprobe', '-v', 'quiet', 
+                                        '-select_streams', 'v:0',
+                                        '-show_entries', 'stream=codec_name',
+                                        '-of', 'csv=p=0', output_mp4
+                                    ]
                                     
-                                    cap.release()
-                                    out.release()
+                                    verify_result = subprocess.run(verify_cmd, capture_output=True, text=True)
+                                    if verify_result.returncode == 0 and 'h264' in verify_result.stdout.lower():
+                                        os.remove(video_file)
+                                        logging.info(f"✓ 成功转换为H.264 MP4: {output_mp4}")
+                                    else:
+                                        logging.warning(f"生成的MP4可能不是H.264编码: {output_mp4}")
+                                else:
+                                    logging.error(f"ffmpeg转换失败: {result.stderr}")
                                     
-                                    # 使用ffmpeg进一步优化MP4文件(如果可用)
+                                    # 如果ffmpeg失败,尝试使用OpenCV作为备选方案
+                                    logging.info("尝试使用OpenCV作为备选方案")
                                     try:
-                                        import subprocess
-                                        temp_mp4 = output_mp4 + '.temp.mp4'
-                                        os.rename(output_mp4, temp_mp4)
+                                        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))
                                         
-                                        # 使用ffmpeg重新编码为H.264格式
-                                        cmd = [
-                                            'ffmpeg', '-i', temp_mp4,
-                                            '-c:v', 'libx264',
-                                            '-preset', 'fast',
-                                            '-crf', '23',
-                                            '-y', output_mp4
-                                        ]
+                                        # 尝试使用H264编码器
+                                        fourcc = cv2.VideoWriter_fourcc(*'H264')
+                                        out = cv2.VideoWriter(output_mp4, fourcc, fps, (width, height))
                                         
-                                        result = subprocess.run(cmd, capture_output=True, text=True)
-                                        if result.returncode == 0:
-                                            os.remove(temp_mp4)
-                                            logging.info(f"使用ffmpeg优化MP4文件: {output_mp4}")
-                                        else:
-                                            # ffmpeg失败,恢复原文件
-                                            os.rename(temp_mp4, output_mp4)
-                                            logging.warning(f"ffmpeg优化失败,使用OpenCV生成的MP4: {output_mp4}")
+                                        if out.isOpened():
+                                            while cap.isOpened():
+                                                ret, frame = cap.read()
+                                                if not ret:
+                                                    break
+                                                out.write(frame)
                                             
-                                    except (FileNotFoundError, subprocess.SubprocessError) as e:
-                                        # ffmpeg不可用,使用OpenCV生成的MP4
-                                        logging.warning(f"ffmpeg不可用,使用OpenCV生成的MP4: {output_mp4}")
-                                    
-                                    # 删除原文件
-                                    os.remove(video_file)
-                                    logging.info(f"视频已转换为MP4格式: {output_mp4}")
-                                else:
-                                    # OpenCV编码器失败,尝试使用ffmpeg直接转换
-                                    logging.warning(f"OpenCV编码器失败,尝试使用ffmpeg转换")
-                                    try:
-                                        import subprocess
-                                        cmd = [
-                                            'ffmpeg', '-i', video_file,
-                                            '-c:v', 'libx264',
-                                            '-preset', 'fast',
-                                            '-crf', '23',
-                                            '-y', output_mp4
-                                        ]
-                                        
-                                        result = subprocess.run(cmd, capture_output=True, text=True)
-                                        if result.returncode == 0:
+                                            cap.release()
+                                            out.release()
                                             os.remove(video_file)
-                                            logging.info(f"使用ffmpeg直接转换MP4文件: {output_mp4}")
+                                            logging.info(f"使用OpenCV H264编码器生成MP4: {output_mp4}")
                                         else:
-                                            logging.error(f"ffmpeg转换失败: {result.stderr}")
+                                            logging.error("OpenCV H264编码器也无法使用")
                                             
-                                    except (FileNotFoundError, subprocess.SubprocessError) as e:
-                                        logging.error(f"ffmpeg不可用,保持原格式: {e}")
+                                    except Exception as cv_error:
+                                        logging.error(f"OpenCV备选方案也失败: {cv_error}")
+                                        
+                            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))
+                                            if out.isOpened():
+                                                logging.info(f"使用OpenCV编码器 {fourcc}")
+                                                break
+                                        except:
+                                            continue
+                                    
+                                    if out and out.isOpened():
+                                        while cap.isOpened():
+                                            ret, frame = cap.read()
+                                            if not ret:
+                                                break
+                                            out.write(frame)
+                                        
+                                        cap.release()
+                                        out.release()
+                                        os.remove(video_file)
+                                        logging.info(f"使用OpenCV生成MP4: {output_mp4}")
+                                    else:
+                                        logging.error("所有编码器都无法使用")
+                                        
+                                except Exception as cv_error:
+                                    logging.error(f"OpenCV处理失败: {cv_error}")
                                     
                             except Exception as e:
                                 logging.error(f"转换视频格式时出错: {e}")