File size: 3,459 Bytes
866375a
 
 
 
 
 
f7ecc76
866375a
 
f7ecc76
 
866375a
 
 
f7ecc76
866375a
f7ecc76
866375a
f7ecc76
866375a
 
 
 
f7ecc76
866375a
 
 
 
 
add0255
 
866375a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
add0255
866375a
 
 
 
 
 
5469832
add0255
866375a
 
 
 
 
 
 
8656a89
add0255
5469832
866375a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5469832
f7ecc76
866375a
f7ecc76
866375a
 
 
 
 
 
 
 
f7ecc76
 
866375a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python3
# ------------------------------------------------------------
# Whisper Small LS-100 Demo (local or Hugging Face Spaces)
# Author: Murali Chandran (codeninja3d)
# ------------------------------------------------------------

import torch
import torchaudio
import gradio as gr
from transformers import WhisperProcessor, WhisperForConditionalGeneration

# -------------------------------
# Config
# -------------------------------
MODEL_ID = "codeninja3d/whisper-small-ls100"
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"

# print(f"βœ… Loading model from: {MODEL_ID}")
processor = WhisperProcessor.from_pretrained(MODEL_ID)
model = WhisperForConditionalGeneration.from_pretrained(MODEL_ID).to(DEVICE).eval()
# print(f"βœ… #Params: {sum(p.numel() for p in model.parameters()) / 1e6:.2f}M")
# print("βœ… Sample rate:", processor.feature_extractor.sampling_rate)


# -------------------------------
# Transcribe function
# -------------------------------
def transcribe(audio, language, task):
    if audio is None:
        return "⚠️ Please record or upload an audio clip."

    # Handle tuple (mic) or file path (upload)
    if isinstance(audio, tuple):
        sr, waveform_np = audio
        waveform = torch.tensor(waveform_np, dtype=torch.float32)
        if waveform.ndim > 1:                     # [samples, channels] β†’ [1, samples]
            waveform = waveform.mean(dim=-1, keepdim=True).T
    else:
        waveform, sr = torchaudio.load(audio)

    # Ensure mono and correct shape [1, samples]
    if waveform.ndim > 1:
        waveform = waveform.mean(dim=0, keepdim=True)

    # Resample to 16 kHz
    if sr != 16000:
        waveform = torchaudio.functional.resample(waveform, sr, 16000)
        sr = 16000

     # βœ… Normalize amplitude to [-1, 1]
    waveform = waveform / waveform.abs().max()

    # βœ… Force 1D numpy array (no 2D padding issues)
    waveform_np = waveform.squeeze().numpy().astype("float32")

    # Preprocess
    inputs = processor.feature_extractor(
        waveform_np,
        sampling_rate=sr,
        return_tensors="pt"
    ).to(DEVICE)


    # print(f"[DEBUG] waveform shape: {waveform.shape}, dtype: {waveform.dtype}, sr={sr}")
    # print(f"[DEBUG] min={waveform.min().item():.3f}, max={waveform.max().item():.3f}, mean={waveform.mean().item():.3f}")

    # Decoder setup
    forced_decoder_ids = processor.get_decoder_prompt_ids(language="en", task="transcribe")

    # print("[DEBUG] forced_decoder_ids:", forced_decoder_ids)


    with torch.no_grad():
        pred_ids = model.generate(
            **inputs,
            forced_decoder_ids=forced_decoder_ids,
            max_new_tokens=256,
            num_beams=5,
            no_repeat_ngram_size=3,
            repetition_penalty=1.2,
            early_stopping=True
        )

    text = processor.tokenizer.batch_decode(pred_ids, skip_special_tokens=True)[0]
    return text.strip()




# -------------------------------
# Gradio Interface
# -------------------------------


iface = gr.Interface(
    fn=transcribe,
    inputs=[
        gr.Audio(type="numpy", label="πŸŽ™οΈ Record or Upload Audio"),
    ],
    outputs=gr.Textbox(label="πŸ“„ Transcription"),
    title="Whisper Small LS-100 (Fine-tuned)",
    description="Upload or record audio to test Murali's fine-tuned Whisper model on LibriSpeech-100.",
    theme="soft",
    allow_flagging="auto"
)

iface.launch(server_name="0.0.0.0", server_port=7860)