# -*- coding: utf-8 -*- import logging import subprocess from typing import Optional, Tuple import cv2 import numpy as np from app.video_io import get_ffmpeg_cmd logger = logging.getLogger(__name__) def laplacian_score(image_path: str) -> float: img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: return 0.0 return float(cv2.Laplacian(img, cv2.CV_64F).var()) def refine_time_in_window( video_path: str, center_sec: float, window_sec: float = 2.0, step: float = 0.5, ) -> Tuple[float, float]: """在 [center-window, center+window] 内选清晰度最高帧,返回 (best_sec, score)。""" import os import tempfile best_t = center_sec best_score = 0.0 ffmpeg = get_ffmpeg_cmd("ffmpeg") t = max(0.0, center_sec - window_sec) end = center_sec + window_sec tmp = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) tmp.close() try: while t <= end: cmd = [ ffmpeg, "-y", "-ss", f"{t:.3f}", "-i", video_path, "-frames:v", "1", "-q:v", "2", tmp.name, ] subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if os.path.isfile(tmp.name) and os.path.getsize(tmp.name) > 0: score = laplacian_score(tmp.name) if score > best_score: best_score = score best_t = t t += step finally: if os.path.isfile(tmp.name): os.remove(tmp.name) return round(best_t, 2), best_score