doum
2 天以前 ce44d803b73a65b2cc31db5bcc662139029463d3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# -*- 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