Automatic Speech Recognition
LiteRT-LM
LiteRT
Chinese
English
Japanese
litertlm
on-device
edge
asr
speech-recognition
streaming
audio
qwen3-asr
Instructions to use mlboydaisuke/Confucius4-R2T2-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT-LM
How to use mlboydaisuke/Confucius4-R2T2-LiteRT with LiteRT-LM:
# LiteRT-LM runs on various platforms (Android, iOS, Windows, Linux, macOS, IoT, Web/WASM) # and supports many APIs (C++, Python, Kotlin, Swift, JavaScript, Flutter). # For platform-specific integration guides, please refer to the official developer website: # https://ai.google.dev/edge/litert-lm # To try LiteRT-LM, the easiest way is to use our CLI tool. # 1. Install the LiteRT-LM CLI tool: pip install -U litert-lm # 2. Download and run this model locally: # See: https://ai.google.dev/edge/litert-lm/cli # A single .litertlm file in the repo is picked automatically; otherwise the CLI asks which one to run # (or pass its name right after the repo id). litert-lm run \ --from-huggingface-repo=mlboydaisuke/Confucius4-R2T2-LiteRT \ --prompt="Write me a poem"
- LiteRT
How to use mlboydaisuke/Confucius4-R2T2-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
android/: the Android sample app (model picker, hold to talk, three clips, device check); card: the Sample app line with the Galaxy S26 numbers
5d22c56 verified |
Download android/README.md from mlboydaisuke/Confucius4-R2T2-LiteRT: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/mlboydaisuke/Confucius4-R2T2-LiteRT/resolve/main/android/README.md
- Command line
-
hf download hf://mlboydaisuke/Confucius4-R2T2-LiteRT/android/README.md
-
curl -L -o README.md https://huggingface.co/mlboydaisuke/Confucius4-R2T2-LiteRT/resolve/main/android/README.md
12.1 kB
| # ASR LiteRT-LM — speech to text on Android with three LiteRT-LM bundles | |
| Hold the button, speak for up to 30 s, and the app writes what you said. On the CPU of a Galaxy S26 | |
| (4 threads, measured 2026-10-09), Qwen3-ASR-1.7B turned a 6.4 s English clip into text in 2.49 s and | |
| Fun-ASR-Nano-2512 in 1.19 s. The app runs three speech recognition models in the LiteRT-LM `.litertlm` | |
| format through one code path: pick a model, then talk or play one of three bundled clips. Everything | |
| runs on the phone; the app asks for the microphone and nothing else (no network permission). | |
| ## Models | |
| | Model | Hugging Face | File | Size | License | Languages | | |
| |---|---|---|---|---|---| | |
| | Qwen3-ASR-1.7B | [litert-community/Qwen3-ASR-1.7B](https://huggingface.co/litert-community/Qwen3-ASR-1.7B) | `Qwen3-ASR-1.7B.litertlm` | 2,693,064,192 B | Apache-2.0 | 30 languages (the card scores English, Mandarin, Japanese) | | |
| | Fun-ASR-Nano-2512 | [litert-community/Fun-ASR-Nano-2512](https://huggingface.co/litert-community/Fun-ASR-Nano-2512) | `Fun-ASR-Nano-2512.litertlm` | 1,255,894,736 B | Apache-2.0 | Chinese, English, Japanese | | |
| | Confucius4-R2T2 | [mlboydaisuke/Confucius4-R2T2-LiteRT](https://huggingface.co/mlboydaisuke/Confucius4-R2T2-LiteRT) | `Confucius4-R2T2.litertlm` | 2,693,064,192 B | [NetEase Youdao Model Use License Agreement](https://huggingface.co/mlboydaisuke/Confucius4-R2T2-LiteRT/blob/main/MODEL_LICENSE) | Chinese, English; a fine-tune of Qwen3-ASR-1.7B | | |
| Each file holds the audio encoder, the language model, the tokenizer and the prompt template. Read | |
| the Confucius4-R2T2 agreement before you use that file: it has user-count and revenue thresholds | |
| (clause 2.2) and limits on using the model to improve other models (clause 3.4). | |
| ## Run it in 5 lines | |
| From this directory, with the phone connected over adb: | |
| ```bash | |
| hf download litert-community/Qwen3-ASR-1.7B Qwen3-ASR-1.7B.litertlm --local-dir bundles | |
| hf download litert-community/Fun-ASR-Nano-2512 Fun-ASR-Nano-2512.litertlm --local-dir bundles | |
| hf download mlboydaisuke/Confucius4-R2T2-LiteRT Confucius4-R2T2.litertlm --local-dir bundles | |
| ./gradlew :app:installDebug && adb shell am start -n com.asrlitertlm/.MainActivity | |
| adb push bundles/*.litertlm /sdcard/Android/data/com.asrlitertlm/files/ | |
| ``` | |
| Reopen the app, tap a model in the picker and hold **Hold to talk**. The first launch creates the | |
| folder the push writes to. One bundle is enough; the picker marks the others `missing`. | |
| - Storage: the three files take 6.6 GB. The first load of each file writes a runtime cache into the | |
| app's cache directory: 3.0 GB for each Qwen3-ASR file, 1.5 GB for Fun-ASR. | |
| - Run `adb shell touch /sdcard/Android/data/com.asrlitertlm/files/*.litertlm` after the push. adb push | |
| writes whole-second modification times, and with those a later launch can miss the runtime cache | |
| and write it again ([LiteRT-LM #3772](https://github.com/google-ai-edge/LiteRT-LM/issues/3772)). | |
| ## Galaxy S26 numbers | |
| Galaxy S26 (SM-S942Q, Android 16), `litertlm-android` 0.17.1, language model and audio encoder on the | |
| CPU with 4 threads, 2026-10-09. "Transcribe" is the wall time of `sendMessage()`, from sending the | |
| clip to the full answer; RTF is that time over the clip's length. The three clips are the same sentence | |
| in three languages (below). | |
| | Model | zh, 9.7 s | en, 6.4 s | ja, 11.0 s | Microphone, 9 s | CPU limit at the start (big / prime cores) | | |
| |---|---|---|---|---|---| | |
| | Qwen3-ASR-1.7B | 2.38 s, RTF 0.25 | 2.49 s, RTF 0.39 | 3.56 s, RTF 0.32 | 2.97 s, CER 0 | 3.51 / 4.19 GHz | | |
| | Confucius4-R2T2 | 3.48 s, RTF 0.36 | 2.59 s, RTF 0.40 | 3.54 s, RTF 0.32 | 3.17 s, CER 0 | 3.63 / 4.74 GHz (no limit) | | |
| | Fun-ASR-Nano-2512 | 1.95 s, RTF 0.20 | 1.19 s, RTF 0.19 | 1.83 s, RTF 0.17 | 1.44 s, CER 0 | 3.63 / 4.74 GHz (no limit) | | |
| | Model | Engine load, first (writes the cache) | Engine load, cache in place | Runtime cache | Peak resident memory, first load | | |
| |---|---|---|---|---| | |
| | Qwen3-ASR-1.7B | 7.35 s | 0.72 s | 3.0 GB | 5.6 GB | | |
| | Confucius4-R2T2 | 4.27 s | 1.33 s | 3.0 GB | 5.7 GB | | |
| | Fun-ASR-Nano-2512 | 1.39 s | 1.13 s | 1.5 GB | 3.5 GB | | |
| - Every clip's text equals the Mac CPU answer of the same file (LiteRT-LM 0.17.1, Python) after | |
| removing punctuation and spaces. The three models write the same sentences for these clips. | |
| - The last column is the CPU limit at the start of the run (the maximum is 3.63 / 4.74 GHz; a warm phone | |
| lowers it). The Confucius4-R2T2 and Fun-ASR rows are a second run of the check on the same day with no | |
| limit (Confucius4-R2T2 at thermal status 0, Fun-ASR at status 1, each file pushed alone). The first run, | |
| with the limit lowered by heat, gave Confucius4-R2T2 4.03 / 3.06 / 3.83 s at 2.75 / 2.67 GHz and | |
| Fun-ASR 1.26 / 1.60 / 2.29 s at 2.23 / 2.23 GHz. Confucius4-R2T2 has the same architecture and file | |
| size as Qwen3-ASR-1.7B. In a run that started at the maximum, Qwen3-ASR-1.7B took 2.13 / 2.14 / 3.19 s | |
| for the three clips. | |
| - "Engine load" is `Engine.initialize()` plus the first conversation, which creates the audio encoder. | |
| The Qwen3-ASR-1.7B cached load is a new launch; the other two are a second load in the same process. | |
| - Microphone: the phone plays clip en through its speaker and records it with its microphone | |
| (media volume 3 of 15), then transcribes the recording. CER is the character error rate against | |
| the clip's sentence. | |
| - Language model on the GPU (launch extra `--es backend gpu`), Fun-ASR-Nano-2512: 1.69 / 1.68 / 2.29 s, | |
| the same text. All nodes of the prefill and decode graphs ran on the GPU (LITERT_CL); the audio | |
| encoder stays on the CPU (the model cards: the GPU delegate does not take it). Engine load 2.61 s. | |
| It was not faster than the CPU here. | |
| ## How the app calls a model | |
| The three bundles share one path ([`AsrEngine.kt`](app/src/main/kotlin/com/asrlitertlm/AsrEngine.kt)): | |
| one `Engine`, a new `Conversation` per clip, and one user message that holds only the audio file. Each | |
| bundle's template adds the rest: Fun-ASR's default instruction `语音转写:`, Qwen3-ASR's audio markers. | |
| ```kotlin | |
| val engine = Engine(EngineConfig( | |
| modelPath = bundle.path, // /sdcard/Android/data/com.asrlitertlm/files/<file> | |
| backend = Backend.CPU(threadCount = 4), // the language model | |
| audioBackend = Backend.CPU(threadCount = 4), // the audio encoder | |
| cacheDir = context.cacheDir.path, | |
| )) | |
| engine.initialize() | |
| val raw = engine.createConversation(ConversationConfig( | |
| samplerConfig = SamplerConfig(topK = 1, topP = 1.0, temperature = 0.0), | |
| maxOutputToken = 512, | |
| )).use { conversation -> | |
| conversation.sendMessage(Message.user(Contents.of(Content.AudioFile(wav.absolutePath)))).toString() | |
| } | |
| // Qwen3-ASR-1.7B and Confucius4-R2T2: "language English<asr_text>Everything in the universe ..." | |
| // Fun-ASR-Nano-2512: "Everything in the universe ..." | |
| ``` | |
| Only the answer differs: [`ModelProfile.kt`](app/src/main/kotlin/com/asrlitertlm/ModelProfile.kt) | |
| splits the Qwen3-ASR answer at `<asr_text>` and shows the named language; Fun-ASR's answer is the text. | |
| - One file is loaded at a time: picking another model closes the engine first. A first load of a | |
| Qwen3-ASR file peaked at 5.6–5.7 GB resident (VmHWM, the memory-mapped file included) on this phone | |
| with 11.4 GB of memory. | |
| - `Engine.close()` throws when called twice, so the app drops its reference before closing; releasing | |
| twice is harmless. | |
| - All model calls run on one worker thread. | |
| ## Microphone | |
| Hold **Hold to talk** and speak; releasing the button ends the recording, and so does the 30 s limit. | |
| Each model reads one window of about 30 s per message, so the app sends at most 30 s. The app records | |
| 16 kHz mono 16-bit PCM (the `VOICE_RECOGNITION` source) and writes it as a WAV file for the runtime. | |
| A recording quieter than −60 dBFS RMS is reported as "No speech heard" and is not sent to the model. | |
| Without the microphone permission the app shows a sentence that says how to allow it; the clips still work. | |
| ## The three clips | |
| `app/src/main/res/raw/` holds FLEURS test sentence 1698 read in Mandarin, English and Japanese | |
| ([google/fleurs](https://huggingface.co/datasets/google/fleurs) revision `70bb2e84`, test split, id 1698; | |
| FLEURS, Conneau et al. 2022, licensed [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)). Changes: | |
| converted to 16-bit PCM and given one linear gain each, so that all three have an active RMS of −20 dBFS. | |
| The English reading is "Everything in the Universe is made of matter. All matter is made of tiny | |
| particles called atoms." | |
| ## Device check | |
| [`AsrDeviceCheck.kt`](app/src/androidTest/kotlin/com/asrlitertlm/AsrDeviceCheck.kt) runs on a phone | |
| with at least one bundle pushed (as above). Turn the media volume up first: the microphone step plays a | |
| clip through the speaker. | |
| ```bash | |
| ./gradlew :app:installDebug :app:assembleDebugAndroidTest | |
| adb install -r -t app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk | |
| adb shell pm revoke com.asrlitertlm android.permission.RECORD_AUDIO | |
| adb shell am instrument -w -e class com.asrlitertlm.AsrDeviceCheck#check com.asrlitertlm.test/androidx.test.runner.AndroidJUnitRunner | |
| adb logcat -d -s asr-check | grep RESULT | |
| ``` | |
| It prints one line per step, `RESULT step=<name> ok=<true|false> model=<id> ...`, then | |
| `RESULT ok=<all>`. It starts with the microphone permission revoked and checks the sentence the app | |
| shows; then it grants the permission. For each bundle on the phone: load, the three clips (text equal to | |
| the expected sentence after removing punctuation and spaces), the microphone (CER ≤ 0.15), release | |
| twice, and a second load. Then a 33.6 s clip (cut to 30 s), a silent recording and a file that is not | |
| on the phone. With two or more bundles it also switches models without releasing. Add | |
| `-e class com.asrlitertlm.AsrDeviceCheck#gpu -e gpu_model fun-asr-nano-2512` for the GPU run. | |
| ## Launch extras | |
| For recordings and tests; the app works without them. | |
| | Extra | Effect | | |
| |---|---| | |
| | `--es model <id>` | `qwen3-asr-1.7b`, `fun-asr-nano-2512` or `confucius4-r2t2` (default: the model used last) | | |
| | `--es backend gpu` | language model on the GPU; the audio encoder stays on the CPU | | |
| | `--ez autoplay true` | after loading: clips zh, en, ja, each played and then transcribed (`--ei delay_ms`, `--ei gap_ms`) | | |
| | `--ei mic_test_ms 9000` | after loading and `delay_ms`: record that long, then transcribe (`--ez mic_test_play true` plays clip en meanwhile) | | |
| The app logs one `STATE <name>` line per screen state and `LOAD` / `TRANSCRIBED` lines with the times | |
| under the tag `AsrLitertlm`. | |
| ## Files | |
| | File | Role | | |
| |---|---| | |
| | `app/src/main/kotlin/com/asrlitertlm/AsrEngine.kt` | Engine and one Conversation per clip: load, transcribe (cut at 30 s), release (safe twice) | | |
| | `app/src/main/kotlin/com/asrlitertlm/ModelProfile.kt` | the three bundles: file name, Hugging Face id, answer format | | |
| | `app/src/main/kotlin/com/asrlitertlm/AsrSession.kt` | the app's one engine on one worker thread, events for the screen, the no-speech check | | |
| | `app/src/main/kotlin/com/asrlitertlm/MainActivity.kt` | picker, hold to talk, clip buttons, launch extras | | |
| | `app/src/main/kotlin/com/asrlitertlm/MicRecorder.kt` | 16 kHz mono recording, up to 30 s | | |
| | `app/src/main/kotlin/com/asrlitertlm/ClipPlayer.kt`, `PlayBar.kt` | clip playback through the speaker and its progress bar | | |
| | `app/src/main/kotlin/com/asrlitertlm/Wav.kt`, `TextMatch.kt` | WAV read, write and cut; transcript comparison (normalization and CER) | | |
| | `app/src/main/res/raw/fleurs_*_1698.wav` | the three clips | | |
| | `app/src/androidTest/kotlin/com/asrlitertlm/AsrDeviceCheck.kt` | device check | | |
| | `app/src/test/kotlin/com/asrlitertlm/AsrLogicTest.kt` | JVM tests: answer parsing, transcript comparison, WAV cut and levels | | |
| Build: AGP 9.3.1 with Kotlin 2.4.0 (the `litertlm-android` 0.17.1 AAR carries Kotlin 2.4 metadata), | |
| compileSdk 36, minSdk 31, arm64-v8a. The runtime version is pinned in `gradle.properties`. | |
| ## License | |
| The app code is under the repository's MIT license. The clips are CC BY 4.0 (FLEURS, see above). Each | |
| model file has its own license (table above); none of them is in this directory. | |