Balochi_STT / README.md
Aynkader's picture
Upload 20 files
3bb84f7 verified
|
Raw
History Blame Contribute Delete
4.16 kB
# Balochi STT (Whisper)
Fine-tuned **Whisper-small** speech-to-text model for **Balochi (Latin script)**.
| Item | Value |
| --- | --- |
| Task | Automatic speech recognition (ASR / STT) |
| Language | Balochi (Latin orthography) |
| Base model | Whisper-small |
| Sample rate | 16 kHz, mono |
| Best eval WER | ~4.5% |
| Training data | 5,237 clips (~3 hours) from `wavs/wavs` + `wavs/wavs.txt` |
---
## Folder layout
```text
balochi_whisper/
├── README.md
├── best_model/
│ ├── model/ # Whisper weights + config
│ ├── processor/ # tokenizer + feature extractor
│ └── eval_metrics.txt
└── checkpoints/ # training checkpoints (optional)
```
Use **`best_model/`** for inference.
---
## Requirements
```bash
source ~/venvs/torch/bin/activate
```
Needs: `torch`, `transformers`, `soundfile`, `torchaudio`, `numpy`.
GPU is recommended (tested on NVIDIA RTX 3060).
---
## Quick inference (Python)
```python
from pathlib import Path
import numpy as np
import soundfile as sf
import torch
import torchaudio
from transformers import WhisperForConditionalGeneration, WhisperProcessor
ROOT = Path("balochi_whisper/best_model")
device = "cuda" if torch.cuda.is_available() else "cpu"
processor = WhisperProcessor.from_pretrained(ROOT / "processor")
model = WhisperForConditionalGeneration.from_pretrained(ROOT / "model").to(device)
model.eval()
model.config.forced_decoder_ids = None
model.generation_config.forced_decoder_ids = None
model.generation_config.pad_token_id = processor.tokenizer.pad_token_id
def load_16k(path: str) -> np.ndarray:
wav, sr = sf.read(path, always_2d=False)
if wav.ndim > 1:
wav = wav.mean(axis=1)
wav = np.asarray(wav, dtype=np.float32)
if sr != 16000:
wav = (
torchaudio.functional.resample(
torch.from_numpy(wav).unsqueeze(0), sr, 16000
)
.squeeze(0)
.numpy()
)
return wav
wav = load_16k("your_audio.wav")
inputs = processor(
wav, sampling_rate=16000, return_tensors="pt", return_attention_mask=True
)
with torch.no_grad():
ids = model.generate(
inputs.input_features.to(device),
attention_mask=inputs.attention_mask.to(device),
max_new_tokens=224,
)
text = processor.batch_decode(ids.cpu(), skip_special_tokens=True)[0].strip()
print(text)
```
---
## CLI (from project root)
```bash
cd ~/Balochi_tts
source ~/venvs/torch/bin/activate
python infer_stt.py /path/to/audio.wav
```
Desktop GUI:
```bash
python stt_gui.py
```
---
## Training data format
```text
wavs/wavs/1.wav … N.wav
wavs/wavs.txt # line i → transcript for (i+1).wav
```
Transcripts use Balochi **Latin** script (`á`, `é`, `ó` allowed).
Retrain / resume from project root:
```bash
python train_stt.py
```
Checkpoints are saved under `balochi_whisper/checkpoints/`. The best model (lowest WER) is copied to `balochi_whisper/best_model/`.
---
## Hugging Face
Upload this model:
```bash
# from Balochi_tts project root
bash scripts/push_models_to_hf.sh YOUR_HF_USER
```
That publishes `YOUR_HF_USER/balochi-whisper-stt` with `model/` and `processor/`.
Load from the Hub:
```python
from transformers import WhisperForConditionalGeneration, WhisperProcessor
repo = "YOUR_HF_USER/balochi-whisper-stt"
processor = WhisperProcessor.from_pretrained(repo, subfolder="processor")
model = WhisperForConditionalGeneration.from_pretrained(repo, subfolder="model")
```
If you upload files at the repo root (no subfolders), omit `subfolder=...`.
---
## Notes
- Input audio is converted to **16 kHz mono** before recognition.
- Audio longer than **30 seconds** should be chunked (the project CLI/GUI do this).
- Output is Balochi **Latin** text, not Arabic script.
- Do not force an English language token; Balochi is not a built-in Whisper language.
---
## Files to ship
Minimum files for inference:
```text
best_model/model/config.json
best_model/model/generation_config.json
best_model/model/model.safetensors
best_model/processor/ # full processor directory
```
`checkpoints/` is only needed to resume training.