Skip to main content

简体中文 | English

ASRKit

One interface for speech recognition — on-device to cloud, swap one model string, your code doesn't change.

PyPI Python License CI

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, run asrkit doctor for a one-command health check (engines / keys / dirs / config; --net adds 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 old local/ prefix is kept permanently as a historical alias and still resolves (e.g. local/sensevoice is equivalent to sherpa/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 an ImportError.
  • 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/vtt subtitles: 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_RETRIES tunable).

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 right pip install for you, no quoting). When installing an extra with pip directly, zsh needs quotes around asrkit[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 own pip uninstall. Only models whose adapter declares cache_owner="asrkit" have the symmetric ASRKit-store pull/rm lifecycle. Engine-owned caches (for example HuggingFace or whisper.cpp caches) stay with that engine; rm refuses to delete them. Third-party adapters default to cache_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=true to the same endpoint → text/event-stream, OpenAI-compatible transcript.text.delta (partial) / transcript.text.done (final) events; temp files are cleaned up automatically on disconnect. Only streaming models are supported — requesting stream=true on 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 serve defaults to 200 MiB uploads, 4 active transcriptions, and a 300-second timeout; direct build_app() embedders should set their own limits. Eviction and app shutdown call the adapter's close() hook.
  • Loopback browser defense: transcription POSTs carrying a non-empty Origin header 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_response escape 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)

Source distribution for asrkit 0.5.5
File Size Uploaded
asrkit-0.5.5.tar.gz 91.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for asrkit 0.5.5
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.5.5 This release

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page