mazesmazes commited on
Commit
eece501
·
verified ·
1 Parent(s): 8c0bdcb

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +76 -106
README.md CHANGED
@@ -27,60 +27,87 @@ library_name: transformers
27
 
28
  # Tiny Audio
29
 
30
- An English speech recognition model that outputs punctuated, capitalized, formatted text. Built with
31
- [Tiny Audio](https://github.com/alexkroman/tiny-audio)—a minimal, hackable ASR framework.
32
 
33
- A frozen Granite Speech encoder is connected to a frozen Qwen3.5-2B decoder through a trained MLP
34
- projector, with LoRA adapters on the decoder. Only ~80M parameters are trained.
 
 
 
 
 
35
 
36
  ## Quick Start
37
 
 
 
 
 
38
  ```python
39
  from transformers import pipeline
40
 
41
  pipe = pipeline(
42
  "automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True
43
  )
44
- result = pipe("audio.wav")
45
- print(result["text"])
46
  # The quarterly revenue grew by 12% according to Dr. Smith.
47
  ```
48
 
49
- ## Usage Examples
50
-
51
- ### Basic Transcription
52
 
53
- ```python
54
- from transformers import pipeline
55
 
56
- pipe = pipeline(
57
- "automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True
58
- )
59
 
60
- # From file
61
- result = pipe("audio.wav")
62
- print(result["text"])
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
- # From URL
65
- result = pipe("https://example.com/audio.mp3")
66
 
67
- # From numpy array (must be 16kHz)
68
- import numpy as np
69
 
70
- audio = np.random.randn(16000).astype(np.float32) # 1 second
71
- result = pipe(audio)
 
 
72
  ```
73
 
74
- ### Batch Processing
 
 
75
 
76
  ```python
77
- files = ["audio1.wav", "audio2.wav", "audio3.wav"]
78
- results = pipe(files, batch_size=4)
79
- for r in results:
 
 
 
 
 
 
 
80
  print(r["text"])
81
  ```
82
 
83
- ### Word-Level Timestamps
84
 
85
  `return_timestamps=True` times every word with
86
  [Qwen3-ForcedAligner-0.6B](https://huggingface.co/Qwen/Qwen3-ForcedAligner-0.6B-hf) and returns them
@@ -96,15 +123,13 @@ for word in result["words"]:
96
  # {'word': 'Hi,', 'start': 0.0, 'end': 0.24}
97
  ```
98
 
99
- ### Speaker Diarization
100
 
101
- `return_speakers=True` labels every word with a speaker (it implies `return_timestamps=True`).
102
- Speakers come from [Nemotron-3-Diarization](https://huggingface.co/nvidia/Nemotron-3-Diarization),
103
- run once over the whole recording, so labels stay consistent across hour-long meetings; it handles
104
- overlapping speech and up to 8 speakers. Each word goes to the speaker most active while it was
105
- spoken.
106
 
107
- Nemotron-3-Diarization is in transformers `main`, not yet a release:
108
 
109
  ```bash
110
  pip install git+https://github.com/huggingface/transformers
@@ -136,73 +161,25 @@ go to the closest kept speaker:
136
  result = pipe("call.wav", return_speakers=True, num_speakers=2)
137
  ```
138
 
139
- If alignment or diarization fails (for example, transformers without Nemotron), the transcript is
140
- still returned and the error is reported under `result["timestamp_error"]` or
141
- `result["diarization_error"]`.
142
 
143
- ### GPU Inference
144
 
145
- ```python
146
- import torch
147
-
148
- pipe = pipeline(
149
- "automatic-speech-recognition",
150
- model="mazesmazes/tiny-audio",
151
- trust_remote_code=True,
152
- device="cuda",
153
- torch_dtype=torch.bfloat16,
154
- )
155
- ```
156
-
157
- ## Benchmarks
158
-
159
- Word error rate (%, lower is better) on 1,000 samples per dataset, scored with the
160
- [Tiny Audio eval harness](https://github.com/alexkroman/tiny-audio/tree/main/scripts/eval)
161
- (`ta eval`) after text normalization.
162
-
163
- | Dataset | WER |
164
- | ---------------------- | -------: |
165
- | LibriSpeech test-clean | 1.80 |
166
- | SPGISpeech | 2.24 |
167
- | LibriSpeech test-other | 3.09 |
168
- | TED-LIUM | 3.74 |
169
- | LoquaciousSet † | 6.10 |
170
- | Common Voice | 6.62 |
171
- | VoxPopuli | 6.96 |
172
- | AMI (IHM) | 8.88 |
173
- | GigaSpeech | 9.07 |
174
- | Earnings22 † | 10.54 |
175
- | People's Speech | 17.69 |
176
- | AMI (SDM) | 23.59 |
177
- | **Mean (12 sets)** | **8.36** |
178
-
179
- † Held out: no data from this source was used in training.
180
 
181
- ## Architecture
182
-
183
- ```text
184
- Audio (16kHz) → Granite Speech encoder (frozen) → MLP projector (trained)
185
- → Qwen3.5-2B + LoRA (trained adapters) → Text
186
  ```
187
 
188
- | Component | Model | Parameters | Status |
189
- | -------------- | ------------------------------------------------------------------------------------------------------- | ---------- | ------- |
190
- | Audio Encoder | [granite-speech-5.0-470m-turboctc](https://huggingface.co/ibm-granite/granite-speech-5.0-470m-turboctc) | ~470M | Frozen |
191
- | Projector | 2-layer MLP (hidden 4096) | 12.6M | Trained |
192
- | Language Model | [Qwen3.5-2B](https://huggingface.co/Qwen/Qwen3.5-2B) | ~2B | Frozen |
193
- | LoRA adapters | r=64, alpha=64, all linear layers | 67.3M | Trained |
194
-
195
- ### How It Works
196
-
197
- 1. **Audio encoder**: Granite Speech turns 16kHz audio into frame-level embeddings.
198
- 1. **Projector**: A 2-layer MLP maps those embeddings into the decoder's embedding space. Each
199
- projected frame replaces an `<audio>` placeholder token in the prompt.
200
- 1. **Language model**: Qwen3.5-2B, adapted with LoRA, generates the transcript conditioned on the
201
- projected audio and the prompt *"Transcribe the speech with proper punctuation and
202
- capitalization"*.
203
-
204
- At inference, 0.25s of silence is prepended to each clip (`inference_lead_in_seconds`). This keeps
205
- the first word from being dropped on clips that start mid-speech.
206
 
207
  ## Model Specifications
208
 
@@ -210,7 +187,7 @@ the first word from being dropped on clips that start mid-speech.
210
  | ---------------- | ------------------------------------------------------------------ |
211
  | Input | Audio (16kHz mono) |
212
  | Output | Punctuated, capitalized text with formatted numbers |
213
- | Max Audio Length | ~30 seconds per call |
214
  | Vocabulary | Qwen3.5 tokenizer |
215
  | Languages | English only |
216
  | Generation | Greedy decoding (num_beams=1, do_sample=False), max 256 new tokens |
@@ -239,7 +216,7 @@ The training recipe is
239
  `return_speakers=True`, which transcribe in 8-18 s chunks automatically.
240
  - **Speaker diarization**: At most 8 speakers per recording. The count is detected automatically;
241
  `num_speakers` and `max_speakers` can cap it, but `min_speakers` is not supported (passing it
242
- raises a `ValueError`). Needs transformers `main` until a release includes Nemotron-3-Diarization.
243
  - **Accuracy**: May degrade on:
244
  - Far-field and overlapping speech (see AMI SDM)
245
  - Noisy or low-quality audio
@@ -284,13 +261,6 @@ If you use this model, please cite:
284
  }
285
  ```
286
 
287
- ## Links
288
-
289
- - [GitHub Repository](https://github.com/alexkroman/tiny-audio) - Train your own model
290
- - [Free 3.5-hour Course](https://github.com/alexkroman/tiny-audio/blob/main/docs/course/0-course-overview.md)
291
- \- Learn ASR from scratch
292
- - [Live Demo](https://huggingface.co/spaces/mazesmazes/tiny-audio) - Try it in your browser
293
-
294
  ## Acknowledgments
295
 
296
  - [Granite Speech](https://huggingface.co/ibm-granite/granite-speech-5.0-470m-turboctc) for the
 
27
 
28
  # Tiny Audio
29
 
30
+ **A tiny, hackable, open-source speech LLM.**
 
31
 
32
+ It transcribes English with punctuation, capitalization, word timestamps, and speaker labels: 1.8%
33
+ WER on LibriSpeech test-clean and 8.4% averaged over 12 benchmarks. Built and trained with
34
+ [Tiny Audio](https://github.com/alexkroman/tiny-audio).
35
+
36
+ **[Try the live demo](https://huggingface.co/spaces/mazesmazes/tiny-audio)** ·
37
+ **[Train your own](https://github.com/alexkroman/tiny-audio)** ·
38
+ **[Free 3.5-hour course](https://github.com/alexkroman/tiny-audio/blob/main/docs/course/0-course-overview.md)**
39
 
40
  ## Quick Start
41
 
42
+ ```bash
43
+ pip install "transformers>=5.0" peft torch torchaudio librosa
44
+ ```
45
+
46
  ```python
47
  from transformers import pipeline
48
 
49
  pipe = pipeline(
50
  "automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True
51
  )
52
+ print(pipe("audio.wav")["text"])
 
53
  # The quarterly revenue grew by 12% according to Dr. Smith.
54
  ```
55
 
56
+ The input can be a file path, a URL, or a 16 kHz float32 numpy array. No post-processing is needed:
57
+ the model writes punctuation, capitalization, and numbers itself.
 
58
 
59
+ ## Benchmarks
 
60
 
61
+ Word error rate (%, lower is better) on 1,000 samples per dataset, scored with the
62
+ [Tiny Audio eval harness](https://github.com/alexkroman/tiny-audio/tree/main/scripts/eval)
63
+ (`ta eval`) after text normalization.
64
 
65
+ | Dataset | WER |
66
+ | ---------------------- | -------: |
67
+ | LibriSpeech test-clean | 1.80 |
68
+ | SPGISpeech | 2.24 |
69
+ | LibriSpeech test-other | 3.09 |
70
+ | TED-LIUM | 3.74 |
71
+ | LoquaciousSet † | 6.10 |
72
+ | Common Voice | 6.62 |
73
+ | VoxPopuli | 6.96 |
74
+ | AMI (IHM) | 8.88 |
75
+ | GigaSpeech | 9.07 |
76
+ | Earnings22 † | 10.54 |
77
+ | People's Speech | 17.69 |
78
+ | AMI (SDM) | 23.59 |
79
+ | **Mean (12 sets)** | **8.36** |
80
 
81
+ † Held out: no data from this source was used in training.
 
82
 
83
+ To reproduce a row, or score AssemblyAI, Deepgram, ElevenLabs, or Apple's on-device recognizer on
84
+ the same samples:
85
 
86
+ ```bash
87
+ git clone https://github.com/alexkroman/tiny-audio.git && cd tiny-audio && poetry install
88
+ poetry run ta eval -m mazesmazes/tiny-audio -d loquacious -n 100
89
+ ASSEMBLYAI_API_KEY=... poetry run ta eval -m assemblyai -d loquacious -n 100
90
  ```
91
 
92
+ ## More Than Plain Text
93
+
94
+ ### Batches and GPU
95
 
96
  ```python
97
+ import torch
98
+
99
+ pipe = pipeline(
100
+ "automatic-speech-recognition",
101
+ model="mazesmazes/tiny-audio",
102
+ trust_remote_code=True,
103
+ device="cuda",
104
+ torch_dtype=torch.bfloat16,
105
+ )
106
+ for r in pipe(["audio1.wav", "audio2.wav", "audio3.wav"], batch_size=4):
107
  print(r["text"])
108
  ```
109
 
110
+ ### Word-level timestamps
111
 
112
  `return_timestamps=True` times every word with
113
  [Qwen3-ForcedAligner-0.6B](https://huggingface.co/Qwen/Qwen3-ForcedAligner-0.6B-hf) and returns them
 
123
  # {'word': 'Hi,', 'start': 0.0, 'end': 0.24}
124
  ```
125
 
126
+ ### Speaker diarization
127
 
128
+ Pass `return_speakers=True` to label every word with who said it. It also turns on word timestamps.
129
+ It works on recordings of any length, keeps speaker labels consistent across hour-long meetings, and
130
+ handles overlapping speech and up to 8 speakers.
 
 
131
 
132
+ Diarization needs transformers installed from `main` until the next release:
133
 
134
  ```bash
135
  pip install git+https://github.com/huggingface/transformers
 
161
  result = pipe("call.wav", return_speakers=True, num_speakers=2)
162
  ```
163
 
164
+ If alignment or diarization fails (for example, on a transformers release without diarization
165
+ support), the transcript is still returned and the error is reported under
166
+ `result["timestamp_error"]` or `result["diarization_error"]`.
167
 
168
+ ## Train Your Own
169
 
170
+ Everything that produced this model is open: the code, the data mix, and the recipe. Swap the
171
+ encoder, the LLM, or the projector from config and train on your own data. A smoke test runs on a
172
+ laptop in about five minutes:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
+ ```bash
175
+ git clone https://github.com/alexkroman/tiny-audio.git && cd tiny-audio && poetry install
176
+ poetry run python scripts/train.py +experiments=mps_smoke
 
 
177
  ```
178
 
179
+ The
180
+ [free course](https://github.com/alexkroman/tiny-audio/blob/main/docs/course/0-course-overview.md)
181
+ walks through how the pieces fit, training a model, evaluating it, and publishing it with a demo
182
+ like [this one](https://huggingface.co/spaces/mazesmazes/tiny-audio).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  ## Model Specifications
185
 
 
187
  | ---------------- | ------------------------------------------------------------------ |
188
  | Input | Audio (16kHz mono) |
189
  | Output | Punctuated, capitalized text with formatted numbers |
190
+ | Max Audio Length | ~19 s per plain call; any length with timestamps or speakers |
191
  | Vocabulary | Qwen3.5 tokenizer |
192
  | Languages | English only |
193
  | Generation | Greedy decoding (num_beams=1, do_sample=False), max 256 new tokens |
 
216
  `return_speakers=True`, which transcribe in 8-18 s chunks automatically.
217
  - **Speaker diarization**: At most 8 speakers per recording. The count is detected automatically;
218
  `num_speakers` and `max_speakers` can cap it, but `min_speakers` is not supported (passing it
219
+ raises a `ValueError`). Needs transformers `main` until the next release.
220
  - **Accuracy**: May degrade on:
221
  - Far-field and overlapping speech (see AMI SDM)
222
  - Noisy or low-quality audio
 
261
  }
262
  ```
263
 
 
 
 
 
 
 
 
264
  ## Acknowledgments
265
 
266
  - [Granite Speech](https://huggingface.co/ibm-granite/granite-speech-5.0-470m-turboctc) for the