Skip to main content
VoxWeave

VoxWeave

BGM-robust subtitles for anime, film, and clips.

Vocal separation and song-skip so ASR never hallucinates on background music, OP/ED, or insert songs. Local-first Qwen3 ASR, word-level forced alignment, speaker labels, and edit-and-resync — CJK-aware.

CI PyPI License: MIT Python 3.11+ CUDA cu128 Apple Silicon MLX Buy Me A Coffee

https://github.com/user-attachments/assets/e75b6dd3-fa37-4afe-89db-b6ee2c28f6bc

Sliced clip under heavy BGM · voxweave Test.mp4 · Qwen3-ASR-1.7B

VoxWeave derives from the WhisperX "edit-and-resync" workflow: transcribe once, then edit the text and re-align it against the original audio for word-level timestamps. Where it differs is the front end — vocal separation and song-skip keep background music out of the ASR, and a CJK-aware layout/alignment stack (MMS-300m for Japanese, BudouX/jieba for line breaks) handles Chinese/Japanese/English as first-class.

Why VoxWeave

  • BGM removal before ASR. A Mel-Band Roformer vocal separator (pure torch, full-band 44.1k) strips music first, so ASR doesn't transcribe lyrics or hallucinate on score.
  • Song-skip. PANNs detects singing/music on the separated vocals and skips OP/ED and insert songs before ASR — on by default, --no-skip-songs to keep them.
  • Local Qwen3 ASR + forced alignment. Text and word-level timestamps in one pass, fully on-device — in-process PyTorch on NVIDIA, or the native MLX Qwen3 models on Apple Silicon. A Whisper hybrid engine is also available for when you prefer Whisper text (faster-whisper on NVIDIA, the native MLX Whisper port on Apple Silicon).
  • Word-level timestamps. Each word gets its own start and end from CTC forced alignment against the audio (MMS-300m for Japanese, wav2vec2 for English, Qwen3-ForcedAligner for Chinese), not from ASR segment times. Cue edges then snap to shot changes under Netflix timing rules.
  • Speaker labels. --diarize splits cues at speaker changes and sets short two-person exchanges as Netflix -line pairs. voxweave speakers serve opens a page where you audition each speaker, name them, and split two people that were merged. Enrolled voices go into one library, so names carry over to later episodes. Opt-in; needs a Hugging Face token for the gated pyannote model (see Setup).
  • Edit-and-resync. Fix the transcript by hand, then align re-derives timestamps from the audio — timestamps are never hand-written.
  • CJK-aware. Japanese aligns with MMS-300m + uroman (zero-OOV, immune to the per-cue drift that breaks wav2vec2-xlsr on rare kanji); line breaks use BudouX phrase atoms + jieba.
  • Optional LLM steps. correct cleans up ASR typos/garbled names before alignment; translate does whole-episode context-aware translation while preserving cue count (dual-speaker -line/-line cues are translated one speaker at a time and re-assembled).
  • Ship the result. pack soft-muxes finished VTTs into the media as titled subtitle tracks (instant stream copy); burn hardcodes them at constant quality with NVENC / VideoToolbox acceleration, matching the source bit depth.

Pipeline at a glance

Media goes through vocal separation, song-skip, VAD chunking, ASR, forced alignment and cue splitting into a VTT and JSON pair; speaker diarization is an optional branch that splits cues at speaker changes

Fig. 1. Processing pipeline. Solid lines carry the audio and text; the dashed box and lines are the optional --diarize branch. Every stage runs locally; see How it works.

Install

# NVIDIA / Linux
uv tool install --torch-backend=cu128 \
  --overrides <(printf "onnxruntime; sys_platform == 'darwin'\n") \
  "voxweave[cuda]"
# Apple Silicon / macOS
uv tool install "voxweave[mps]"

From a clone, make install does the same and picks the variant, the torch build and the overrides for you (make reinstall after pulling new code).

Both variants need ffmpeg on PATH. The default pipeline fits in about 8 GB of VRAM. --diarize also needs a Hugging Face token for a gated model; see Speaker models. Everything else about installing (variants, CUDA notes, overrides, dependencies) is in Setup.

Quickstart

# Transcribe a video to a timestamped VTT (+ a JSON source of truth)
voxweave episode.mkv

# Opt in to speaker diarization (requires gated-model access; see Setup)
voxweave interview.mkv --diarize

# Stay on the older 3.1 pipeline if that is the gate you have accepted
voxweave interview.mkv --diarize --diarize-model 3.1

# ...edit episode.vtt by hand (fix wording, line breaks)...

# Re-align the edited text against the original audio
voxweave align episode.vtt

# Optionally translate the aligned subtitles to Chinese
voxweave translate episode.vtt --target zh

