import io import numpy as np import librosa TARGET_SR = 22050 def load_audio_bytes(data: bytes) -> tuple[np.ndarray, int, float]: """Load raw audio bytes → (y, sr, duration_seconds). Resamples to 22050 Hz mono.""" y, sr = librosa.load(io.BytesIO(data), sr=TARGET_SR, mono=True) return y, sr, float(len(y) / sr) def chunk_audio( y: np.ndarray, sr: int, chunk_duration: float = 10.0, overlap: float = 0.5, ) -> list[dict]: """Split audio into overlapping chunks. Returns list of {y, start, end}.""" chunk_samples = int(chunk_duration * sr) hop_samples = int(chunk_samples * (1 - overlap)) if len(y) <= chunk_samples: return [{"y": y, "start": 0.0, "end": float(len(y) / sr)}] chunks = [] for s in range(0, len(y) - chunk_samples + 1, hop_samples): chunks.append({"y": y[s: s + chunk_samples], "start": s / sr, "end": (s + chunk_samples) / sr}) return chunks