qwen3-asr-rs

Library Listed

Pure Rust implementation of Qwen3 ASR (Automatic Speech Recognition) with libtorch and MLX backends

Checked · Sources

Downloads
21
Dependents
0
Stars
254
Forks
26
Contributors
1
Commits
72
Latest release
0.2.0 ·

About

From the project README ·

Qwen3 ASR -- Rust CLI tools

Pure Rust implementation of Qwen3-ASR automatic speech recognition. The project builds a cross-platform CLI tool and API server suitable for agentic skills for AI agents and bots.

  • asr generates text from an input audio file (supports most codex and file formats)
  • asr-server runs an OpenAI-compatible HTTP API server for audio transcription

Supports two backends: libtorch (via the tch crate, cross-platform with optional CUDA) and MLX (Apple Silicon native via Metal GPU). Loads model weights directly from safetensors files and re-implements the complete neural network forward pass in Rust.

Learn more:

Quick Start

The install script automatically detects your platform (macOS/Linux, CPU/CUDA GPU), downloads the correct release binary, model weights, and a sample audio file:

curl -sSf https://raw.githubusercontent.com/second-state/qwen3_asr_rs/main/install.sh | bash
Read the full README

The installer will prompt you to choose a model size (0.6B recommended) and, on Linux with an NVIDIA GPU, whether to use CUDA or CPU.

Once complete, run your first transcription:

cd qwen3_asr_rs
./asr ./Qwen3-ASR-0.6B sample.wav

Output:

Language: English
Text: Thank you for your contribution to the most recent issue of Computer.

Architecture

The implementation ports the Qwen3-ASR encoder-decoder architecture from PyTorch/Transformers to Rust with libtorch (via the tch crate):

  • Audio Encoder (Whisper-style): 3x Conv2d downsampling → sinusoidal positional embeddings → 18 transformer encoder layers → output projection (896 → 1024)
  • Text Decoder (Qwen3): 28 transformer decoder layers with Grouped Query Attention (16 Q heads / 8 KV heads), QK-normalization, MRoPE (Multimodal Rotary Position Embeddings), and SwiGLU MLP
  • Audio preprocessing: FFmpeg decodes any audio format → resampled to mono 16kHz f32 → 128-bin log-mel spectrogram (Whisper-style)

Supported Models

ModelParametersHuggingFace
Qwen3-ASR-0.6B0.6BQwen/Qwen3-ASR-0.6B
Qwen3-ASR-1.7B1.7BQwen/Qwen3-ASR-1.7B

Usage

# Basic transcription (auto-detect language)
asr ./Qwen3-ASR-0.6B input.wav

# Force language
asr ./Qwen3-ASR-0.6B input.wav chinese
asr ./Qwen3-ASR-0.6B input.wav english

# Enable debug logging
RUST_LOG=debug asr ./Qwen3-ASR-0.6B input.wav
Output Format
Language: Chinese
Text: 你好世界

API Server

The asr-server binary provides an OpenAI-compatible HTTP API for audio transcription.

Start the Server
asr-server --model-dir ./Qwen3-ASR-0.6B

Options:

--model-dir <PATH>      Path to the Qwen3-ASR model directory (required)
--host <ADDR>           Host address to bind to (default: 0.0.0.0)
--port <PORT>           Port to listen on (default: 8080)
--language <LANG>       Default language for transcription (e.g., chinese, english)
-v, -vv                 Verbose output (debug, trace)
Endpoints
POST /v1/audio/transcriptions

OpenAI-compatible transcription endpoint. Accepts multipart form data.

FieldTypeRequiredDescription
filebinaryYesAudio file (any format supported by FFmpeg)
languagestringNoLanguage hint (e.g., english, chinese)
response_formatstringNojson (default), text, or verbose_json
modelstringNoAccepted for compatibility, ignored
temperaturefloatNoAccepted for compatibility, ignored
promptstringNoAccepted for compatibility, ignored

Examples:

# JSON response (default)
curl -X POST http://localhost:8080/v1/audio/transcriptions \
  -F file=@recording.wav

# {"text":"Thank you for your contribution..."}

# Plain text response
curl -X POST http://localhost:8080/v1/audio/transcriptions \
  -F file=@recording.wav \
  -F response_format=text

