import json import os import subprocess import tempfile class MediaHandler: @staticmethod def get_media_duration(media_path: str) -> float: cmd = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", media_path] try: return float(subprocess.run(cmd, capture_output=True, text=True).stdout.strip()) except Exception: return 3600.0 @staticmethod def get_audio_stream_index(media_path: str, language: str) -> str: lang_map = {'english': 'eng', 'french': 'fre', 'fra': 'fre', 'german': 'ger', 'spanish': 'spa', 'italian': 'ita'} target_iso = lang_map.get(language.lower(), 'eng') cmd = ["ffprobe", "-v", "quiet", "-print_format", "json", "-show_streams", "-select_streams", "a", media_path] try: data = json.loads(subprocess.run(cmd, capture_output=True, text=True).stdout) for i, stream in enumerate(data.get('streams', [])): if stream.get('tags', {}).get('language', 'und').lower() == target_iso: return f"0:a:{i}" return "0:a:0" except Exception: return "0:a:0" @staticmethod def get_language_code(language_name: str) -> str: """Maps Bazarr language names to Whisper ISO codes.""" mapping = { 'english': 'en', 'french': 'fr', 'spanish': 'es', 'german': 'de', 'italian': 'it', 'portuguese': 'pt', 'dutch': 'nl', 'russian': 'ru', 'japanese': 'ja', 'chinese': 'zh' } return mapping.get(language_name.lower(), 'en') @staticmethod def extract_audio_chunk(media_path: str, start_sec: int, duration_sec: int, stream_index: str) -> str: fd, tmp_name = tempfile.mkstemp(suffix=".wav") os.close(fd) cmd = [ "ffmpeg", "-y", "-ss", str(start_sec), "-i", media_path, "-map", stream_index, "-t", str(duration_sec), "-ac", "1", "-ar", "16000", "-vn", "-loglevel", "error", tmp_name ] subprocess.run(cmd, check=True) return tmp_name