Skip to content

Forced alignment for Parakeet + multilingual CTC map - #65

Closed
wassgha wants to merge 7 commits into
mainfrom
cursor/forced-align-parakeet-multilingual-bb72
Closed

wassgha wants to merge 7 commits into
mainfrom
cursor/forced-align-parakeet-multilingual-bb72

Conversation

@wassgha

@wassgha wassgha commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Extends the forced-alignment work from #61 with two follow-ups:

  1. Parakeet — same post-ASR timing pass as Whisper (VAD/envelope → CTC force-align → expand → disfluencies).
  2. Multilingual — language-gated CTC model map instead of always downloading English wav2vec2.

Align model map

Language Model Notes
en Xenova/wav2vec2-base-960h (~86 MB q4) unchanged
es / fr / de onnx-community/mms-300m-1130-forced-aligner-ONNX (~240 MB q4) shared; accents folded to ASCII
zh onnx-community/wav2vec2-large-xlsr-53-chinese-zh-cn-ONNX (~240 MB q4) Han + Latin vocab

Languages without a model (none currently in the supported set) keep the heuristic-only path. Aligners only warm/download for the active transcript language.

Also

  • Shared refineWordTimestamps() used by Whisper and Parakeet
  • normalizeForCtc supports latin-upper / latin-lower / cjk
  • Delimiter id read from the tokenizer (| when present; MMS has none)
  • Unit tests for the model map and multilingual normalisation

Built on top of fix-alignment-forced (#61).

Open in Web Open in Cursor 

wassgha and others added 7 commits August 2, 2026 11:09
# Conflicts:
#	workers/transcription.worker.ts
The CTC aligner loaded itself with bare from_pretrained calls, so its 86 MB
download happened behind a static "Aligning words…" with no bar — indistinguishable
from a hang on a cold cache.

Register it in the existing ModelManager instead, so it shares the download
progress, cache labeling and unload-on-GPU-loss path with the ASR models. It
needs the processor, model and tokenizer separately rather than a pipeline(),
so it is a plain ModelDefinition wired to transformersProgress rather than
transformersModel().

The aligner warms in the background while Whisper runs, so its bytes must not
fight the "Transcribing…" line: speech models always own the progress line, and
the aligner only claims it once transcription is done and we are actually
waiting on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	workers/transcription.worker.ts
wav2vec2 is not in the same family as the ASR models — it is an acoustic
aligner, not a transcriber, and not something the user picks. But the deciding
factor is lifecycle, not taxonomy.

The ASR registry exists under a WebGPU→WASM fallback policy whose recovery step
is unloadAll(). The aligner never asks for a device, so transformers.js runs it
on WASM (DEFAULT_DEVICE), where a lost GPU cannot touch it. Sharing the registry
meant a GPU loss threw away 86 MB of perfectly good weights and forced a
needless session rebuild.

Splitting also removes the id special-casing the shared registry forced into the
progress subscription. The ASR handler goes back to "whatever is loading", and
the aligner's own subscription is scoped to the await in forceAlign — the
subscription's lifetime is the gate, so there is no module-level flag left to
fall out of step if that path is ever re-entered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
subscribe() only fires on the next change, so a load that had started but not
yet received its first byte left the UI on the previous message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Share the VAD → CTC → expand post-pass between Whisper and Parakeet, and
pick a language-specific aligner (English wav2vec2, MMS for es/fr/de, XLS-R
for zh) so non-English runs no longer warm an English-only model.

Co-authored-by: Wassim Gharbi <wassgha@gmail.com>
@wassgha wassgha closed this Aug 6, 2026
wassgha added a commit that referenced this pull request Aug 6, 2026
CTC forced alignment for word timings (supersedes #61, #65)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants