简体中文 | English
ASRKit
One interface for speech recognition — on-device to cloud, swap one model string, your code doesn't change.
ASRKit is to speech recognition what Ollama + LiteLLM are to LLMs: ASRKit-managed models pull-and-go, one addressing scheme across on-device and cloud, plus an optional OpenAI-compatible local server. The core is just a thin interface — the base install depends only on requests; engines install on demand, while external engine-owned caches remain under their engine's control. No torch for things you don't use.
It brings an uncommon combination under one interface: Chinese SOTA on-device models (SenseVoice / Paraformer / FireRed / TeleSpeech — 47 ASRKit-managed sherpa models) + major China cloud providers (DashScope / Doubao / SiliconFlow) + the Whisper family + open addressing for HuggingFace ASR models.
⚠️ Early beta, under active development. The core interface is usable, but we're still iterating — addressing/APIs may shift slightly between minor versions. Try it and tell us what breaks.
Install — pick your way, it's not pip-only
The base install needs only requests (cloud is built in); engines/models/serve are all opt-in. So cloud-only use is nearly zero-setup — pick the row that fits you:
| You want | Install |
|---|---|
| Cloud-only, zero env hassle | uv tool install asrkit — uv is a single one-line binary; asrkit lands on your PATH, no Python env to manage |
| Not even install (run once) | uvx asrkit transcribe audio.wav -m siliconflow/sensevoice --api-key <KEY> — no ASRKit preinstall; uv creates a temporary environment and may retain download caches |
| Regular Python user | pip install asrkit |
| Global command, don't touch current env | pipx install asrkit |
| On-device engines (sherpa, 47 models) | once asrkit is installed, asrkit engine install sherpa-onnx (into your Python env; no shell-quoting to fight) |
Install
uv:curl -LsSf https://astral.sh/uv/install.sh | sh(one line on macOS/Linux, single binary; no Python environment to manage manually for ASRKit). After installing, runasrkit doctorfor a one-command health check (engines / keys / dirs / config;--netadds connectivity checks).
30 seconds to first transcript
asrkit transcribe audio.wav -m siliconflow/sensevoice --api-key <KEY> # cloud example; provider account/API key required, pricing may change
asrkit run sherpa/sensevoice audio.wav # on-device: downloads on first run, then transcribes (needs asrkit engine install sherpa-onnx first)
The model string is the only thing that changes
Engine, model, on-device or cloud — all the same call:
asrkit run sherpa/sensevoice audio.wav # sherpa-onnx (on-device)
asrkit run faster-whisper/large-v3 audio.wav # faster-whisper engine
asrkit run whispercpp/base audio.wav # whisper.cpp engine
asrkit run transformers/openai/whisper-large-v3 audio.wav # any HuggingFace model
asrkit run dashscope/qwen3-asr-flash audio.wav --api-key … # cloud, bring your own key
On-device sherpa/sensevoice and cloud siliconflow/sensevoice are the same call — comparing edge vs cloud is just swapping the string.
Note: the canonical prefix for sherpa models is
sherpa/; the oldlocal/prefix is kept permanently as a historical alias and still resolves (e.g.local/sensevoiceis equivalent tosherpa/sensevoice) — existing scripts are unaffected.
from asrkit import transcribe
print(transcribe("sherpa/sensevoice", "audio.wav").text)
Why ASRKit
- A Chinese/multilingual-first edge-and-cloud combination. 47 sherpa on-device models + 5 cloud vendors out of the box; China cloud providers and Chinese on-device models are first-class citizens, not an afterthought.
- The interface is the core; everything is pluggable. The base install ships only the interface + cloud (just
requests); engines, models, and the server are all add-ons. Use an engine you haven't installed → a friendly error with the install command, not anImportError. - Learn once, use three ways. CLI, Python library, and HTTP (OpenAI-compatible serve) — one model addressing scheme across all of them.
- Transparent by design. It doesn't touch your audio or change a model's native behavior by default. Wrong format? An honest error — never silent garbage. Unsupported options warn instead of being silently dropped. Conversion and chunking are opt-in.
- Clear data boundaries. ASRKit itself does not host or collect audio. Local models stay on-device; cloud models send audio and required credentials to the provider you select, under that provider's privacy terms.
Batch & scripting
Transcribe many files, a directory, a glob, or stdin at once — structured tables for comparison and scripting:
asrkit transcribe *.wav -m sherpa/sensevoice -f csv # one row each: file,model,text,latency_ms,rtf…
asrkit transcribe ./recordings -m dashscope/qwen3-asr-flash -f json --batch # recurse a dir → NDJSON
cat a.wav | asrkit transcribe - -m sherpa/sensevoice # stdin
- NDJSON / csv / tsv for batches (a single file is still one object); contract in docs/result-contract.md.
srt/vttsubtitles: the whisper family (faster-whisper / whispercpp / openai/whisper-1) returns timestamps, so subtitles just work; other models get an honest error — never a fabricated timeline.- Graded exit codes
0/1/2/3/4(ok / unexpected / usage error / model not found / transcription failed; any failure in a batch → non-zero), so scripts can tell why. - Cloud batches retry transient failures automatically — cost-safe: billable requests retry only on rate-limit/connection failure, never double-billing (
ASRKIT_HTTP_RETRIEStunable).
Streaming (minimal)
Decode sherpa online (streaming) models chunk by chunk, emitting incremental text as audio is fed:
asrkit stream sherpa/stream-paraformer-zhen meeting.wav # live partials → stderr, final text → stdout
asrkit stream sherpa/stream-paraformer-zhen meeting.wav > out.txt # pipe-friendly: capture final text only
asrkit stream sherpa/stream-paraformer-zhen --mic # live microphone transcription, Ctrl-C to stop (needs asrkit[mic])
Only models with streaming in modes are supported (batch models get a clear error). serve also supports streaming: see "Run it as a server" below.
Discovery & diagnostics
asrkit search whisper # search models by id/name
asrkit list --lang ja # filter by language (broad multilingual models returned as candidates)
asrkit doctor # health check: engines / keys (presence only) / models dir writable / config valid
asrkit doctor --net # add download-source / cloud reachability checks
asrkit completion zsh # bash/zsh/fish completion (model names complete dynamically)
run/transcribe/stream/serve all support -v (INFO) / -vv (DEBUG) for more log detail; silent by default, doesn't affect stdout consumed by scripts.
Pluggable: a tiny core, engines/serve added on demand
The base install is just the interface + cloud (only requests — installs in seconds, runs anywhere). Everything else is opt-in (extras in the table below):
| You want | Install |
|---|---|
Cloud + CLI + a client for serve |
pip install asrkit |
| Default on-device engine (sherpa, 47 models) | asrkit engine install sherpa-onnx |
| Other engines | asrkit engine install faster-whisper / whispercpp / transformers |
| Local server | extra asrkit[serve] |
| Live microphone streaming | extra asrkit[mic] |
| Everything | extra asrkit[all] |
Prefer
asrkit engine install <name>for engines (runs the rightpip installfor you, no quoting). When installing an extra with pip directly, zsh needs quotes aroundasrkit[serve]and friends:pip install 'asrkit[serve]'.
Ownership model: engines are shared pip packages —
asrkit engine install <name>installs into the right environment for you; uninstall with your ownpip uninstall. Only models whose adapter declarescache_owner="asrkit"have the symmetric ASRKit-storepull/rmlifecycle. Engine-owned caches (for example HuggingFace or whisper.cpp caches) stay with that engine;rmrefuses to delete them. Third-party adapters default tocache_owner="unknown", which is also non-removable until the plugin explicitly declares ownership.
Commands
| Command | What it does |
|---|---|
asrkit list |
list all models (✓ = adapter-defined legacy installed/readiness signal); filter with --lang/--arch, bare ids with --ids; JSON also reports cached, cache_owner, and removable |
asrkit search <term> |
search models by id/name |
asrkit run <model> <audio> |
ensure adapter readiness, then transcribe; ASRKit-managed sherpa models are pulled when absent |
asrkit transcribe <audio…> -m <model> |
transcribe only; multiple files / dir / glob / - (stdin), --batch; --format txt/json/srt/vtt/csv/tsv, -o, --language |
asrkit stream <model> <audio> |
streaming transcription (sherpa online models) |
asrkit pull <model> [--url …] / rm <model> |
acquire a model through its adapter / remove only an ASRKit-owned cache (--url is for ASRKit-managed downloads) |
asrkit show <model> |
model details |
asrkit engine list / install <name> / default <name> / rm <name> |
manage engines (rm is advisory: prints uninstall instructions, never runs pip uninstall) |
asrkit config set-key <vendor> <KEY> / list |
store keys / default engine / models dir |
asrkit doctor [--net] |
health-check the install and config |
asrkit serve |
run an OpenAI-compatible local server |
asrkit completion <shell> |
bash/zsh/fish completion script |
asrkit add-model … |
register a custom sherpa model |
Engines & models
| Engine | Install | Address | Covers |
|---|---|---|---|
| sherpa-onnx (default on-device) | asrkit[sherpa] |
sherpa/<model> or bare <model> |
47 on-device models, 16 registered config_type values |
| faster-whisper | asrkit[faster-whisper] |
faster-whisper/<model> |
fast Whisper, native long-audio |
| whisper.cpp | asrkit[whispercpp] |
whispercpp/<model> |
ultra-light Whisper (no torch/onnx) |
| transformers | asrkit[transformers] |
transformers/<any-hf-id> |
the whole HuggingFace ASR hub + LLM-arch SOTA |
| cloud | built-in | <vendor>/<model> |
see below, bring your own key |
Cloud vendors (built in, just add a key)
| Vendor | Addressing | Key |
|---|---|---|
| SiliconFlow | siliconflow/sensevoice, siliconflow/telespeech |
--api-key |
| OpenAI | openai/whisper-1 |
--api-key |
| Alibaba DashScope | dashscope/qwen3-asr-flash, dashscope/fun-asr-flash, dashscope/qwen-omni-plus, dashscope/qwen-omni-flash |
--api-key |
| Volcengine / Doubao | doubao/auc-2 (2.0 Seed), doubao/auc-1 (1.0) |
--api-key, or --app-key + --access-key |
| ElevenLabs | elevenlabs/scribe-v1 |
--api-key |
Three ways to supply a key (highest priority first): --api-key > env var <VENDOR>_API_KEY (Volcengine's dual key uses DOUBAO_APP_KEY/DOUBAO_ACCESS_KEY) > asrkit config set-key <vendor> <KEY> once.
Run it as a server: OpenAI-compatible subset
asrkit serve starts a local server. OpenAI SDK apps that use ASRKit's supported fields, agents, and ordinary HTTP clients can change base_url and reach registered on-device or cloud models through one endpoint. The caller needs zero asrkit deps, just HTTP. See the compatibility boundary.
Security boundary: the ordinary CLI still has no built-in authentication, but it defaults to a 200 MiB upload limit, 4 active transcriptions, a 300-second timeout, and rejects browser-origin transcription requests. It remains a trusted-local service: do not expose it directly to the public internet or an untrusted network; put authentication and exact access controls at the gateway first.
pip install 'asrkit[serve]'
asrkit config set-key dashscope <KEY> # store a key once (only for cloud)
asrkit serve # 127.0.0.1:11435 by default, local only
from openai import OpenAI
c = OpenAI(base_url="http://localhost:11435/v1", api_key="unused")
c.audio.transcriptions.create(model="sherpa/sensevoice", file=open("a.wav", "rb"))
- Endpoints:
POST /v1/audio/transcriptions(response_format: json/verbose_json/text/srt/vtt),GET /v1/models,GET /health. - Streaming: add
stream=trueto the same endpoint →text/event-stream, OpenAI-compatibletranscript.text.delta(partial) /transcript.text.done(final) events; temp files are cleaned up automatically on disconnect. Only streaming models are supported — requestingstream=trueon a non-streaming model errors out. - Runtime lifecycle: each app owns a capacity-target adapter LRU and a fixed worker pool. Construction is single-flight per canonical model id; adapters are serialized by default unless they opt into concurrent calls, and active requests pin an adapter until batch or SSE work really finishes. Normal
asrkit servedefaults to 200 MiB uploads, 4 active transcriptions, and a 300-second timeout; directbuild_app()embedders should set their own limits. Eviction and app shutdown call the adapter'sclose()hook. - Loopback browser defense: transcription POSTs carrying a non-empty
Originheader are rejected by default, preventing an arbitrary web page from triggering local inference or configured cloud billing. Put an authenticated gateway with an exact CORS allowlist in front when browser access is intentional. - Cloud keys can come from a plaintext config file protected with 0600 permissions, so no per-request key is needed; use environment variables if you do not want credentials persisted. Transparent: raw bytes uploaded, no decoding.
Extend it
Add any sherpa model — one command, or an entry in ~/.asrkit/models.json:
asrkit add-model sherpa/my-model --url https://…/model.tar.bz2 --arch senseVoice --langs zh,en
Add an engine — ship a small package that declares an asrkit.adapters entry point; pip install auto-registers it. No fork, no core changes. Recipe: docs/engines-and-addressing.md.
Design principles & boundaries
ASRKit is deliberately restrained — what it doesn't do matters as much as what it does:
- It never touches your audio. The core does zero processing and hands bytes to the model/cloud as-is; decoding/resampling/chunking are all opt-in (
--convert/--segment). - It doesn't swallow specialist ecosystems. Speaker diarization and forced alignment stay out of the interface layer — use the
raw_responseescape hatch or compose on top. - It doesn't uninstall engines for you. Engines are shared pip packages: it helps you install into the right env, but your environment is yours.
- It doesn't fake support. No timestamps from the model → no subtitles; an option that won't take effect → a warning. Honest errors beat silent wrong output.
Docs
Usage · OpenAI compatibility boundary · Adapter contract · Result contract · Engines & addressing · Model management · Product form · Embedding & distribution · Roadmap
Apache-2.0. ASRKit does not grant model licenses; verify them on the model or provider's official page before commercial use. ASRKit itself does not host audio; cloud models send audio and required credentials to the provider you select.
Metadata
Release files for asrkit 0.5.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| asrkit-0.5.5.tar.gz | 91.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| asrkit-0.5.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 195.7 kB
Release files / asrkit-0.5.5.tar.gz
| Download URL | asrkit-0.5.5.tar.gz |
|---|---|
| Size | 91.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5776a5fda28a06badfc70912c404566c058be035d4cd747bf2da18d6762cd378
|
|
BLAKE2b-256 checksum How to use checksums |
832a51bace0751f3fb5dd87b701a84f39515bb84abf1ca0522b1cfed52105402
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 16, 2026.
Transparency logRelease files / asrkit-0.5.5-py3-none-any.whl
| Download URL | asrkit-0.5.5-py3-none-any.whl |
|---|---|
| Size | 103.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6da9d3ebaac6bef95d704148e924c874ac2eda72811f608d8b72e7db8a6794ad
|
|
BLAKE2b-256 checksum How to use checksums |
434c2354797ca163e5497e3d82dfbcff6b4aeda882f1541bbddf8917cf00453e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 16, 2026.
Transparency log