How qwenlm/qwen3-asr-toolkit works
1. This repository is a small multi-language toolkit centered on one pipeline: take long audio/video, split it into transcribable chunks, send those chunks to the Qwen-ASR service, then stitch the results back together. The Python package is the primary product; the Java directory is a standalone reference implementation of the same idea.
2. The Python code is organized into three main subsystems:
- qwen3asr.py: the CLI/orchestration layer
- audio_tools.py: media loading, conversion, chunking, and subtitle-related helpers
- call_api.py: the DashScope/Qwen-ASR request boundary
This separation maps cleanly to the architecture: input preparation, remote inference, and result handling.
3. The main data flow starts with an input media source that can be either a local file or a remote URL. The tool normalizes that source into audio suitable for the API, then uses voice activity detection to find natural breakpoints instead of cutting blindly by time.
4. Media preprocessing is a key boundary in this repo. The README indicates FFmpeg is used to accept many input formats and resample them into the 16 kHz mono format expected by the ASR API. Temporary chunk files are stored under a configurable cache directory, which makes the preprocessing stage explicit and separable from the transcription stage.
5. Chunking is controlled by VAD and a target segment duration. The design goal is to keep chunks under the API’s 3-minute limit while avoiding mid-sentence cuts. This means the splitter is not just a file splitter; it is a semantic boundary detector that tries to preserve speech continuity.
6. API interaction is isolated behind the call_api.py layer. That layer is the external-service boundary to Alibaba Cloud DashScope, authenticated via DASHSCOPE_API_KEY or a CLI argument. The repository does not embed a model locally in Python; it depends on the hosted Qwen-ASR service for transcription.
7. Long-form throughput is improved by parallelism. The toolkit submits chunk requests concurrently using multiple threads, then reorders and aggregates the returned text segments. In architectural terms, transcription is a fan-out/fan-in stage: split into chunks, dispatch in parallel, collect in order.
8. After transcription, the tool performs cleanup/post-processing on the assembled text. The README calls out removal of hallucinations and repetitive artifacts, so the final output stage is not a raw API passthrough; it is a normalization step that improves readability before writing the transcript.
9. Output generation is file-oriented. The final transcript is printed to the terminal and saved as a .txt file next to the source media. If enabled, an .srt subtitle file is generated from the same segmented timing information, so subtitle creation is a secondary output derived from the VAD/chunk timeline.
10. The package boundary is straightforward: install via pip, then invoke the qwen3-asr command. Python 3.8+, FFmpeg, and the DashScope API key are the main runtime dependencies that materially affect architecture.
11. The Java example in examples/java-example mirrors the same pipeline in another runtime. App.java appears to be the entry point, AudioSplitter.java handles chunking, SlieroVadDetector.java and SlieroVadOnnxModel.java wrap VAD inference, and utils/Result.java / utils/Util.java support orchestration. This example includes an embedded silero_vad.onnx, so unlike the Python path it demonstrates local ONNX-based VAD integration.
12. From an architecture-diagram perspective, the important boundaries are: media input, audio normalization/VAD splitting, parallel remote ASR calls, post-processing/ordering, and output files. The Python package is the production flow; the Java example is a parallel reference implementation of the same control flow.
Main entry points: audio_tools.py Audio tools · App.java App · qwen3asr.py qwen3asr · AudioSplitter.java Audio splitter
Components 18
Python toolkit
Primary production pipeline exposed as a CLI package.
- Media source · Local file or remote URL provided by the user.
- qwen3asr · Command entrypoint that drives the end-to-end workflow.
qwen3_asr_toolkit/qwen3asr.py - Audio tools · Load, convert, split, and prepare audio plus subtitle timing.
qwen3_asr_toolkit/audio_tools.py - ASR client · Boundary for authenticated Qwen-ASR requests.
qwen3_asr_toolkit/call_api.py - VAD splitter · Finds speech-aware breakpoints and keeps chunks within API limits.
- FFmpeg · Converts diverse inputs into 16 kHz mono audio.
- Chunk cache · Configurable directory for temporary processed chunks.
- Parallel jobs · Submits chunk requests concurrently.
- Merge results · Reorders returned segments and stitches them into one transcript.
- Cleanup text · Removes repetitive artifacts and improves readability.
- Transcript file · Final text written next to the source media.
- Subtitle file · Optional subtitle output derived from segment timing.
Java example
Standalone reference implementation of the same transcription flow.
- App · Reference entrypoint for the Java pipeline.
examples/java-example/src/main/java/org/example/App.java - Audio splitter · Splits media into transcription-sized chunks.
examples/java-example/src/main/java/org/example/AudioSplitter.java - VAD detector · Runs speech activity detection for natural chunk boundaries.
examples/java-example/src/main/java/org/example/SlieroVadDetector.java - ONNX model · Embedded Silero VAD model used by the Java example.
examples/java-example/src/main/resources/silero_vad.onnx - Result utils · Supports orchestration and transcript aggregation.
examples/java-example/src/main/java/org/example/utils/Result.java - Util helpers · Shared helper functions for the Java example.
examples/java-example/src/main/java/org/example/utils/Util.java
Connections 18
- Media source → qwen3asr: start · User provides media to the CLI.
- qwen3asr → Audio tools: prepare · Coordinates media normalization and chunk preparation.
- Audio tools → FFmpeg: convert · Uses FFmpeg to decode and resample input media.
- Audio tools → VAD splitter: split · Delegates speech-aware chunking to VAD-based segmentation.
- VAD splitter → Chunk cache: store chunks · Writes temporary chunk files for later transcription.
- qwen3asr → ASR client: transcribe · Sends prepared chunks to the remote ASR boundary.
- ASR client → Parallel jobs: fan-out · Chunk requests are issued concurrently.
- Parallel jobs → Merge results: fan-in · Collected responses are reordered and merged.
- Merge results → Cleanup text: clean · Assembled transcript is post-processed for readability.
- Cleanup text → Transcript file: write · Final transcript is printed and saved as text.
- Merge results → Subtitle file: subtitle · Segment timing can be rendered into subtitles.
- App → Audio splitter: orchestrate · Java entrypoint drives the same chunking flow.
- Audio splitter → VAD detector: detect speech · Chunking is guided by VAD output.
- VAD detector → ONNX model: run model · Loads the embedded Silero VAD ONNX model.
- App → Result utils: collect · Uses helper types for aggregation and control flow.
- App → Util helpers: support · Uses shared Java utility functions.
- Audio splitter → Result utils: emit chunks · Produces chunk metadata for downstream handling.
- Audio tools → Subtitle file: timing data · Provides segment timing used for subtitle generation.