CPU-friendly, fast language identification for 1,386 African languages
# african-speech-id
CPU-friendly, fast language identification for 1,386 African languages.
The model uses a fast version of Omnilingual ASR to turn speech into text, and a
classification head that reads that text and names the language. Both run on CPU, so a
phone or a laptop is enough.
The inference core is C++ with a C API, so there is no Python on the device.
```sh
pip install african-speech-id
```
**How the model behaves and where it fails** is on the
model card. This file is about using it.
## Results
Evaluated on two held-out sets, against
facebook/mms-lid-4017 on identical clips:
| test set | languages | clips | **this model** | MMS-LID-4017 |
|---|---|---|---|---|
| Waxal | 28 | 1,675 | **0.610** | 0.604 |
| omniASR corpus (test) | 76 | 4,557 | **0.429** | 0.270 |
| **combined** | **104** | **6,232** | **0.478** | **0.360** |
Per language the model is ahead on 57, behind on 38, and tied on 9.
The gap is widest on the long tail. MMS-LID covers 4,017 languages and is strong on
well-resourced ones; this model is built for the languages underneath that, which is where
the omniASR test set sits.
## Quick start
The head classifies text and cannot read audio, so it needs a recogniser in front of it:
```python
import soundfile as sf
import sherpa_onnx
from african_speech_id import AfricanSpeechId
model, tokens = AfricanSpeechId.download_recogniser() # omniASR, once
rec = sherpa_onnx.OfflineRecognizer.from_omnilingual_asr_ctc(model=model, tokens=tokens)
lid = AfricanSpeechId.load()
wav, sr = sf.read("clip.wav", dtype="float32")
s = rec.create_stream()
s.accept_waveform(sr, wav)
rec.decode_stream(s)
print(lid.classify(s.result.text)) # ewe (0.03)
```
`classify()` returns `None` when no n-gram matched, meaning there was no basis for a
decision. Report that as unknown rather than naming whichever language scored least badly.
Labels are ISO 639-3 codes (`ewe`, `hau`, `fat`) where the source corpus carried one, and
language names otherwise. …