npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tilawi/quran-asr

v0.1.0

Published

On-device Quran recitation recognition core: CTC decoding, verse identification and a conservative trust gate. Runtime-agnostic (inject your ONNX runner).

Readme

@tilawi/quran-asr

On-device Quran recitation recognition: turn a recitation into the verse(s) being recited, privately, with no server.

This is the recognition core behind the Tilawi app. It takes the output of a CTC speech model, decodes it, identifies the recited verse or verse span, and applies a conservative trust gate. When the gate isn't confident, it returns "no match" instead of guessing, because naming the wrong verse is worse than naming none.

  • Runtime-agnostic. You inject a model runner: onnxruntime-react-native in an app, onnxruntime-node on a server or in tests.
  • Pure TypeScript with zero runtime dependencies.
  • Never generates Quran text. The model transcribes the user's recitation, and the core only compares that transcript against the fixed canonical text.

Accuracy

Measured with eval/run-eval.mjs: the real model through this core on 600 verses (200 per reciter, randomly sampled across the whole Quran, seed 1) from EveryAyah.

| Reciter | Correct verse | No match | Wrong verse | |---|---|---|---| | Mohamed Siddiq al-Minshawi (murattal) | 200 / 200 | 0 | 0 | | Mahmoud Khalil al-Husary | 200 / 200 | 0 | 0 | | Mishary Rashid Alafasy | 199 / 200 | 1 | 0 |

"Correct" includes 12 cases where the predicted verse is word-for-word identical to the recited one (e.g. 55:13, which recurs 31 times in Ar-Rahman). Audio alone cannot tell those apart. The one "no match" is a very short verse (104:5) that the trust gate declined to guess.

Caveat: these are clean studio recordings by professional reciters. Recordings from a phone microphone in a real room, and from learners, will score lower. The harness is included so you can measure on your own audio.

Memorization feedback

judgeAttempt was checked against the real transcripts of those 600 recitations (7,551 expected words), comparing to the quran.com (KFGQPC) word text the Tilawi app uses; results in eval/results/memo/memo-eval.json. (That harness lives in the app repo because it reads the app's text database.) Mistakes are planted only in what the reciter "said"; the canonical text is never modified.

| Scenario | Result | |---|---| | Correct recitation | 99.6% of words judged correct; 13 words (0.17%, in 9 verses) wrongly flagged | | A wrong word was said | 91.7% flagged as an error, 97.8% flagged as an error or "uncertain" | | A word was skipped | 99.5% flagged as missed | | An extra word was said | 99.7% reported as extra |

All 13 false flags on correct recitations trace back to the model mishearing or dropping words, not to the judging logic. The same studio-audio caveat applies.

Scoring a passage: judgeAttempt returns two scores. overallPercent is correct ÷ (all expected words + extra words), so stopping early lowers it; show this one for a passage. scorePercent only covers the words the reciter reached, so 1 correct word of a page scores 100. Words after the point where the reciter stopped come back as unattempted (not errors). Words skipped before a recited word come back as omission.

Quick start (Node)

The model and its data files live on Hugging Face: muhdur/tilawi-fastconformer-quran.

git clone https://github.com/Tilawi/quran-asr && cd quran-asr
npm install
npm run build
npm run fetch-assets                          # ~110 MB, verified by SHA-256
node examples/transcribe.mjs recitation.mp3   # needs ffmpeg on PATH
# e.g. with https://everyayah.com/data/Husary_128kbps/112001.mp3:
# heard: قل هو الله احد
# verse: 112:1 (score 1.00)

Usage

import { createAsrSession, type SessionRunner } from '@tilawi/quran-asr';

// 1. A runner wrapping your ONNX runtime. The model takes raw 16 kHz mono PCM
//    (audio_signal float32 [1, N] + length int64 [1]) and returns [1, T, vocab]
//    log-probabilities; feature extraction is inside the graph.
//    eval/node.mjs has a complete onnxruntime-node runner.
const runner: SessionRunner = {
  async run(audio) {
    /* run the model, return { logprobs, timeSteps, vocabSize } */
  },
};

// 2. The text-side assets from Hugging Face: vocab.json, quran_ctc_tokens.json, quran.json.
const session = createAsrSession(runner, { vocab, quranCtcTokens, quran, blankId: 1024 });

// 3. Recognize a clip.
const result = await session.transcribe(pcm16kMono);
// { surah: 2, ayah: 255, ayah_end: null, score: 0.93, transcript: '...' }
// surah/ayah are 0 when nothing was trusted.

Other exports: detectSpeech (reject silence before running the model), judgeAttempt (word-by-word memorization feedback against the fixed canonical text), stitchTranscripts (long clips in overlapping windows).

In React Native / Expo, use @tilawi/react-native-quran-asr, which wraps this package with onnxruntime-react-native and a microphone hook.

Tests

npm run fetch-assets && npm test
  • test/asrGoldens.test.ts: a golden regression suite (real recitations plus synthetic verses, spans, fragments, dropped/substituted tokens, Bismillah openings and noise). The model is replaced by a one-hot runner, so everything after the neural network must produce byte-identical output. Set ASR_GOLDENS=full to run all 640 cases.
  • npm run eval -- --reciter Husary_128kbps --n 200: the end-to-end accuracy harness above (downloads EveryAyah audio; needs ffmpeg).

License

The code is MIT. The model and data on Hugging Face have their own terms: the model is fine-tuned from NVIDIA's stt_ar_fastconformer_hybrid_large_pcd_v1.0 (CC-BY-4.0), and the Quran text is from the Tanzil Project (CC-BY-3.0, verbatim).