Spaces:
Running
Running
File size: 2,199 Bytes
af32e72 | 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 68 69 70 71 72 | from __future__ import annotations
import subprocess
import threading
from pathlib import Path
from .startup import get_ffmpeg_path
def _transcode_file(src: Path, tmp_suffix: str = ".trans.mp4") -> bool:
"""Transcode `src` to H.264 mp4 using ffmpeg in-place (via temp file).
Returns True if replaced successfully.
"""
ffmpeg = get_ffmpeg_path()
if not ffmpeg:
return False
tmp = src.with_suffix(src.suffix + tmp_suffix)
cmd = [
ffmpeg, "-y", "-i", str(src),
"-c:v", "libx264", "-preset", "veryfast", "-crf", "23",
"-pix_fmt", "yuv420p", "-movflags", "+faststart", str(tmp),
]
try:
ret = subprocess.run(cmd, capture_output=True, check=False)
if ret.returncode != 0 or not tmp.exists() or tmp.stat().st_size == 0:
try:
tmp.unlink(missing_ok=True)
except Exception:
pass
return False
# replace original
tmp.replace(src)
return True
except Exception:
try:
tmp.unlink(missing_ok=True)
except Exception:
pass
return False
def transcode_clips_in_dir(dirpath: Path) -> int:
"""Transcode matching files under `dirpath`. Returns count replaced."""
replaced = 0
if not get_ffmpeg_path():
return 0
for p in dirpath.rglob("*.mp4"):
# skip files that are already small or likely h264? We transcode anyway.
try:
if p.stat().st_size == 0:
continue
ok = _transcode_file(p)
if ok:
replaced += 1
except Exception:
continue
return replaced
def transcode_clips_async(base_dir: Path) -> threading.Thread:
"""Start background thread to transcode clips under `base_dir` and return the Thread."""
def _worker():
try:
count = transcode_clips_in_dir(base_dir)
if count:
print(f"[transcode] replaced {count} clip(s) with H.264-encoded MP4s")
except Exception as exc:
print(f"[transcode] error: {exc}")
t = threading.Thread(target=_worker, daemon=True)
t.start()
return t
|