gnumanth/sushrota-sanskrit-asr-onnx · Hugging Face

2 min read Original article ↗

Su-śrotā Sanskrit ASR — ONNX & In-Browser INT8

This repository provides ONNX and INT8 quantized exports of Su-śrotā (v13b), a scholar-grade Sanskrit speech recognition model developed by Prof. Prathosh A P (Indian Institute of Science, Bengaluru).

These models allow running Sanskrit ASR 100% serverless in a web browser (via onnxruntime-web) or locally on Mac/Linux/Windows with zero PyTorch/NeMo dependencies.

Files in this repository

File Size Description
sushrota_sanskrit_ctc_int8.onnx ~178 MB Conformer-CTC model quantized with INT8 MatMul for browser WASM / WebGPU / CoreML execution
preprocessor.onnx ~149 KB Neural Audio-to-Mel-Spectrogram filterbank preprocessor (16 kHz mono PCM $\rightarrow$ 80-mel log spectrogram)
sanskrit_vocab.json ~3 KB Tokenizer dictionary mapping 257 CTC output classes to Sanskrit characters/BPE units

Performance

  • Parameters: ~115M active parameters (Sanskrit slice of IndicConformer)
  • Local Mac CPU Latency: ~0.10s for 3.0s audio (RTF: 0.03, ~30x faster than real-time)
  • In-Browser WebAssembly Latency: ~0.25s for 2.0s audio (RTF: 0.12, ~8x faster than real-time)

Usage

1. In-Browser (JavaScript with onnxruntime-web)

<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.all.min.js"></script>
<script>
  // 1. Load sessions
  const prep = await ort.InferenceSession.create('https://huggingface.co/gnumanth/sushrota-sanskrit-asr-onnx/resolve/main/preprocessor.onnx');
  const asr = await ort.InferenceSession.create('https://huggingface.co/gnumanth/sushrota-sanskrit-asr-onnx/resolve/main/sushrota_sanskrit_ctc_int8.onnx');
  const vocab = await (await fetch('https://huggingface.co/gnumanth/sushrota-sanskrit-asr-onnx/resolve/main/sanskrit_vocab.json')).json();

  // 2. Transcribe Float32Array PCM audio at 16kHz
  const audioTensor = new ort.Tensor('float32', pcmFloat32Array, [1, pcmFloat32Array.length]);
  const lenTensor = new ort.Tensor('int64', BigInt64Array.from([BigInt(pcmFloat32Array.length)]), [1]);
  
  const feats = await prep.run({ audio_signal: audioTensor, length: lenTensor });
  const logits = await asr.run({ audio_signal: feats.features, length: feats.feature_lengths });

  // 3. Greedy CTC Decode
  // (argmax over logits -> collapse duplicate consecutive tokens -> drop blank token 0)
</script>

2. Python (Without NeMo or PyTorch)

pip install onnxruntime soundfile numpy
import onnxruntime as ort, soundfile as sf, numpy as np, json

prep = ort.InferenceSession("preprocessor.onnx")
asr = ort.InferenceSession("sushrota_sanskrit_ctc_int8.onnx")
vocab = json.load(open("sanskrit_vocab.json"))

wav, sr = sf.read("audio.wav", dtype="float32") # must be 16kHz mono
if wav.ndim > 1: wav = wav.mean(axis=1)

feats, flen = prep.run(None, {"audio_signal": wav[np.newaxis, :], "length": np.array([len(wav)], dtype=np.int64)})
logits = asr.run(None, {"audio_signal": feats, "length": flen})[0]

# Greedy decode
pred_ids = np.argmax(logits[0], axis=-1)
out, prev = [], -1
for i in pred_ids:
    if i != prev and i != 0: out.append(vocab[i])
    prev = i
print("Transcript:", "".join(out).replace("▁", " ").strip())

Citation

Prathosh A P, Su-śrotā: Scholar-grade Sanskrit ASR and metre-aware chant practice, Indian Institute of Science, Bengaluru, 2026.