|
|
@@ -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}")
|