Automatic Speech Recognition
NeMo
Thai
English
speech
streaming
Thai
FastConformer
Transducer
NeMo
Nemotron
Instructions to use iapp/OpenThai2.0-ASR-Streaming with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use iapp/OpenThai2.0-ASR-Streaming with NeMo:
import nemo.collections.asr as nemo_asr asr_model = nemo_asr.models.ASRModel.from_pretrained("iapp/OpenThai2.0-ASR-Streaming") transcriptions = asr_model.transcribe(["file.wav"]) - Notebooks
- Google Colab
- Kaggle
|
Download serve/README.md from iapp/OpenThai2.0-ASR-Streaming: direct link, hf CLI and curl.
- Browser
- Download file 4.38 kB
-
https://huggingface.co/iapp/OpenThai2.0-ASR-Streaming/resolve/main/serve/README.md
- Command line
-
hf download hf://iapp/OpenThai2.0-ASR-Streaming/serve/README.md
-
curl -L -o README.md https://huggingface.co/iapp/OpenThai2.0-ASR-Streaming/resolve/main/serve/README.md
4.38 kB
| # OpenThai2.0 ASR Streaming service: reference | |
| Install, start and example calls: see the main [README](../README.md). | |
| ## Endpoints | |
| | endpoint | what it does | | |
| |---|---| | |
| | `POST /v1/transcribe` | multipart `file` + the fields below → JSON | | |
| | `WS /v1/live` | a live stream of any length: JSON config → PCM16 LE 16 kHz mono frames → text `end`. Replies `partial` (the sentence so far) and one `final` each time the speaker pauses, then `done` | | |
| | `WS /v1/stream` | one utterance: JSON config → frames → `end`; replies `partial`… then one `final` | | |
| | `GET /v1/health` | loaded model and settings | | |
| | field | values | default | | |
| |---|---|---| | |
| | `mode` | `standard` · `conversation` · `meeting` | `standard` | | |
| | `lang` | `th-TH` · `th-mix` | `th-TH` | | |
| | `latency_ms` | 80 · 320 · 560 · 1120 | 560 | | |
| | `diarize` | `true` · `false` | on for `meeting` | | |
| | `split` (files) | `auto` · `on` · `off` | `auto`: cut files longer than 30 s at pauses | | |
| | `end_silence_ms` (`/v1/live`) | 300–3000 | 700 | | |
| **Response fields:** | |
| - `text` (raw, as scored) and `display_text` (for display). | |
| - `duration_s`, `lang`, `latency_ms`, `mode`, `policy`, `delta`, `model`, `processing_s`. | |
| - A file cut at pauses also has `segments` `[{start, end, text}]`, one per piece. | |
| - With speaker labels, also `segments` `[{speaker, start, end, text}]` and `speakers`. | |
| **Errors:** 400 empty file · 415 unreadable audio · 422 bad option. | |
| ## What each mode does | |
| The blank bias δ controls how readily the model writes something: the more negative it is, the fewer words get dropped. | |
| | mode | decode | | |
| |---|---| | |
| | `standard` | δ −1.0; clips under 2 s re-decoded at −2.5; empty output re-decoded at −4.0 | | |
| | `conversation` | δ −2.0; empty output re-decoded at −4.0 | | |
| | `meeting` | δ −1.0 + speaker labels from `nvidia/Nemotron-3-Diarization` (downloaded on first use) | | |
| ## Environment variables | |
| | var | default | meaning | | |
| |---|---|---| | |
| | `CHINDA_DEVICE` | `cpu` | `cuda` for GPU | | |
| | `CHINDA_MODEL` | `../openthai2.0-asr-streaming_raw.nemo` | must be the raw file; `*_bias-*` files are refused (the bias would apply twice) | | |
| | `CHINDA_PRELOAD` | unset | `1` = load at start-up; otherwise the first request waits about 20 s | | |
| | `CHINDA_REPLICAS` | `1` | model copies, about 2.6 GB each; each copy runs one decode step at a time | | |
| | `CHINDA_NUM_THREADS` | min(16, CPUs); 1 on macOS | CPU threads. On Apple silicon each extra thread makes decoding slower, so macOS uses 1 | | |
| | `CHINDA_DIAR_MODEL` | download | path to a local `Nemotron-3-Diarization.nemo` | | |
| | `CHINDA_CUDA_GRAPHS` | `0` | leave at 0: `1` crashes on the request after speaker labels | | |
| | `CHINDA_SPLIT_FROM_S` | `30` | `split=auto` cuts files longer than this many seconds | | |
| ## Long audio | |
| Do not decode a long recording as one stream. After a pause of near-silence this model drops some of the speech that follows: TVSpeech's videos, rebuilt by joining their clips with one second of silence, score 23.5% character errors as one stream and 12.7% cut at pauses (12.4% clip by clip). So: | |
| - `POST /v1/transcribe` cuts any file longer than 30 s where nobody speaks for 0.7 s, and decodes the pieces on their own (`split=auto`). Speaker labels (`mode=meeting`) still decode one stream. | |
| - `WS /v1/live` ends an utterance at each pause and starts the next one fresh, like iApp's hosted OpenThai ASR Realtime. | |
| - `WS /v1/stream` decodes everything you send as one utterance; keep it for short commands and single sentences. | |
| - In Python: `chinda_realtime.transcribe_long(asr, audio)` for recordings, `chinda_realtime.RealtimeSession` for live audio. | |
| The pause detector is an energy rule (`chinda_realtime.Endpointer`): a 20 ms frame is speech when it is louder than both the loudest recent level − 30 dB and the quietest recent level + 8 dB. Stretches with no speech are skipped. | |
| ## Good to know | |
| - No authentication or rate limiting. | |
| - With `diarize` on `/v1/stream`, speaker labels arrive with the `final` message only; `/v1/live` has no speaker labels. Speakers are anonymous (`speaker_0`, …). | |
| - Live text equals decoding the finished utterance on its own. Batch decoding (the benchmark) can differ by the last word on clips under 2 s. | |
| - With `ffmpeg` on the PATH, the API also accepts mp3, m4a and ogg. | |
| - The decode loop is adapted from NVIDIA NeMo's `speech_to_text_cache_aware_streaming_infer.py` (Apache-2.0). | |