Skip to main content

qwen-aligner-toolkit

Production toolkit around Qwen3-ForcedAligner: VAD pre-segmentation, multi-language word/char-level forced alignment, and speaker diarization.

Why

qwen-asr ships an excellent forced aligner (Qwen3-ForcedAligner-0.6B) that handles multiple languages with one model — no per-language wav2vec2 needed, no kanji vocab gaps. This toolkit packages it with the surrounding pieces you typically need in production:

  • VAD (pyannote/segmentation-3.0) to chunk long audio
  • Diarization (pyannote/speaker-diarization-community-1) with per-word speaker assignment and run smoothing
  • Audio utilities (path / URL / bytes / np.ndarray → 16 kHz mono)
  • AVX-less CPU compatibility via a nagisa char-level stub

The toolkit does not do ASR. Bring your own transcript (from Whisper via vLLM, faster-whisper, qwen-asr itself, or any other system) and the toolkit will time-align it and label speakers.

Install

pip install qwen-aligner-toolkit
pip install qwen-aligner-toolkit[full]    # with VAD + diarization

Usage

Simple alignment (short audio)

from qwen_aligner_toolkit import Aligner

aligner = Aligner.from_pretrained()
words = aligner.align(
    text="甚至出现交易几乎停滞的情况。",
    audio="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-ASR-Repo/asr_zh.wav",
    language="Chinese",
)
for w in words:
    print(w.start_time, w.end_time, w.text)

ASR segments → word-level + speakers

from qwen_aligner_toolkit import Pipeline

pipeline = Pipeline.from_pretrained(hf_token="hf_...", device="cuda")

segments = [
    {"text": "おはようございます。", "start": 0.0, "end": 2.3},
    {"text": "今日は良い天気ですね。", "start": 2.3, "end": 5.1},
]

result = pipeline.align_segments(
    segments=segments,
    audio="audio.wav",
    language="Japanese",
    diarize=True,
)

for w in result.words:
    print(f"{w.start_time:.2f}-{w.end_time:.2f} [{w.speaker}] {w.text}")

VAD only

from qwen_aligner_toolkit import VAD

vad = VAD.from_pretrained(hf_token="hf_...")
chunks = vad.detect("audio.wav")

Sharing the segmentation model between VAD and Diarizer

pyannote/speaker-diarization-community-1 already loads a copy of pyannote/segmentation-3.0 internally. To avoid loading it twice when you also need standalone VAD, build the VAD on top of the diarizer's segmentation submodel:

from qwen_aligner_toolkit import Diarizer, VAD

diarizer = Diarizer.from_pretrained(hf_token="hf_...")
vad = VAD.from_segmentation_model(diarizer.segmentation_model)
chunks = vad.detect("audio.wav")

Per-speaker grouped output

If you want speaker turns with joined text (one entry per consecutive same-speaker run, with short-run smoothing), call Diarizer.split_words_by_speaker on word-level dicts:

from qwen_aligner_toolkit import Diarizer

words = [
    {"word": "hi",  "start": 0.0, "end": 1.0, "speaker": "A"},
    {"word": "yes", "start": 1.0, "end": 2.0, "speaker": "B"},
]
turns = Diarizer.split_words_by_speaker(words, min_duration_sec=0.3)
# [{"text": "hi", "start_time": 0.0, "end_time": 1.0, "speaker": "A"},
#  {"text": "yes", "start_time": 1.0, "end_time": 2.0, "speaker": "B"}]

For CJK languages where you don't want a space between concatenated tokens, pass join_separator="". The dict keys are configurable via word_key / start_key / end_key / speaker_key.

Configuration knobs

The toolkit has no global config — every knob is a function parameter. The table below maps common production env-var conventions to the corresponding toolkit argument, so you can wire them up with one-line plumbing.

VAD

