"""Tiện ích cho test: tạo video/âm thanh mẫu bằng ffmpeg, đo thời lượng.""" from __future__ import annotations import os import shutil import subprocess FFMPEG = shutil.which("ffmpeg") or "ffmpeg" FFPROBE = shutil.which("ffprobe") or "ffprobe" def make_video(path: str, dur: float = 2.0, size: str = "320x240", rate: int = 15, with_audio: bool = False, color: str = "blue"): os.makedirs(os.path.dirname(path), exist_ok=True) if with_audio: cmd = [FFMPEG, "-y", "-hide_banner", "-loglevel", "error", "-f", "lavfi", "-i", f"testsrc=size={size}:rate={rate}:duration={dur}", "-f", "lavfi", "-i", f"sine=frequency=330:duration={dur}", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-c:a", "aac", "-shortest", path] else: cmd = [FFMPEG, "-y", "-hide_banner", "-loglevel", "error", "-f", "lavfi", "-i", f"color=c={color}:s={size}:rate={rate}:d={dur}", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-an", path] subprocess.run(cmd, check=True, capture_output=True) return path def make_audio(path: str, dur: float = 2.0, freq: int = 440): os.makedirs(os.path.dirname(path), exist_ok=True) subprocess.run([FFMPEG, "-y", "-hide_banner", "-loglevel", "error", "-f", "lavfi", "-i", f"sine=frequency={freq}:duration={dur}", "-c:a", "aac", path], check=True, capture_output=True) return path def duration(path: str) -> float: out = subprocess.run([FFPROBE, "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", path], capture_output=True, text=True).stdout.strip() try: return float(out) except ValueError: return 0.0 def has_audio(path: str) -> bool: out = subprocess.run([FFPROBE, "-v", "error", "-select_streams", "a", "-show_entries", "stream=codec_name", "-of", "csv=p=0", path], capture_output=True, text=True).stdout.strip() return bool(out) def dimensions(path: str) -> tuple[int, int]: """(width, height) của stream video đầu tiên.""" out = subprocess.run([FFPROBE, "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height", "-of", "csv=p=0:s=x", path], capture_output=True, text=True).stdout.strip() try: w, h = out.split("x") return int(w), int(h) except ValueError: return (0, 0) def has_video(path: str) -> bool: out = subprocess.run([FFPROBE, "-v", "error", "-select_streams", "v", "-show_entries", "stream=codec_name", "-of", "csv=p=0", path], capture_output=True, text=True).stdout.strip() return bool(out)