""" Audio file validation and decoding. """ from __future__ import annotations import logging from pathlib import Path import numpy as np from config.settings import MAX_UPLOAD_SIZE_MB, SUPPORTED_EXTENSIONS logger = logging.getLogger(__name__) # Whisper and the diarization models both expect 16 kHz mono. SAMPLE_RATE = 16000 # --------------------------------------------------------------------------- # Validation # --------------------------------------------------------------------------- def validate_file_extension(filename: str) -> bool: """Check whether the file extension is in the supported set.""" return Path(filename).suffix.lower() in SUPPORTED_EXTENSIONS def validate_file_size(file_size_bytes: int) -> bool: """Return True if file is within the configured upload limit.""" return file_size_bytes <= MAX_UPLOAD_SIZE_MB * 1024 * 1024 # --------------------------------------------------------------------------- # Decoding # --------------------------------------------------------------------------- def load_audio(file_path: Path) -> np.ndarray: """ Decode any supported audio/video file to 16 kHz mono float32 samples. Uses the FFmpeg libraries bundled with faster-whisper (PyAV), so no system FFmpeg install is needed. The result is decoded once and shared by transcription and diarization. """ from faster_whisper import decode_audio try: audio = decode_audio(str(file_path), sampling_rate=SAMPLE_RATE) except Exception as exc: raise ValueError( "This file could not be read as audio. It may be corrupt or in an unsupported format." ) from exc if len(audio) == 0: raise ValueError("This file contains no audio.") logger.info("Decoded %.1f s of audio from %s", len(audio) / SAMPLE_RATE, file_path) return audio