CoolFace
Apppublic

Haseeb949/fluenta-backend

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
ml_utils.py58 linesDownload Raw Back to root
1# ml_utils.py2import os3import numpy as np4from pydub import AudioSegment5import librosa6import soundfile as sf7 8SAMPLE_RATE = 160009 10def to_wav_mono16(in_path, out_path, target_sr=SAMPLE_RATE):11    """Convert to mono WAV 16-bit PCM and resample to SAMPLE_RATE."""12    audio = AudioSegment.from_file(in_path)13    audio = audio.set_frame_rate(target_sr).set_channels(1).set_sample_width(2)14    audio.export(out_path, format="wav")15    return out_path16 17def load_audio_mono(path, sr=SAMPLE_RATE):18    y, sr = librosa.load(path, sr=sr, mono=True)19    return y, sr20 21def trim_silence(y, top_db=30):22    intervals = librosa.effects.split(y, top_db=top_db)23    if len(intervals) == 0:24        return y25    parts = [y[start:end] for start, end in intervals]26    return np.concatenate(parts)27 28def extract_mfcc(y, sr=SAMPLE_RATE, n_mfcc=20, hop_length=512):29    mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=n_mfcc, hop_length=hop_length)30    # shape: (n_mfcc, t). We return mean+std for simple vector input31    feat = np.concatenate([mfcc.mean(axis=1), mfcc.std(axis=1)])32    return feat.astype(np.float32)33 34class ModelWrapper:35    """Replace predict() with your model code. Keep interface same: returns dict."""36    def __init__(self, model_path=None):37        self.model_path = model_path38        # TODO: load Torch/TF/ONNX model here if available39        self.model = None40 41    def predict_from_features(self, features):42        # placeholder: if mean MFCC amplitude > threshold say "Stutter"43        score = float(np.tanh(np.abs(features).mean()) )  # dummy 0..1-ish44        label = "Stutter" if score > 0.4 else "NoStutter"45        events = []  # e.g. [{"t":1.2,"type":"repeat"}]46        return {"label": label, "confidence": score, "events": events}47 48    def predict_from_file(self, audio_path):49        # full pipeline: convert -> load -> trim -> extract -> predict50        tmp = audio_path51        if not audio_path.lower().endswith(".wav"):52            tmp = audio_path + ".wav"53            to_wav_mono16(audio_path, tmp)54        y, sr = load_audio_mono(tmp)55        y = trim_silence(y)56        feats = extract_mfcc(y, sr)57        return self.predict_from_features(feats)58