# Thank you for your contribution...

# Verbose JSON with language and duration
curl -X POST http://localhost:8080/v1/audio/transcriptions \
  -F file=@recording.wav \
  -F response_format=verbose_json

# {"task":"transcribe","language":"English","duration":7.999,"text":"Thank you..."}

# Force language
curl -X POST http://localhost:8080/v1/audio/transcriptions \
  -F file=@recording.wav \
  -F language=chinese
GET /v1/models

Lists available models.

curl http://localhost:8080/v1/models
# {"object":"list","data":[{"id":"qwen3-asr","object":"model","owned_by":"qwen"}]}
GET /health

Health check endpoint.

curl http://localhost:8080/health
# {"status":"ok"}

Supported Languages

Qwen3-ASR supports 30 languages: Chinese, English, Cantonese, Arabic, German, French, Spanish, Portuguese, Indonesian, Italian, Korean, Russian, Thai, Vietnamese, Japanese, Turkish, Hindi, Malay, Dutch, Swedish, Danish, Finnish, Polish, Czech, Filipino, Persian, Greek, Romanian, Hungarian, Macedonian.

Build from Source

Prerequisites

Download model weights and generate the tokenizer:

pip install huggingface_hub transformers

huggingface-cli download Qwen/Qwen3-ASR-0.6B --local-dir Qwen3-ASR-0.6B

python -c "
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained('Qwen3-ASR-0.6B', trust_remote_code=True)
tok.backend_tokenizer.save('Qwen3-ASR-0.6B/tokenizer.json')
"
Build for macOS (MLX)
git submodule update --init --recursive
cargo build --release --no-default-features --features mlx
Build for Linux (libtorch)

Download and extract libtorch for your platform from libtorch-releases:

# Linux x86_64 (CPU)
curl -LO https://github.com/second-state/libtorch-releases/releases/download/v2.7.1/libtorch-cxx11-abi-x86_64-2.7.1.tar.gz
tar xzf libtorch-cxx11-abi-x86_64-2.7.1.tar.gz

# Linux x86_64 (CUDA 12.6)
curl -LO https://github.com/second-state/libtorch-releases/releases/download/v2.7.1/libtorch-cxx11-abi-x86_64-cuda12.6-2.7.1.tar.gz
tar xzf libtorch-cxx11-abi-x86_64-cuda12.6-2.7.1.tar.gz

# Linux ARM64 (CPU)
curl -LO https://github.com/second-state/libtorch-releases/releases/download/v2.7.1/libtorch-cxx11-abi-aarch64-2.7.1.tar.gz
tar xzf libtorch-cxx11-abi-aarch64-2.7.1.tar.gz

# Linux ARM64 (CUDA 12.6 / Jetson)
curl -LO https://github.com/second-state/libtorch-releases/releases/download/v2.7.1/libtorch-cxx11-abi-aarch64-cuda12.6-2.7.1.tar.gz
tar xzf libtorch-cxx11-abi-aarch64-cuda12.6-2.7.1.tar.gz

Set environment variables:

export LIBTORCH=$(pwd)/libtorch
export LIBTORCH_BYPASS_VERSION_CHECK=1

Install dependencies and build:

cargo build --release

Project Structure

src/
├── main.rs            # CLI binary entry point
├── bin/
│   └── server.rs      # API server binary entry point
├── lib.rs             # Library module declarations
├── tensor.rs          # Unified Tensor abstraction (tch/MLX backend)
├── config.rs          # Model configuration (from config.json)
├── error.rs           # Error types
├── audio.rs           # FFmpeg-based audio loading and format conversion
├── mel.rs             # Whisper-style mel spectrogram feature extraction
├── weights.rs         # Safetensors weight loading (bf16 → f32 conversion)
├── layers.rs          # Neural network building blocks (LayerNorm, RMSNorm,
│                      #   attention, MLP, MRoPE, etc.)
├── audio_encoder.rs   # Whisper-style audio encoder (Conv2d + Transformer)
├── text_decoder.rs    # Qwen3 text decoder with KV cache
├── tokenizer.rs       # HuggingFace tokenizer wrapper
├── inference.rs       # End-to-end ASR inference pipeline
└── backend/
    └── mlx/           # Apple MLX backend (Metal GPU)
        ├── ffi.rs     # Raw C FFI bindings to mlx-c
        ├── array.rs   # Safe RAII MlxArray wrapper
        ├── ops.rs     # Safe operation wrappers
        ├── io.rs      # Safetensors loading via mlx-c
        ├── signal.rs  # STFT, mel spectrogram signal processing
        └── stream.rs  # Device/stream management

