|
|
@@ -180,21 +180,6 @@ 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接口的训练参数,所有参数均需前端传入。
|
|
|
@@ -373,20 +358,19 @@ def yolov12_predict(params: PredictParams):
|
|
|
for ext in ['*.avi', '*.webm', '*.mov']:
|
|
|
video_files.extend(glob.glob(os.path.join(save_dir, ext)))
|
|
|
|
|
|
- # 如果找到非MP4视频文件,尝试转换为MP4,失败则转换为WebM
|
|
|
+ # 如果找到非MP4视频文件,转换为MP4
|
|
|
for video_file in video_files:
|
|
|
output_mp4 = video_file.rsplit('.', 1)[0] + '.mp4'
|
|
|
- output_webm = video_file.rsplit('.', 1)[0] + '.webm'
|
|
|
try:
|
|
|
import subprocess
|
|
|
|
|
|
- # 使用ffmpeg转换为浏览器兼容的MP4格式(简化参数)
|
|
|
+ # 使用ffmpeg转换为MP4
|
|
|
cmd = [
|
|
|
'ffmpeg', '-i', video_file,
|
|
|
- '-c:v', 'libx264', # H.264编码器
|
|
|
- '-preset', 'ultrafast', # 最快编码
|
|
|
- '-crf', '28', # 稍低质量但更兼容
|
|
|
- '-pix_fmt', 'yuv420p', # 兼容性像素格式
|
|
|
+ '-c:v', 'libx264',
|
|
|
+ '-preset', 'ultrafast',
|
|
|
+ '-crf', '28',
|
|
|
+ '-pix_fmt', 'yuv420p',
|
|
|
'-y', output_mp4
|
|
|
]
|
|
|
|
|
|
@@ -394,143 +378,27 @@ def yolov12_predict(params: PredictParams):
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
|
|
|
|
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
|
|
|
- ]
|
|
|
-
|
|
|
- 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编码,尝试转换为WebM")
|
|
|
- # 尝试转换为WebM
|
|
|
- webm_cmd = [
|
|
|
- 'ffmpeg', '-i', video_file,
|
|
|
- '-c:v', 'libvpx',
|
|
|
- '-crf', '30',
|
|
|
- '-b:v', '0',
|
|
|
- '-y', output_webm
|
|
|
- ]
|
|
|
- webm_result = subprocess.run(webm_cmd, capture_output=True, text=True)
|
|
|
- if webm_result.returncode == 0:
|
|
|
- os.remove(video_file)
|
|
|
- logging.info(f"✓ 成功转换为WebM: {output_webm}")
|
|
|
- else:
|
|
|
- logging.error(f"WebM转换也失败: {webm_result.stderr}")
|
|
|
+ os.remove(video_file)
|
|
|
+ logging.info(f"✓ 成功转换为MP4: {output_mp4}")
|
|
|
else:
|
|
|
- logging.error(f"MP4转换失败,尝试转换为WebM: {result.stderr}")
|
|
|
- # 尝试转换为WebM
|
|
|
- webm_cmd = [
|
|
|
- 'ffmpeg', '-i', video_file,
|
|
|
- '-c:v', 'libvpx',
|
|
|
- '-crf', '30',
|
|
|
- '-b:v', '0',
|
|
|
- '-y', output_webm
|
|
|
- ]
|
|
|
- webm_result = subprocess.run(webm_cmd, capture_output=True, text=True)
|
|
|
- if webm_result.returncode == 0:
|
|
|
- os.remove(video_file)
|
|
|
- logging.info(f"✓ 成功转换为WebM: {output_webm}")
|
|
|
- else:
|
|
|
- logging.error(f"WebM转换也失败: {webm_result.stderr}")
|
|
|
+ logging.error(f"ffmpeg转换失败: {result.stderr}")
|
|
|
|
|
|
- # 如果ffmpeg失败,尝试使用OpenCV作为备选方案
|
|
|
- logging.info("尝试使用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编码器
|
|
|
- fourcc = cv2.VideoWriter_fourcc(*'H264')
|
|
|
- out = cv2.VideoWriter(output_mp4, fourcc, fps, (width, height))
|
|
|
-
|
|
|
- if 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 H264编码器生成MP4: {output_mp4}")
|
|
|
- else:
|
|
|
- logging.error("OpenCV H264编码器也无法使用")
|
|
|
-
|
|
|
- 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))
|
|
|
-
|
|
|
- # 强制使用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():
|
|
|
- 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}")
|
|
|
+ # 如果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编码器
|
|
|
+ fourcc = cv2.VideoWriter_fourcc(*'H264')
|
|
|
+ out = cv2.VideoWriter(output_mp4, fourcc, fps, (width, height))
|
|
|
|
|
|
- if out and out.isOpened():
|
|
|
+ if out.isOpened():
|
|
|
while cap.isOpened():
|
|
|
ret, frame = cap.read()
|
|
|
if not ret:
|
|
|
@@ -540,9 +408,9 @@ def yolov12_predict(params: PredictParams):
|
|
|
cap.release()
|
|
|
out.release()
|
|
|
os.remove(video_file)
|
|
|
- logging.info(f"使用OpenCV生成MP4: {output_mp4}")
|
|
|
+ logging.info(f"使用OpenCV H264编码器生成MP4: {output_mp4}")
|
|
|
else:
|
|
|
- logging.error("所有编码器都无法使用")
|
|
|
+ logging.error("OpenCV H264编码器不可用")
|
|
|
|
|
|
except Exception as cv_error:
|
|
|
logging.error(f"OpenCV处理失败: {cv_error}")
|