Env var Default Toolkit argument
ASR_VAD_ONSET 0.5 VAD.detect(onset=...)
ASR_VAD_OFFSET 0.5 VAD.detect(offset=...)
ASR_VAD_MIN_DURATION_ON 0.25 VAD.detect(min_duration_on=...)
ASR_VAD_MIN_DURATION_OFF 0.5 VAD.detect(min_duration_off=...)
ASR_VAD_MAX_CHUNK_SEC 30.0 merge_segments(max_chunk_sec=...) / Pipeline.vad_chunks(max_chunk_sec=...)
ASR_VAD_MAX_GAP_SEC 0.5 merge_segments(max_gap_sec=...)
ASR_VAD_PADDING_SEC 0.2 Aligner.align_segments(padding_sec=...)

Diarization

Env var Default Toolkit argument
HF_TOKEN — Diarizer.from_pretrained(hf_token=...)
ASR_DIARIZATION_MODEL pyannote/speaker-diarization-community-1 Diarizer.from_pretrained(model_id=...)
ASR_SPEAKER_MIN_DURATION_SEC 0.3 Diarizer.split_words_by_speaker(min_duration_sec=...)

Device / sample rate

Env var Default Toolkit argument
ASR_DEVICE cuda (or cpu if no GPU) Aligner.from_pretrained(device_map=...), Diarizer.from_pretrained(device=...), VAD.from_pretrained(device=...), Pipeline.from_pretrained(device=...)

All device= / device_map= arguments accept None to auto-detect (cuda if available, else cpu).

The toolkit operates internally at 16 kHz mono. Audio is auto-resampled on load; there is no target_sample_rate knob exposed at the public API.

Feature toggles

Flags like ASR_VAD_ENABLED or ASR_DIARIZATION_ENABLED belong to the orchestration layer of your application, not the toolkit. The toolkit exposes capabilities as separate classes (VAD, Diarizer) and the Pipeline constructor takes explicit with_vad= / with_diarization= flags:

Pipeline.from_pretrained(
    hf_token=HF_TOKEN if ASR_DIARIZATION_ENABLED else None,
    with_vad=ASR_VAD_ENABLED,
    with_diarization=ASR_DIARIZATION_ENABLED,
)

CPU compatibility (AVX requirement)

qwen-asr depends on nagisa, which ships DyNet38 compiled with AVX. On AVX-less CPUs (Intel Celeron G-series, some embedded SoCs), importing nagisa crashes with SIGILL.

If that affects you, install the char-level stub:

qwen-aligner-toolkit install-nagisa-stub
# or
python -m qwen_aligner_toolkit.compat install-stub

This downgrades Japanese tokenization from morpheme-level to character-level (other languages are unaffected). For forced alignment the difference is mostly cosmetic; speaker boundaries may even be detected at finer granularity.

For Docker:

RUN pip install qwen-aligner-toolkit && \
    qwen-aligner-toolkit install-nagisa-stub

License

Apache 2.0. See LICENSE.

Metadata

Release files for qwen-aligner-toolkit 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qwen-aligner-toolkit 0.1.3
File Size Uploaded
qwen_aligner_toolkit-0.1.3.tar.gz 19.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for qwen-aligner-toolkit 0.1.3
File Interpreter ABI Platform
qwen_aligner_toolkit-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 37.1 kB

Release files / qwen_aligner_toolkit-0.1.3.tar.gz

Download URL qwen_aligner_toolkit-0.1.3.tar.gz
Size 19.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c38461f25357341a62734714b5d426e1b90598255854fcbb31c0797c54c3cda3
BLAKE2b-256 checksum
How to use checksums
53ba30663714d9267fb69f7eb20a993d24314810a9411e7d968d27990886e6ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

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 28, 2026.

Transparency log

Release files / qwen_aligner_toolkit-0.1.3-py3-none-any.whl

Download URL qwen_aligner_toolkit-0.1.3-py3-none-any.whl
Size 17.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6bdbc971c0eb792b4512fbfa7dfb2e28a854518784b8e475a02e2ba7041f033
BLAKE2b-256 checksum
How to use checksums
dea9df397726df9156b450303dbaefc0678dd84b888531c869159a0740e22a50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

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 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.4

2 release files

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

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