Performance

Benchmarked on Apple M4 Mac Mini (16GB RAM), MLX Metal GPU backend. All times are warm runs (post-shader compilation), best-of-3.

Qwen3-ASR-0.6B
Test FileAudio DurationTokensCLIAPI Server
sample1.wav (English)8.0s312.35s2.10s
speech_en.wav (English)3.5s151.30s1.05s
sample2.wav (English)2.8s131.17s0.95s
sample3.wav (Chinese)5.6s151.31s1.07s
Qwen3-ASR-1.7B
Test FileAudio DurationTokensCLIAPI Server
sample1.wav (English)8.0s316.26s5.80s
speech_en.wav (English)3.5s153.40s3.06s
sample2.wav (English)2.8s132.82s2.59s
sample3.wav (Chinese)5.6s153.31s2.94s

The API server is faster per request because the model stays loaded in memory, avoiding the process startup and model loading overhead of the CLI.

License

Apache-2.0

Runs on
CUDA
What shows it
  • CUDA: qwen3-asr-rs feature tch-backend (dependency tch)
Native code
Optional
  • Binds native code: torch-sys (feature tch-backend)
  • Build uses a native toolchain: cmake
Python bindings
No Python binding crate found
License
Apache-2.0

Compare with similar projects

Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.

qwen3-asr-rs beside the projects that share a topic with it
ProjectDownloadsDependentsStarsLatest releaseRuns on (GPU)Native codeLicense
qwen3-asr-rs This page Listed

Pure Rust implementation of Qwen3 ASR (Automatic Speech Recognition) with libtorch and MLX backends

21 downloads over 30 days 0 254 0.2.0 CUDA Binds native code: torch-sys (feature tch-backend). Build uses a native toolchain: cmake Apache-2.0
sherpa-onnx Featured

Safe Rust wrapper for sherpa-onnx speech recognition toolkit

259,599 downloads over 30 days 28 15,834 2.0.1 GPU support unknown Binds native code: sherpa-onnx, sherpa-onnx-sys Apache-2.0
any-tts Listed

A Rust TTS library with Candle backends and runtime adapters for modern open TTS models

3,404 downloads over 30 days 2 23 0.2.0 CUDA, Metal No native code found Apache-2.0 OR MIT
qwen3_tts_rs App Listed

A Rust implementation of the Qwen3 Text-to-Speech (TTS) model inference.

204 binary downloads per release Not applicable 237 Not measured Not measured None stated
whisrs App Listed

Voice for the Linux desktop: dictation, read-aloud (TTS), and voice-driven LLM commands, with Groq, OpenAI, Deepgram, and local Whisper backends

61 binary downloads per release Not applicable 149 0.2.0 CUDA, Vulkan Binds native code: alsa-sys, mac-notification-sys, wayland-sys (feature overlay), whisper-rs-sys (feature local-whisper) MIT

Rust implementation for the CohereLabs/cohere-transcribe-03-2026 speech-to-text model. Includes a CLI and an OpenAI-compatible API server.

0 downloads over 30 days 0 101 0.1.1 CUDA Binds native code: torch-sys (feature tch-backend). Build uses a native toolchain: cmake Apache-2.0
voxr New

Audio and speech on boostr: compressed-audio decode, resampling, DSP and grapheme to phoneme, with speech synthesis (Kokoro, VITS), voice cloning (VoxCPM2), transcription with word timings (Whisper), voice activity (Silero) and audio-text scoring (CLAP), on CPU or CUDA.

642 downloads over 30 days 2 2 0.9.1 CUDA No native code found Apache-2.0
Why ListedNo archive, New or Featured rule places it, so it is Listed.

What it lacks for Featured

  • It has 0 active dependents and 0 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 254 stars, 26 forks and 1 contributor. It needs 4,539 stars, 434 forks and 79 contributors together.

What else the check found

  • The last activity is on 28 Mar 2026, 226 days ago. The rules expect an update within 365 days. Dormancy rule

