doum
3 天以前 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
55
56
57
58
59
60
61
62
63
64
65
66
67
# -*- coding: utf-8 -*-
import json
import logging
import os
import shutil
import subprocess
import tempfile
from contextlib import contextmanager
from typing import Optional
 
import httpx
 
logger = logging.getLogger(__name__)
 
 
def get_ffmpeg_cmd(name: str = "ffmpeg") -> str:
    ffmpeg_dir = "D:/code/ffmpeg/"
#     ffmpeg_dir = os.environ.get("FFMPEG_DIR", "")
    print(f"ffmpeg_dir:{ffmpeg_dir}")
    if ffmpeg_dir:
        exe = "ffmpeg.exe" if os.name == "nt" else "ffmpeg"
        print(f"exe:{exe}")
        if name == "ffprobe":
            exe = "ffprobe.exe" if os.name == "nt" else "ffprobe"
        return os.path.join(ffmpeg_dir, exe)
    return name
 
 
def probe_duration(video_path: str) -> float:
    cmd = [
        get_ffmpeg_cmd("ffprobe"),
        "-v", "error",
        "-show_entries", "format=duration",
        "-of", "default=noprint_wrappers=1:nokey=1",
        video_path,
    ]
    try:
        out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True).strip()
        return float(out) if out else 0.0
    except Exception as e:
        logger.warning("ffprobe 失败: %s", e)
        return 0.0
 
 
def download_video(url: str, dest_path: str, timeout: float = 600.0) -> None:
    with httpx.stream("GET", url, timeout=timeout, follow_redirects=True) as resp:
        resp.raise_for_status()
        with open(dest_path, "wb") as f:
            for chunk in resp.iter_bytes(chunk_size=65536):
                f.write(chunk)
 
 
@contextmanager
def temp_video(video_url: Optional[str], duration_hint: float = 0.0):
    tmp_dir = tempfile.mkdtemp(prefix="snap_infer_")
    video_path = os.path.join(tmp_dir, "video.mp4")
    try:
        if video_url:
            download_video(video_url, video_path)
        else:
            raise ValueError("video_url 不能为空")
        duration = probe_duration(video_path)
        if duration <= 0:
            duration = duration_hint if duration_hint > 0 else 1200.0
        yield video_path, duration
    finally:
        shutil.rmtree(tmp_dir, ignore_errors=True)