Recipes

A meeting or interview recording, with named speakers in the subtitles. Audio files work as well as video. When the background is clean, --no-separate skips the vocal separator. Bound the speaker count if you know it: --max-speakers is the best lever against one person being split into two (see Transcribe).

voxweave meeting.m4a --no-separate --diarize --max-speakers 4

# Listen to each speaker, type a name, press Save.
voxweave speakers serve meeting.m4a

Diarize the recording, serve the speaker page, name each speaker and press Save to re-render the VTT with voice tags; optionally enroll the names into the voice library so the next recording suggests them

Fig. 2. Naming speakers. Each Save re-renders the VTT; the dashed boxes are the optional voice library, which suggests the names again in later recordings.

Each Save re-renders meeting.vtt with the names as <v Name> voice tags. If two people share one speaker card, use Split this speaker; it needs --voiceprints on the first run (see Label speakers).

A recurring group (a weekly meeting, a show with a fixed cast). Name people once, and later recordings suggest the names:

voxweave week1.m4a --no-separate --diarize --voiceprints
voxweave speakers serve week1.m4a      # name and Save
voxweave speakers enroll week1.m4a     # store the names in the voice library

voxweave week2.m4a --no-separate --diarize --voiceprints
voxweave speakers serve week2.m4a      # names are suggested; check them, then Save

Anime or film with music. The default pipeline separates vocals and skips OP/ED and insert songs, so no flags are needed:

voxweave episode.mkv
voxweave episode.mkv --diarize         # add speaker labels

Fix the text, keep the timing. Edit episode.vtt by hand, then re-align:

voxweave align episode.vtt

Ship the result:

voxweave translate episode.vtt --target zh
voxweave pack episode.zh.vtt           # soft track, stream copy
voxweave burn episode.zh.vtt           # hard subtitles

Commands

Command What it does
voxweave <media> Transcribe: separate vocals, skip songs, ASR, align, split into cues. Writes <stem>.vtt and <stem>.json.
voxweave speakers serve <media> Open the page where you name the speakers; each Save re-renders the VTT.
voxweave speakers enroll <media> Store the named voices in the shared voice library.
voxweave align <vtt> Re-derive timestamps from the audio after you edit the text.
voxweave render <media> Re-split cues from the saved JSON, without any model.
voxweave correct <vtt> Optional LLM pass that fixes obvious ASR errors before alignment.
voxweave translate <subtitle> --target zh Whole-episode translation; the cue count stays the same.
voxweave export <subtitle> --to srt Convert between VTT, SRT and ASS.
voxweave pack <subtitle> / voxweave burn <subtitle> Add subtitles to the media as tracks, or burn them into the picture.

Options and details: Commands.

Documentation

Page Covers
Setup Install variants, CUDA and Apple Silicon notes, dependencies
Commands Every command with its options
Speakers Diarization models, voiceprints, the speaker page, the voice library
How it works The edit-and-resync workflow and the pipeline stages
Configuration voxweave.conf, environment variables, performance knobs
Data contract Files written next to the media, JSON schema, tests
Migration notes Changes between releases

Support

If VoxWeave saves you time, you can support development here:

Buy Me A Coffee

License

MIT — see LICENSE.

Acknowledgments

Metadata

Release files for voxweave 0.19.0

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

Source distribution (sdist)

Source distribution for voxweave 0.19.0
File Size Uploaded Provenance Actions
voxweave-0.19.0.tar.gz 869.3 kB Without provenance Details for voxweave-0.19.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for voxweave 0.19.0
File Interpreter ABI Platform Actions
voxweave-0.19.0-py3-none-any.whl Python 3 none any Details for voxweave-0.19.0-py3-none-any.whl

Total release size: 1.8 MB

Release files / voxweave-0.19.0.tar.gz

Download URL voxweave-0.19.0.tar.gz
Size 869.3 kB
Tags Source
SHA-256 checksum
How to use checksums
1b9778acfe2c47dcf177acb2a5c1af386d04a8339b4d03a589da0fa983cec70c
BLAKE2b-256 checksum
How to use checksums
c69b9d76c5b3ac55324ae830a2d3814c4d6d59f60690b67aca591fafa672271a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / voxweave-0.19.0-py3-none-any.whl

Download URL voxweave-0.19.0-py3-none-any.whl
Size 947.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
450e2627528f049ff3c25c63a95fe5d2c26529e594f2c3b0c6ad0842224deda1
BLAKE2b-256 checksum
How to use checksums
0a25bf07e06f578c04ebaa3f096ff3297dc2c8eb10c646d7c1f6a8b862853f73
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for voxweave 0.19.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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