Check notes

  • the latest release was packaged from a dirty working tree

Exact rules: Listed, Featured library. The check on applied thresholds version 9.

Every rule outcome, as the check records it
  • expected-interval: version 0.2.0 base 80, capped at 1 releases = 50, raised to the 365-day floor: E = 365 days
  • dormancy: last activity 2026-03-28, 226 days ago, E = 365: active
  • featured: not featured: active_users 0 < 11 and new_adopters 0 < 9 and repository route stars 254 (needs 4539), forks 26 (needs 434), contributors 1 (needs 79)
  • listed: listed: no archive, new or featured rule applies

Measurements and sources

Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.

Sources6 sources
Adoption0 active dependents, 0 new dependents in 365 days1 not measured
Adoption measurements
SignalValueSourceFetchedCounts
Active dependents0crates.io database dumpYes
New dependents (365 days)0crates.io database dumpYes
Peak active dependents0crates.io database dumpYes
Active dependents as a share of the peak1crates.io database dumpYes
Binary downloads per releaseNot measuredYes
MaintenanceLatest human commit: 7 months ago3 not measured
Maintenance measurements
SignalValueSourceFetchedCounts
Latest human commit2026-03-28GitHub repositoryYes
Latest release2026-03-28crates.io database dumpYes
First release2026-03-28crates.io database dumpYes
Latest version0.2.0crates.io database dumpYes
Days the oldest outside issue waits for a reply227GitHub repositoryYes
Maintainer replies over 365 days3GitHub repositoryYes
Repository archivedfalseGitHub repositoryYes
Repository gonefalseGitHub repositoryYes
Release commit or manifest in the repotruecrates.io packageYes
Published docstruecrates.io database dumpYes
Latest release fails cargo checkNot measuredYes
Build check dateNot measuredYes
Build check toolchainNot measuredYes
SecurityUnpatched vulnerabilities: none
Security measurements
SignalValueSourceFetchedCounts
Unpatched vulnerabilities past the grace windownoneRustSec advisory databaseYes
RustSec unmaintained advisorynoneRustSec advisory databaseYes
Deprecation noticenonecrates.io database dumpYes
Deprecated requirementnonecrates.io database dumpYes
Distribution1 releases, 21 downloads over 30 days5 not measured
Distribution measurements
SignalValueSourceFetchedCounts
Releases1crates.io database dumpYes
Downloads over 30 days21crates.io database dumpYes
Binary downloads over the last 3 releasesNot measuredYes
Homebrew installs on request over 365 daysNot measuredYes
Repology repository familiesNot measuredYes
Docker pull growth over 90 daysNot measuredYes
Docker pulls at the growth baselineNot measuredYes
Every version a prereleasefalsecrates.io database dumpYes
Every version 0.0.xfalsecrates.io database dumpYes
Every version yankedfalsecrates.io database dumpYes
Crate deleted from crates.iofalsecrates.io database dumpYes
Repository254 stars, 26 forks, 1 contributors, 72 commits. Stars alone never qualify a project.
Repository measurements
SignalValueSourceFetchedCounts
GitHub stars254GitHub repositoryYes — one part of the repository route
GitHub forks26GitHub repositoryYes — one part of the repository route
Contributors with a GitHub account1GitHub contributorsYes — one part of the repository route
Commits on the default branch72GitHub repositoryNo
Repository's main crate left out of the entrynonecrates.io database dumpYes
Facts that never count
Facts that never count measurements
SignalValueSourceFetchedCounts
LicenseApache-2.0crates.io database dumpNo
Runs on, from listed crates and their direct dependenciesCUDAcrates.io database dumpNo
What shows each backendCUDA: qwen3-asr-rs feature tch-backend (dependency tch)crates.io database dumpNo
Native code, from listed crates and their dependenciesBinds native code: torch-sys (feature tch-backend). Build uses a native toolchain: cmakecrates.io database dumpNo
Python bindings, from direct dependencies of listed cratesNo Python binding crate foundcrates.io database dumpNo
Crates that depend on a listed crate directly0crates.io database dumpNo

Corrections and review history

Report a correction

No correction applies to this entry.

Judgments

A judgment enters only through an approved issue and a merged pull request.

No judgment applies to this entry.