Python · Local ASR · September 11, 2026
Run Orukeet locally: Python speech recognition
Orukeet transcribes recordings in 25 languages on your own computer. Try it in the OpenWhispr desktop app, or install the published Python package and keep the recognizer loaded for a batch. You do not need an Oruk account or API key.
Orukeet produces text and segment times. If you need emotion or speaking-style scores, use the hosted speech API. Those outputs are separate from this open model.
Choose the OpenWhispr steps, native Python runtime or sherpa-onnx example. Each path includes an actual result from the supplied recording. The six-language integration checks show where the tested exports improved or regressed against stock Parakeet. For an editor or local client, use the persistent HTTP server.
Watch the local example
Hear the sample, see the command and inspect what the model returned. This 39-second walkthrough uses a recorded Orukeet 0.1.1 run on Apple silicon with the native Q8 model and Metal runtime.
Use Orukeet in OpenWhispr
You can transcribe a file without a Python environment. OpenWhispr 1.10.0 includes Orukeet as its recommended local model. The steps below were checked in the macOS app with the model already downloaded.
- Open Settings → Speech-to-Text → Audio Upload. Choose Local, then the Oruk tab. Download Orukeet if needed and select it so its card says Active.
- Close Settings and open Upload. Check that the provider reads Using Orukeet.
- Paste the public sample URL below into the audio URL field and choose Add link. Wait for the filename to appear.
- Leave Speaker detection off and choose Transcribe. The app shows Transcribing locally…, then the result.
https://oruk.ai/samples/oruk-quickstart.wavI am genuinely excited that this is finally working.If Upload says No transcription provider set up, check the Audio Upload tab in Settings. Dictation, Note Recording and Audio Upload have separate selections; having Orukeet active for dictation does not configure file uploads. We encountered this during the check and resolved it by selecting Orukeet for Audio Upload.
Checked September 11, 2026 with the public quickstart recording and speaker detection off. This verifies one file-transcription workflow in the released app. It does not measure recognition accuracy, latency, speaker separation or a customer outcome.
Install the model and runtime
Start with Python 3.12 or newer. The commands below use a macOS or Linux shell. Allow space for the 714 MB Q8 model, the native runtime and Python dependencies. The prebuilt runtime does not require a compiler.
python3 --version # Python 3.12 or newer
python3 -m venv .venv
source .venv/bin/activate
python -m pip install https://github.com/Oruk-AI/orukeet/releases/download/v0.1.1/orukeet-0.1.1-py3-none-any.whl
orukeet install --device auto --cache ./orukeet-cache --output installation.jsonThe installer checks artifact hashes and saves absolute paths in installation.json. Automatic selection uses Metal on Apple silicon, CUDA when an NVIDIA device is detected, and CPU otherwise, subject to the published runtime support for your platform. The run recorded below used Metal on Apple silicon.
Installation downloads the weights and runtime. Keep those files and the receipt together; transcription then runs locally. If you move the installation to another computer, run the installer there to select its runtime and regenerate the paths.
Transcribe a recording you can check
Download the short public quickstart recording and the complete runner. Listen to the audio, then compare it with the returned text.
curl --fail --location --output sample.wav https://oruk.ai/samples/oruk-quickstart.wav
curl --fail --location --output orukeet-local.py https://oruk.ai/examples/orukeet-local.py
python orukeet-local.py sample.wav --installation installation.json{
"file": "sample.wav",
"text": "I am genuinely excited that this is finally working.",
"segments": [
{
"text": "I am genuinely excited that this is finally working.",
"start": 0,
"end": 3.84
}
],
"language": null
}We recorded this output on September 11, 2026 using the published package in a fresh virtual environment. This one recording checks installation and the response format; it is not an accuracy benchmark. Verification record and hashes · Download the output.
Keep one recognizer loaded
Replace the filenames with your own recordings. The runner accepts several paths, processes them in order, and prints one JSON object per file. Redirect its output when you want to save the results.
python orukeet-local.py interview.wav lecture.flac --installation installation.json > transcripts.jsonlIn your own Python worker, create the recognizer outside the per-file loop. Construction verifies and loads the model. Repeating it for every recording adds startup work to every job.
import json
from pathlib import Path
from orukeet import Orukeet
config = json.loads(Path("installation.json").read_text(encoding="utf-8-sig"))
with Orukeet(config["model"], config["runtime"], device=config["device"]) as asr:
for audio in ["interview.wav", "lecture.flac"]:
result = asr.transcribe(audio)
print(json.dumps({"file": audio, **result}, ensure_ascii=False))A worker serializes its requests. Several workers each need their own model memory; this example is sequential, not vectorized batch inference. The local server below provides bounded HTTP uploads around the same native runtime.
Keep a local transcription server running
This optional example keeps one recognizer loaded for completed recordings from an editor or OpenAI-compatible client. After the installation steps above, run these commands in the same virtual environment and directory as installation.json. It reuses your downloaded model and runtime.
curl --fail --location --output local_server.py \
https://raw.githubusercontent.com/Oruk-AI/orukeet/6b79841e22d88b066c94236ed4a36ab98eeef04d/examples/local_server.py
curl --fail --location --output local-server-requirements.txt \
https://raw.githubusercontent.com/Oruk-AI/orukeet/6b79841e22d88b066c94236ed4a36ab98eeef04d/examples/local-server-requirements.txt
python -m pip install -r local-server-requirements.txt
python local_server.py --installation installation.jsonWait for Orukeet ready and the server startup message. Keep that terminal running, then send the sample recording from another terminal:
curl --fail-with-body http://127.0.0.1:8000/v1/audio/transcriptions \
-F model=orukeet -F file=@sample.wav -F response_format=textThe server listens on 127.0.0.1:8000 and processes one recording at a time. By default it admits two requests total, limits each upload to 25 MiB and decoded audio to five minutes, and returns HTTP 429 when full. Send recordings sequentially or retry after the indicated delay. Run one server only: extra workers or reload processes each load another model. Responses contain final text; this example does not stream partial transcripts.
Full setup, limits and Emacs client settings · Pinned server source · Pinned requirements. The example is for local use; the setup document covers authentication when binding beyond your computer.
Read the output at the right granularity
textcontains the transcription. Check unfamiliar names and domain vocabulary against your audio.segmentscontain text and start/end seconds on the original recording timeline. The native runner uses bounded windows for long inputs; these times are not word-level alignment or speaker turns.languageisnull. The native interface does not return a detected language or calibrated confidence.- Emotion, speaking style and diarization are not part of this local response. Do not infer them from missing fields.
When something fails
- The package will not install
- Check
python --versioninside the activated environment. Orukeet 0.1.1 needs Python 3.12+. Use the versioned wheel above; the hosted client package namedorukis a different package. - No pinned runtime for this platform
- The installer has no matching prebuilt artifact. Check the runtime support and build instructions. Selecting
--device cpumay work on supported CPU platforms; it does not add support for an unlisted platform. - Missing file or installation receipt
- Pass a real local audio path and the receipt produced by the installer. The runner exits with an error rather than downloading an unknown model or treating a failed file as a blank transcript.
- Hash mismatch
- Keep checksum validation enabled. Check which cached artifact failed, replace that incomplete download and rerun installation. A GGUF from another project is not interchangeable with this speech runtime.
- Slow first request
- Separate download, model loading, warmup and recognition when measuring. Keep the worker alive for subsequent files. Published warm timings exclude some of these costs and are not a promise for your hardware.
Use the ONNX export with sherpa-onnx
This is the published ONNX archive used by the OpenWhispr 1.10.0 integration. You can load it directly in Python without installing the desktop app. The example below uses the CPU provider, two threads and a fresh Python 3.12 environment on Apple silicon. It does not use the native Metal runtime.
Allow about 487 MB for the archive and 672 MB for its extracted files, plus the Python environment. The download is pinned to a model revision; the extraction step checks its SHA-256 before unpacking it. Keep the included weight license and attribution with the model. Use Python 3.12 for the pinned package versions shown here.
python3.12 -m venv .venv-onnx
source .venv-onnx/bin/activate
python -m pip install sherpa-onnx==1.13.4 numpy==2.2.6
curl --fail --location --output orukeet-onnx.tar.bz2 \
https://huggingface.co/oruk/orukeet/resolve/55a984d46f68323301837194ce647c702f55facc/onnx/sherpa-onnx-orukeet-v0.1.0-int8.tar.bz2
python - <<'PY'
import hashlib
import tarfile
with open("orukeet-onnx.tar.bz2", "rb") as archive:
digest = hashlib.file_digest(archive, "sha256").hexdigest()
if digest != "f9191f30178cc9122ce2f023bf9fefafc822028307b0efa4caff645ba3fe8d0a":
raise SystemExit("Archive checksum mismatch; download it again.")
with tarfile.open("orukeet-onnx.tar.bz2", "r:bz2") as archive:
archive.extractall(filter="data")
PYcurl --fail --location --output oruk-quickstart.wav https://oruk.ai/samples/oruk-quickstart.wav
curl --fail --location --output orukeet-onnx.py https://oruk.ai/examples/orukeet-onnx.py
python orukeet-onnx.py oruk-quickstart.wav \
--model-dir sherpa-onnx-orukeet-v0.1.0-int8{
"file": "oruk-quickstart.wav",
"text": "I am genuinely excited that this is finally working.",
"duration_seconds": 4.053877551020408,
"runtime": "sherpa-onnx",
"provider": "cpu"
}Recorded September 11, 2026. This checks the released archive, loader and one recording; it does not measure accuracy or compare runtime speed. Environment, hashes and verification · Download the output. The desktop app check above was run separately.
The runner accepts mono, 16-bit PCM WAV files from 0.1 to 30 seconds, at 8–48 kHz. It passes the recording’s actual sample rate to sherpa-onnx, which resamples to the model’s 16 kHz input. The supplied recording is 22.05 kHz. Invalid formats, truncated files and missing model files produce an error instead of an empty transcript.
Pass several WAV paths to reuse one recognizer. The loader needs feature_dim=128 and model_type="nemo_transducer"; ordinary loader defaults are not sufficient. The downloadable runner sets both. This full-context model does not become a streaming recognizer by accepting small audio chunks. For longer recordings, use the native worker above or implement and evaluate your application’s segmentation.
Choose the format for your application
Native Q8 is the compact path used here. F16 uses the same native stack. The ONNX INT8 export fits sherpa-onnx’s Parakeet TDT loader and is the format used by the OpenWhispr integration. NeMo source weights are available for inspection and further adaptation. All derive from the r3 release checkpoint; runtime formats need their own performance checks.
Code is MIT. Weights and fitted kernels are CC BY-SA 4.0, retaining NVIDIA’s foundation attribution. See the licenses and full evaluation protocolbefore reusing the model or quoting results. The release discloses checkpoint-selection and adaptation overlap; this installation test does not add independent accuracy evidence.
The same recordings through four local runtimes
On September 12, we compared Orukeet r3 with stock Parakeet TDT v3 on the first 20 FLEURS validation recordings in English, German, Spanish, French, Russian and Ukrainian. Each comparison used the same 120 clips and 2,433 reference words. On September 17, we rechecked their audio hashes and recomputed these historical tables from the saved transcripts. A separate fresh CPU reproduction below downloads the pinned inputs and runs both ONNX exports again.
These are our integration checks, not an independent holdout. The r3 research protocol discloses benchmark selection and adaptation overlap. This small sample does not establish performance on unseen audio, the other 19 local languages or the hosted API.
| Runtime / export | Parakeet | Orukeet |
|---|---|---|
| sherpa-onnx · INT8 / CPU | 10.28% 250 errors | 6.70% 163 errors |
| LocalAI · Q8 / CPU | 5.22% 127 errors | 5.22% 127 errors |
| LocalAI · Q8 / Metal | 5.14% 125 errors | 5.22% 127 errors |
| Handy runtime · Q8 / Metal | 5.14% 125 errors | 5.34% 130 errors |
The tested ONNX export reduced pooled errors. The native Q8 comparisons did not: LocalAI CPU tied, and Orukeet made two more errors on LocalAI Metal and five more on Handy Metal. English and Spanish improved in those native comparisons, but that did not produce a pooled advantage. Choose and evaluate the export you will actually deploy.
All six language results, including regressions
Every language has 20 clips. WER uses the total errors divided by reference words, with NFKC/casefold normalization, punctuation and symbols changed to spaces, and no number expansion.
| Language / words | Parakeet | Orukeet |
|---|---|---|
| English 382 words | 4.19% | 3.66% |
| German 393 words | 11.20% | 6.87% |
| Spanish 499 words | 14.83% | 2.40% |
| French 467 words | 6.21% | 7.49% |
| Russian 373 words | 9.65% | 6.97% |
| Ukrainian 319 words | 15.99% | 15.36% |
| Language / words | Parakeet | Orukeet |
|---|---|---|
| English 382 words | 4.19% | 3.40% |
| German 393 words | 3.31% | 3.56% |
| Spanish 499 words | 3.81% | 3.01% |
| French 467 words | 4.07% | 4.50% |
| Russian 373 words | 7.77% | 7.51% |
| Ukrainian 319 words | 9.72% | 11.29% |
| Language / words | Parakeet | Orukeet |
|---|---|---|
| English 382 words | 4.19% | 3.40% |
| German 393 words | 3.31% | 3.56% |
| Spanish 499 words | 3.81% | 3.01% |
| French 467 words | 3.64% | 4.50% |
| Russian 373 words | 7.77% | 7.51% |
| Ukrainian 319 words | 9.72% | 11.29% |
| Language / words | Parakeet | Orukeet |
|---|---|---|
| English 382 words | 4.19% | 3.40% |
| German 393 words | 3.56% | 4.07% |
| Spanish 499 words | 3.41% | 3.01% |
| French 467 words | 4.07% | 4.50% |
| Russian 373 words | 7.77% | 7.51% |
| Ukrainian 319 words | 9.40% | 11.60% |
Warm timing depends on what you measure
These runs used an Apple M5 Max with 128 GiB RAM and macOS 26.4.1. Each model processed every recording three times after warmup. LocalAI includes HTTP upload, server decoding and JSON response parsing; sherpa-onnx and the Handy runtime exclude file decoding and model loading. The rows therefore cannot establish a speedup between runtimes.
| Runtime / export | Parakeet | Orukeet |
|---|---|---|
| sherpa-onnx · INT8 / CPU | 325.31 / 586.31 | 275.62 / 506.69 |
| LocalAI · Q8 / CPU | Excluded¹ | Excluded¹ |
| LocalAI · Q8 / Metal | 645.25 / 860.87 | 634.88 / 857.45 |
| Handy runtime · Q8 / Metal | 68.25 / 100.52 | 68.65 / 104.33 |
¹ LocalAI CPU timing overlapped other work. Earlier Handy timings also overlapped other work and were replaced by the alternating paired run above. sherpa-onnx used two CPU threads and separate warmed model blocks; LocalAI and Handy Metal alternated model order per recording. A first LocalAI Metal attempt failed when disk space ran out; its incomplete run is excluded, with the failure retained in the archive. These measurements support comparable native speed on this machine, not a general acceleration claim.
Check the arithmetic without installing a model
curl --fail --location --output orukeet-integrations.zip \
https://oruk.ai/benchmarks/orukeet-integrations-2026-09-12.zip
python3 -m zipfile -e orukeet-integrations.zip .
cd orukeet-integrations-2026-09-12
python3 replay.py --checkThe archive includes every recording’s saved output, all three timed repetitions, the fixed manifest, model and runtime provenance, original protocols, and a dependency-free scorer. It also retains unpaired Handy CPU and NeMo source checks as diagnostics, without inventing a comparison. The replay checks file hashes and recomputes every table above; it makes no API calls.
This archive verifies the saved results and preserves the original protocols. The new package below closes pinned acquisition and fresh inference for the ONNX CPU pair. Native runtime reproduction remains unfinished, including the missing historical LocalAI CPU backend digest. Audio and model weights are not included. FLEURS reference excerpts are credited to Conneau and colleagues under CC BY 4.0.
Download the complete replay archive · Protocol, failures and limitations · Recording manifest · Complete scores · Model and runtime provenance
Re-run the CPU comparison from pinned downloads
On September 17, we downloaded the six immutable FLEURS shards and both published ONNX exports into a new directory, installed a hash-locked Python environment, and ran the comparison again. All 120 audio hashes, recording IDs, original references and sample counts matched the old manifest. Every new transcript matched its model’s historical output, and all repeated transcripts were stable: 960 successful receipts, including warmup, with no inference failures. French regressed from 29 errors with stock Parakeet to 35 with Orukeet; the pooled improvement does not imply a gain in every language.
| INT8 export | WER / errors | Warm median / p95 |
|---|---|---|
| Stock Parakeet TDT v3 | 10.28% 250 errors | 307.27 / 554.14 ms |
| Orukeet r3 | 6.70% 163 errors | 254.16 / 454.53 ms |
Every language in the new run
| Language / words | Parakeet | Orukeet |
|---|---|---|
| German 393 words | 11.20% | 6.87% |
| English 382 words | 4.19% | 3.66% |
| Spanish 499 words | 14.83% | 2.40% |
| French 467 words | 6.21% | 7.49% |
| Russian 373 words | 9.65% | 6.97% |
| Ukrainian 319 words | 15.99% | 15.36% |
The run used an M5 Max with 128 GiB RAM, macOS 26.4.1 and two CPU threads per model. Both models were loaded before warmup, then decoded sequentially in alternating order over three shuffled passes: 360 timed observations per model. Timing excludes downloads, WAV decoding, model loading and result writing. Task-owned heavy work was paused; normal background activity remained. The older ONNX run used separate model blocks, so these numbers do not establish an improvement over that run or a speedup against a different runtime.
This establishes that the published artifacts can reproduce these outputs. It reuses a development integration sample, whose unseen status is unverified. The r3 protocol discloses benchmark use for checkpoint selection and adaptation overlap. This is not independent accuracy evidence or a hosted API measurement. The stock ONNX files are pinned; the exporter’s exact NVIDIA source-checkpoint attestation remains unavailable. The package records that provenance gap and the applicable model-card terms.
curl --fail --location --output orukeet-reproduction.zip \
https://oruk.ai/benchmarks/orukeet-reproduction-2026-09-17.zip
python3 -m zipfile -e orukeet-reproduction.zip .
cd orukeet-reproduction-2026-09-17
python3 verify.py
python3 replay.py --checkTo run new inference, continue in the extracted directory on macOS arm64. Install uv first if it is not already available. The download is about 2.64 GB; allow at least 5 GB free. No API key is needed. Record the actual workload conditions in the note and choose a new output directory. Any changed file hash, missing recording, failed decode or unstable repeated output prevents a complete comparison.
uv venv --python 3.11.15 .venv
uv pip install --python .venv/bin/python --require-hashes --only-binary :all: -r requirements.txt
.venv/bin/python fetch.py --work ../orukeet-inputs
.venv/bin/python run.py --work ../orukeet-inputs --output runs/my-reproduction \
--note 'Describe your actual background workload here.'
.venv/bin/python score.py runs/my-reproduction --checkDownload the reproduction package · Exact protocol and license terms · Pinned acquisition sources · All 960 receipts · Scores and per-recording outputs
How Sacha Chua connected Orukeet to Emacs
Sacha Chua's September 12 demonstration shows Orukeet inside Emacs on a Lenovo P52 using only the CPU. She replays a selected portion of a recording and switches between English and French. Her post describes a small server that keeps the model in memory, with recordings sent from her fork of whisper.el.
Chua chooses when a segment is ready, then keeps recording while earlier segments transcribe. In her published Emacs configuration, sacha-whisper-continue queues the completed recording and starts another; the result handler inserts finished transcripts in queue order. That lets her pause to think and decide where a thought ends. The client sends completed files, rather than requesting partial word hypotheses.
Connect your editor to the local example
Our local server above provides a documented starting point for the same kind of workflow. Start it first, then use these settings for ordinary whisper.el requests. The client appends v1/audio/transcriptions to the base URL, so leave /v1 out of that setting. The placeholder key satisfies the client; a loopback-only server does not require an Oruk account.
(setq whisper-server-mode 'openai
whisper-openai-api-baseurl "http://127.0.0.1:8000/"
whisper-openai-api-key "local"
whisper-openai-model "orukeet"
whisper-language "auto"
whisper-translate nil)Chua's custom queue builds its own URL and uses whisper-model, so it needs the separate queue settings. It also does not retry HTTP 429 automatically. Our server allows one working recording plus one queued by default; submit one at a time, or handle Retry-After before feeding it a longer queue. Keep the audio until you have checked the transcript, especially before using it as a command.
Sources: Chua's client fork, pinned source · Oruk's server setup and limits. Her post links a server file on her own computer, so we cannot reconstruct that exact setup from the post. Our server is a separate implementation. Her demonstration documents an independent integration; it provides no controlled accuracy or latency comparison, and does not validate the hosted API.
If you publish your own reproduction, include the package and weight revision, hardware and runtime, commands, recording permission, actual output, and any failures. Separate installation time from inference time. The verification record shows what we captured for this guide; one successful recording is not an accuracy benchmark.
When to use the hosted API
The hosted Orukeet API accepts English utterances up to 60 seconds, using an Oruk API key. It can add emotion detection and speaker diarization, which are separate from the local model described here. For full transcript, emotion and speaking-style analysis, see the speech emotion API.
Compare the hosted request and streaming formats, plan allowances, and reproducible serving measurements before choosing a deployment. The hosted English interface and local 25-language weights have different capabilities and limits.