Skip to content

Releases: CrispStrobe/CrispASR

v0.8.10 — MOSS-TTS-v1.5 + moss-diarize; #218 long-audio root-caused; TTS perf

Choose a tag to compare

@CrispStrobe CrispStrobe released this 13 Jul 08:56

CrispASR v0.8.10

Headline: the #218 long-audio arc root-caused and fixed (qwen3-asr / glm-asr now
match their Python blueprints; loop mitigation across all LLM backends), new
backends/models (MOSS-TTS-v1.5, canary-qwen, OmniVoice, Voxtral-TTS,
kyutai-stt-2.6b, bananamind-tts), raw CTC logits access across every language
binding, per-token streaming in the C ABI, a GPU graph-cache use-after-free
fix across 7 backends, a class of multi-model-in-one-process correctness bugs
fixed (a second model no longer reads the first's cached weights/vocab),
OmniVoice's silent-synthesis root cause fixed plus a TTS perf pass
(OmniVoice ~1.6-2×, qwen3-tts codec 3× on Metal), a generation-health regression
gate (empty/looping/trailing-silence output caught in CI), and a CUDA long-audio
speedup (qwen3-asr manual-attn default-on, 3.2×).

New backends / models

  • MOSS-TTS-v1.5 (#249) — OpenMOSS-Team/MOSS-TTS-v1.5 (MossTTSDelay): a
    Qwen3-8B backbone autoregressively emits 32 RVQ audio codebooks under a
    staggered delay pattern, decoded to 24 kHz by a 1.6B pure-transformer codec.
    Ported onto CrispASR's in-house Qwen3 runtime (no libllama) by grafting
    pwilkin/openmoss's codec + delay logic. New src/moss_tts.{h,cpp} (backbone
    • 32 embed/head aux graphs + delay state machine) and src/moss_tts_codec.{h,cpp}
      (weight-norm-reconstructed projections → 4 sliding-window ProjectedTransformer
      stages → 24 kHz). Voice cloning via --voice ref.wav (codec encoder +
      reference splice; validated by ASR + speaker-cosine roundtrip). GGUFs at
      cstr/moss-tts-v1.5-GGUF (Q4_K backbone + F16 codec). Validated on Kaggle
      P100: Q4_K decoded round-trip is intelligible + correct on the real 8B weights.
      Code-parity note: the greedy code stream is not byte-identical to the HF
      BF16 reference and is not expected to be — a fixed tokenizer bug made the prompt
      byte-identical, but the residual frame-0 divergence is a Q4_K near-tie argmax
      flip cascading through the AR loop (the reference's greedy pick is the runtime's
      rank-1 runner-up at a 0.135-logit gap), so the ASR round-trip is the acceptance
      gate, not exact codes.
  • moss-diarize (#242) — MOSS-Transcribe-Diarize-0.9B: transcription with
    speaker diarization (SRT with speaker labels). Registry auto-download,
    diff-harness reference backend, quantization rules.
  • bananamind-tts — added to the model registry (EN + DE auto-download).
  • canary-qwen (#233) — nvidia/canary-qwen-2.5b SALM: FastConformer
    encoder → Qwen3-1.7B decoder with merged LoRA. English ASR. GGUFs at
    cstr/canary-qwen-2.5b-GGUF (F16/Q8_0/Q4_K; Q8_0 registry default).
  • OmniVoice TTS (#234) — k2-fsa/OmniVoice: Qwen3-0.6B + SoundStorm-style
    masked-iterative 8-codebook generation with classifier-free guidance,
    HiggsAudioV2 codec decoder → 24 kHz PCM. Voice cloning, 600+ languages.
    GGUFs at cstr/omnivoice-GGUF.
  • Voxtral-TTS (#93) — Mistral Voxtral-based TTS end to end in ggml: LLM AR
    backbone → flow-matching ODE → codec decoder, proper Tekken
    pre-tokenization; multi-voice, EN+FR validated by ASR roundtrip.
  • kyutai-stt 2.6B (#238) — kyutai/stt-2.6b-en support in the kyutai-stt
    backend: model-scaled silence prefix/tail conditioning (2.6B has 3.5 s
    lookahead), registry auto-download, diff-harness reference backend.
  • cohere-transcribe-arabic (#231) — --backend cohere-ar shorthand wired
    into the factory (defaults -l ar), registry auto-download, GGUFs at
    cstr/cohere-transcribe-arabic-07-2026-GGUF.

#218 — long-audio repetition loops / empty output: mitigated AND root-caused

  • Mitigation everywhere: n-gram fix_loops applied to all LLM-decoder
    backends (incl. granite), mirrored into the session C-ABI; word-level dedup
    alongside the text collapse; long-run + phrase-repeat regression fixtures.
  • qwen3-asr root cause: the q4_k GGUFs quantized the audio tower below
    8-bit; compounding encoder drift flipped greedy decode into loops /
    "language none" on long clips. crispasr-quantize now floors qwen3-asr
    audio.* at Q8_0 (re-baked GGUFs live for 0.6b, 1.7b, ja-anime). Runtime
    half: forced language is now an assistant-turn prefill
    (language <Name><asr_text>, the blueprint contract — structurally prevents
    empty output), tail-pad frames dropped before the encoder, KV grows on
    demand (a fixed 4096 capped un-chunked audio at ~5 min), max_new fallback
    512. Un-chunked 145 s decodes clean with the loop-fix disabled.
  • glm-asr root cause: no quantization involved — the GGUF carried no BPE
    merges, so every plain-text instruction silently tokenized to nothing (the
    model never saw the mandatory "Please transcribe this audio into text"), and
    audio was truncated to one 30 s window. Now: real byte-level BPE (merges
    baked by the converter; tools/gguf-add-merges.py backfills — published
    GGUFs updated) and the blueprint multi-window prompt (up to 21×30 s = 655 s
    single-pass). q4_k matches the bf16 reference near-verbatim on the 145 s
    repro clip.
  • mega-asr: verified against its blueprint — the long-form degeneration
    reproduces in the bf16 LoRA-merged reference itself (base model clean), so
    it is model-inherent. --chunk-seconds 0 is unsupported for mega; the
    default 30 s-chunked path works as before.
  • Experimental: CRISP_AUDIO_WINDOWED_ATTN=1 — FA2-style block-diagonal
    windowed encoder attention for qwen3-asr, O(N·W) memory instead of O(N²).
    Opt-in escape hatch for >10-min single-pass audio (keep the loop fix on);
    evaluated and deliberately not the default.
  • Diagnostics: CRISPASR_NGRAM_LOOPFIX_OFF=1 raw-decode gate, qwen3
    stages in crispasr-diff, encoder-cosine quant audit tool
    (qwen3-asr-enc-dump), and a stderr warning when non-silent audio produces
    an empty transcript (#240).

Bindings / API

  • Raw CTC logits accessor across Python, Go, Ruby, Java, C#, Dart, and
    JavaScript bindings, plus a CTC vocabulary accessor for token→word
    detokenization — enables forced alignment on wav2vec2 / canary-ctc and the
    rest of the CTC set (community contribution by Michael J. Culbertson, #232).
  • Per-token streaming callback in the session C-ABI.
  • Dart: replace deprecated Pointer.elementAt; Go: cgo LDFLAGS sync.

Fixes

  • OmniVoice silent synthesis (#234): the C++ generation-config fallbacks
    didn't match the blueprint's OmniVoiceGenerationConfig (guidance scale,
    class/position temperature, layer-penalty and t-shift unmask schedule), so
    the masked-iterative decode degenerated into near-constant silence codes on
    every platform and precision — the codec then faithfully rendered silence.
    With blueprint defaults it produces real audio (whisper roundtrip verbatim).
  • Multi-model-in-one-process correctness (PR #244 + follow-ups): several
    backends cached per-model data in process-global, pointer-keyed maps that
    outlived the model. After freeing model A and loading model B, the allocator
    commonly hands back the same addresses, so B read A's data. Fixed by scoping
    each cache to its model: the wav2vec2 GPU dequant cache and pocket_tts F16
    cache (community contribution by Michael J. Culbertson), the greedy-tokenizer
    vocab maps in kugelaudio/vibevoice, and the voxcpm2 VAE-encode memo.
  • Per-session streaming buffers: the default segment/token callbacks (Dart
    FFI polling path) pushed into process-global buffers, so two sessions —
    concurrent or sequential — interleaved and drained each other's output.
    Scoped to the owning session (and capped so a non-draining consumer can't
    grow them without bound). The persistent CPU threadpool is now released when
    its backend is freed, instead of leaking worker threads per model.
  • canary-qwen instruction echo (#247): on a too-short audio window the SALM
    decoder echoed its task framing as a meta word ("Transcript", "Transcription",
    "PASS") instead of transcribing. Root-caused against the NeMo SALM reference:
    the FastConformer subsamples 8x, so a window with only a few encoder frames
    (T_enc<=5, ~<=0.4 s) gives the Qwen3 LLM decoder no acoustic content to ground
    on and it falls back to its language prior — NeMo emits the identical tokens
    ("Okay" on a 0.1 s clip, "Transcript" on a 0.3 s clip), so this is inherent to
    the model, not a port bug (the prompt is byte-identical to NeMo's, and full-
    utterance output matches exactly). Earlier theories (framing tokens; string
    stripping) did not fix it. Fixed in the pipeline: a degenerate-window gate
    returns empty for sub-gate windows, plus a backend-agnostic safety net that
    strips any leading instruction-echo token from both the text and the
    tokens array (the old workaround left the tokens array inconsistent — #218).
    Both paths are env-gated (CRISPASR_CANARY_QWEN_MIN_ENC_FRAMES,
    CRISPASR_CANARY_QWEN_NO_ECHO_STRIP) for A/B.
  • kugelaudio no-voice synthesis (#248): no voice packs were ever published
    upstream, so unconditioned synthesis produced noise. Implemented VibeVoice's
    zero-tensor neutral-speaker fallback (1-frame zero VAE latent through the
    acoustic connector) so it produces intelligible speech without a voice GGUF.
  • moonshine ran CPU-only from the CLI: the adapter never forwarded the
    --gpu preference, so every moonshine run (including the §232 "GPU"
    benchmarks) used the CPU backend. Now forwards it — encoder is 4-6× faster on
    Metal, transcript identical, --no-gpu still opts out. (moonshine-streaming
    and piper stay on CPU deliberately: their tiny per-frame graphs are
    launch-bound and measurably slower on GPU.)
  • f5-tts was broken and CPU-only: the DiT transformer (the model's dominant
    compute) was hardcoded to run on the CPU backend regardless of --gpu, and a
    gallocr input-aliasing bug corrupted the RoPE positions from the first ODE
    step on — so synthesis produced degenerate audio on both backends (the prior
    "f5 CPU is a dud" state). Both fixed: the DiT now runs on ...
Read more

CrispASR v0.8.9

Choose a tag to compare

@CrispStrobe CrispStrobe released this 08 Jul 09:04

CrispASR v0.8.9

138 commits since v0.8.8. Headline: a new Japanese TTS backend with real
zero-shot voice cloning, TTS output streaming everywhere, on-device browser
(WASM) TTS, MP3/AAC output, a shared reference-conditioning cache, ggml moved to
a shared submodule, and a broad ASR/TTS performance pass.

New backend — Irodori-TTS (Japanese, 48 kHz)

RF-DiT flow-matching TTS (500M) via the Semantic-DACVAE-Japanese-32dim codec,
integrated end to end:

  • Zero-shot voice cloning from any reference WAV — ported the DAC-VAE encoder
    (resample → −16 LUFS → latent) and wired the DiT speaker conditioning with
    speaker CFG. --voice ref.wav --i-have-rights. Validated ~91% of the
    reference implementation's speaker fidelity.
  • Emoji emotion control — the tokenizer now does SentencePiece byte_fallback
    (fixes a core_spm collapse where OOV multibyte input dropped to <unk>), so
    Irodori's emoji controls (whisper 👂, breath 😮‍💨, …) reach the model as the
    byte sequences it was trained on. C++ tokenization is byte-for-byte identical
    to the reference.
  • Duration predictor wired — output length comes from the model's predictor
    instead of a chars/sec heuristic that truncated kanji-heavy text.
  • Overlap-save chunked codec decode — bounds peak decode memory for long
    outputs, byte-identical to a whole decode (extracted a shared
    core_dac::decode_overlap_save driver, also wired into zonos).
  • GPU (Metal/CUDA) for the DiT/ODE + codec; codec-on-Vulkan validated clean on
    MoltenVK (CRISPASR_IRODORI_CODEC_GPU=1).
  • Codec companion auto-download (3-tier resolution).

TTS output streaming (CLI + C ABI + server)

  • --tts-stream — the CLI streams raw s16le mono PCM to stdout per sentence
    as it's synthesized (pipe straight into a player); logs stay on stderr.
  • crispasr_session_synthesize_streaming — new C ABI entry point that fires a
    callback per sentence chunk with watermarked PCM, for embedders/bindings.
  • The server already streamed per-sentence via /v1/audio/speech stream:true;
    this brings the same progressive delivery to the CLI and C ABI. See
    docs/streaming.md.

Reference-conditioning cache (all consumers)

Voice cloning encodes the reference into a small conditioning blob (a DAC-VAE
latent for irodori, Conformer/Perceiver + ECAPA for indextts). It's now cached
content-addressed on the reference audio, in the runtime — so every entry
point
(CLI, server, C ABI, language wrappers) skips the encode on a repeat
reference automatically, byte-identical to a fresh encode. On by default;
CRISPASR_TTS_REF_CACHE=0 disables, CRISPASR_TTS_REF_CACHE_DIR sets the
location. The helper (core/tts_ref_cache.h) is reusable by any runtime.

Browser / WebAssembly TTS

  • On-device TTS in the browserttsOpenExplicit, memory limits, and a
    multithreaded demo. PROXY_TO_PTHREAD build makes multithreaded browser TTS
    deadlock-free; a single-threaded build option avoids the COOP/COEP
    requirement. The WASM build (libwhisper.js/.wasm) is attached as a release
    asset.
  • ggml-webgpu: ported arange, pool2d, conv_transpose_2d ops.

Audio output formats

  • MP3 + AAC-LC output for TTS/S2S via an in-tree, vendored encoder core
    (glint) — --tts-output out.mp3 / out.aac, response_format=mp3|aac on the
    server. Auto-synced from CrispStrobe/glint.

Build / packaging

  • ggml de-vendored into a shared submodule (CrispStrobe/ggml) — smaller
    tree, shared with sibling projects. (Note for contributors: git submodule update --init ggml after checkout; git worktrees must init the submodule, not
    symlink it.)
  • Ruby extsources updated for the submodule; release attaches the WASM build.

Performance

  • FireRedASR — in-graph encoder attention by default (large-T guard),
    encoder-on-GPU default with use_gpu, and Q4_K beam-decode batching (~5.5×).
  • wav2vec2 — flash-style online-softmax CPU attention.
  • silero-LID — ggml-graph forward (3–6× faster, GPU offload, 30 s slice cap).
  • diarization — ggml-graph forwards for pyannote-seg + TitaNet.
  • pocket-tts — batched the eager Mimi encoder through ggml (43 s → 5.6 s per
    synthesis) + disk-cached voice-conditioning latents.
  • ecapa-LID — ASP + FC head in-graph (kills the 3 s scalar head off-Apple).

Fixes

  • indextts — cap over-long reference to the Conformer positional-encoding
    table (a 164 s reference aborted in ggml_view_2d); reference cache moved into
    the runtime.
  • VibeVoice — use-after-free when cached graphs share a scheduler (#171);
    --tts-cfg-scale knob; --context hotword/metadata injection.
  • VibeVoice-ASR — chunk the encoder to avoid CUDA int32 overflow on long
    audio.
  • cli-json — add ms offsets to full-JSON words/tokens (#228).
  • quantize — quantize irodori-tts MLP/attention weights.
  • Windows/MSVC portability fix for the reference-cache directory.

Docs

  • New Irodori-TTS + reference-conditioning-cache sections in docs/tts.md;
    streaming-out section in docs/streaming.md; --tts-stream in docs/cli.md;
    streaming + caching notes in docs/bindings.md.

v0.8.8 — Japanese long-form ASR (issue #89 close-out)

Choose a tag to compare

@CrispStrobe CrispStrobe released this 05 Jul 05:35

CrispASR v0.8.8

This release closes out issue #89 — Japanese long-form transcription with
parakeet-tdt-0.6b-ja no longer silently drops half the speech. Content
recall on the reporter's own clips goes from 56–64 % to 96–97 % (measured
against a whisper-large-v3-turbo reference with reading normalization), which
is the inter-model agreement ceiling — an independent SenseVoice run scores
the same recall on the same audio. It also picks up the MOSS-Transcribe
long-audio fixes (#218).

Japanese long-form ASR — issue #89 (parakeet-ja)

The JA FastConformer encoder is unstable past ~12 s of attention context on
real speech, and blanks whole utterances whenever enough context follows them
— upstream NeMo fails identically on the same audio (its plain,
local-attention, and buffered long-form modes score 1–51 % content recall on
the reference clip; our runtime is character-identical to NeMo in the
comparable modes). The new default pipeline works around the model:

  • VAD slice cap — VAD/energy slices are capped at 12 s and re-split at
    energy minima (never mid-word); each slice decodes in one NeMo-exact pass.
  • Gap-fill second pass — any span ≥ 1 s the first pass left empty inside
    a slice is re-transcribed in isolation and the recovered words merged back.
    CRISPASR_GAP_FILL=0 disables; CRISPASR_GAP_FILL_MIN_CS tunes.
  • Applied everywhere: CLI, session ABI (all language bindings), and
    the OpenAI-compatible server (/v1/audio/transcriptions) via a shared
    implementation.
  • Regression guard: new live test (test-parakeet-ja-longform) pins the
    behavior on a triple-length fixture through the session ABI.
  • New runtime gate CRISPASR_PARAKEET_ATT_CONTEXT="L,R" — the equivalent of
    NeMo's change_attention_model("rel_pos_local_attn"), verified
    char-identical to NeMo at [128,128].

Measured (phonetic char-bigram recall vs whisper-large-v3-turbo): 60 s clip
97.2 % (was 64.2 %), 120 s 96.9 % (was 61.3 %), 300 s 95.9 %;
precision 90–93 %. Verified on Metal and Vulkan (MoltenVK: 95.1 % on
the same clip — the reporter's backend class).

parakeet-ja GGUFs refreshed (cstr/parakeet-tdt-0.6b-ja-GGUF)

  • All files now include the hybrid model's CTC head
    --parakeet-decoder ctc works (earlier GGUFs lacked the tensors and fell
    back to TDT silently).
  • New q8_0 (TDT output byte-identical to F16 at half the size) — now the
    auto-download default for parakeet-ja.
  • q4_k guidance: TDT decode degrades to repetition loops at q4-class
    quantisation on this model (autoregressive decode compounds the quant
    noise; pre-existing) — but CTC decode over the same q4_k file is clean.
    The runtime now prints a load-time warning suggesting
    --parakeet-decoder ctc or the q8_0.

MOSS-Transcribe (#218)

  • Degenerate greedy n-gram repetition loops collapsed via the shared
    core_ngram::fix_loops pass.
  • Overlap-save disabled on long-audio slices for this backend (seam
    duplicates); long-audio path is 3.3× faster.

Tools

  • tools/asr_coverage_score.py — char-bigram recall/precision of ASR output
    vs a stronger-model reference; separates "silently drops speech" from plain
    WER. --strip-latin, --reading (kana/kanji-variant-erasing hiragana
    normalization), --per-line loss localization.
  • tools/nemo_parakeet_blueprint.py — run upstream NeMo's inference modes
    (plain / CTC / local attention / buffered) on a .nemo checkpoint to
    establish blueprint parity before hunting port bugs.

Docs

  • docs/cli.md — parakeet long-form section rewritten (JA pipeline, env-var
    table incl. CRISPASR_PARAKEET_VAD_SLICE_CAP, gap-fill knobs).
  • --align-only standalone CTC forced alignment documented (#217).
  • PERFORMANCE.md — final #89 coverage table; LEARNINGS.md — four
    transferable lessons from the #89 audit.

v0.8.7 — new backends (BananaMind-TTS, MOSS-Transcribe, M2M-100) + Granite decode up to 12x + imatrix quant + VibeVoice music-onset fix

Choose a tag to compare

@CrispStrobe CrispStrobe released this 04 Jul 06:35

CrispASR v0.8.7

This release adds two new backends (BananaMind-TTS-V2.1, MOSS-Transcribe-preview-2B ASR
and M2M-100 translation), a much faster Granite decode path (up to ~12× RTFx via
CUDA-graph capture, in-graph argmax, and fused embedding lookup), a full imatrix
quantization pipeline
(producer + consumer, IQ4_NL/XS, per-tensor overrides), and a large
batch of correctness fixes across TADA, MOSS/Vulkan, Granite long-audio, Parakeet, and
VibeVoice TTS
.

Highlights: the VibeVoice TTS quantized GGUFs no longer produce a spurious "music"/hum onset
(the diffusion prediction head is now kept at full precision), native-Vulkan segfaults on the
MOSS/MOSS-Audio encoders are fixed, and the Mimi codec now defaults to causal + sliding-window
masking (a measured WER/quality win).

New backends & models

  • BananaMind-TTS-V2.1 — new TTS backend (Tacotron-lite acoustic model + HiFi-GAN vocoder),
    wired end-to-end per docs/contributing.md (CLI, C-API, bindings, quantization, tests).
  • MOSS-Transcribe-preview-2B — new ASR backend (Qwen3-Omni encoder + Qwen3-1.7B LM).
  • M2M-100m2m100-f16 registered for exact HF translation parity.
  • Qwen3-ASR-1.7B-JA-Anime-Galgame — auto-download registry entry (#212); the Qwen3-ASR
    converter now accepts both -hf and non--hf model layouts.

Performance — Granite decode

  • CUDA-graph-capture bucketed decode — up to 6.4× faster on CUDA.
  • In-graph argmax — up to 12× RTFx, +32% on Q4_K.
  • Fused embedding lookup into the captured decode graph (F16); raw-gallocr
    allocate-once
    decode on non-capture backends (Metal).
  • Measured finding: the Metal ICB graph-replay path is a DUD (decode is GPU-bound); probe
    left in behind CRISPASR_METAL_PROFILE.

Quantization

  • imatrix (importance-matrix) pipeline — producer + consumer, activation-weighted k-quants,
    IQ4_NL / IQ4_XS, and re-quantization directly from an already-quantized GGUF.
  • --tensor-type <regex>=<type> per-tensor overrides, an A/B CER metric, and a
    published CC0 calibration set.
  • CRISPASR_QUANT_LMHEAD + aligner lm_head-at-F16 option (q8-everything aligner is
    bit-identical, #192).
  • VibeVoice diffusion-head carve-out (#171) — for any vibevoice-* arch the quantizer now
    keeps the diffusion prediction head (pred.*), connectors (at_conn.*, se_conn.*), EOS
    classifier (tts_eos.*) and speech-type table at source precision; only the Qwen2 backbone
    and the deterministic VAE decoder are quantized. This prevents quantization error in the
    CFG-driven diffusion head from compounding into a spurious non-speech "music"/hum onset
    before the voice. Overridable with CRISPASR_VIBEVOICE_QUANT_ALL=1; guarded by a regression
    test. The published vibevoice-realtime-0.5b, vibevoice-1.5b and vibevoice-7b GGUFs have
    been regenerated with this recipe — re-download to pick up the fix.

Mimi codec

  • Causal + sliding-window masking is now the default for kyutai_stt and csm_tts
    (Mimi decoder transformer) — a measured TTS→ASR / WER A/B win (e.g. csm_tts 9.3% vs 12.0%
    WER). Symmetric CRISPASR_MIMI_CAUSAL gate to A/B either direction.

Fixes

VibeVoice TTS (#171)

  • Voice-prompt KV per-head stride leak that corrupted the speaker prompt on server
    multi-request runs (1st/2nd request fine, later requests garbled).
  • The quantization carve-out above (music/hum onset).

MOSS / MOSS-Audio native Vulkan (#215)

  • Root-caused a segfault to a conv graph cached across slices (use-after-free) and to
    flash_attn_ext on the encoder; fixes drain the queue before vkResetCommandPool, use
    manual masked attention on the encoders, and restore GPU execution on native Vulkan.

TADA (#192 / #201)

  • Query-time inline .wav voice cloning and config-parity fixes; --make-ref reachable and
    fails loudly on unresolved --voice; --align forced-alignment word timestamps;
    auto-download of tada-encoder / tada-aligner; generation-loop parity fixes (fixed-step
    loop, candidate scoring, default candidates) so words are no longer truncated.

Granite long-audio & templates (#205)

  • Recovered dropped chunk-context slices and spaceless text rebuilds; byte-exact chat template
    (system turn); route the -plus model through the control-token template for real word
    timestamps; honour --max-len on text-only backends.

Parakeet long audio (#208)

  • Overlapping-window merge recovers dropped sections; bounded session long-audio encode and
    fixed a repeated-call encoder-cache collapse.

Other

  • VAD returns empty for silent audio instead of hallucinating (#213).
  • Respect --gpu-backend preference across all backends (#214).
  • Kokoro built-in G2P technical-token normalization (#216).
  • GLM-ASR / FireRed-ASR warn on unsupported -l instead of silently ignoring (#199).
  • PCS/aligner: dequantize FC-head weights (q4_k previously crashed on every inference).
  • Central f16→f16 GQA-REPEAT guard for all kv_self_attn callers on Vulkan (#200); dots-tts
    F32 KV read on Vulkan (#200).

Platform & bindings

  • Android: native Opus decoding enabled (#26); Media NDK made optional for Termux builds
    (#210); CUDA 13 build variant.
  • Windows: portable setenv/unsetenv shim for MSVC.
  • Go bindings: cgo LDFLAGS synced (adds -lbananamind-tts) so the static link and the
    drift check stay green.
  • All bindings: expose transcribe_chunked + long-form progress callbacks (#208).

v0.8.6 — dots.tts TTS + Higgs-STT / ARK-ASR / Japanese-CTC / Gemma-4 ASR + TADA query-time control

Choose a tag to compare

@CrispStrobe CrispStrobe released this 29 Jun 18:35

CrispASR v0.8.6

This release adds one new TTS backend and four new ASR/multimodal backends,
makes TADA fully controllable at query time, hardens the native-Vulkan TADA
path
, and adds consent-gated speaker identification to diarization — plus a
batch of GPU-stability, server, and build/CI fixes.


What's new

dots.tts — 2B continuous-AR TTS backend (#200)

A new text-to-speech backend for rednote-hilab/dots.tts, a 2B continuous
autoregressive TTS model (Llama-style LLM + flow-matching DiT + BigVGAN vocoder).

  • End-to-end synthesis"Hello world." and longer text round-trip to
    ASR-verbatim audio. The full pipeline is ported and validated against the
    PyTorch reference (DiT forward cos = 0.9999, LLM forward cos = 0.999).
  • CAM++ voice cloning — clone a speaker from a reference clip with --voice
    (encoder cos 0.9996 / global-cond 0.9999 vs reference).
  • Mixed-quant packaging — the DiT stays F16 while the LLM and PatchEncoder
    quantize to Q8/Q4_K (quantizing the DiT derails generation). Published as
    f16 / q8 (3.1 GB) / q4_k (2.3 GB) on
    cstr/dots-tts-soar-GGUF.
  • Incremental PatchEncoder — streaming O(N²)→O(N) patch encoding so long
    text reaches EOS in reasonable time (the earlier O(N³) recompute made long
    text too slow to terminate — it was never an EOS bug).
  • Metal GPU backend — single-backend raw-gallocr compute (no sched hazards),
    5.5× faster on long text, ASR-verbatim. Opt out with
    CRISPASR_DOTS_TTS_CPU=1. (CUDA path untested.)
  • Root-cause fix along the way: the LLM step was missing the attention scale
    (attn_scale=0 → uniform attention → garbage prefill).

Higgs-Audio v3 STT — Whisper-LV3 + Qwen3-1.7B ASR backend

A new ASR backend for bosonai/higgs-audio-v3-stt (Whisper-large-v3 encoder

  • Qwen3-1.7B decoder).
  • Chunked Whisper encoder — audio is encoded in independent 4 s chunks with
    chunk-local positions and concatenated, matching the upstream blueprint. (A
    single padded 30 s window let global attention over the silence-pad derail the
    decoder.) Transcribes JFK and a 45 s / 12-chunk clip verbatim vs the bf16
    reference at F16 / Q8 / Q4.
  • Custom prompt--ask "<prompt>" steers the decoder (e.g. translation or
    Q&A over the audio), with an -l <lang> / params.language hint.
  • CAP_UNBOUNDED_INPUT | CAP_INTERNAL_CHUNKING — the backend chunks long audio
    internally (no CLI window-split duplication).
  • Published on
    cstr/higgs-audio-v3-stt-GGUF.

ARK-ASR-3B — experimental Whisper-RoPE + Qwen2.5-3B ASR backend

A new experimental ASR backend (Whisper-large-v3 encoder with partial RoPE +
MLP adapter + stock Qwen2.5-3B decoder).

  • GPU by default (Metal-validated; opt out with CRISPASR_ARKASR_CPU=1).
  • Single-pass whole-audio decode — kills the language drift that came from
    our 30 s chunking (not the model). Capped by
    CRISPASR_ARKASR_MAX_SINGLE_PASS_S=300.
  • Optional language steering + a live test; diff-harness-validated
    (mel cos 0.999993, logits cos 0.999646).
  • Published as f16 / q8_0 / q4_k on
    cstr/ark-asr-3b-GGUF. Marked
    experimental/WIP.

Parakeet CTC 1.1B (Japanese) — FastConformer-CTC ASR backend

A new Japanese ASR backend for grider-transwithai/parakeet-ctc-1.1b-ja — a
42-layer FastConformer with a CTC decoder.

Gemma-4 E4B — multimodal ASR model variant (#196)

  • Added the gemma4-e4b model (same gemma4 architecture as E2B, larger
    decoder) to the registry, with a Kaggle conversion kernel and README. Published
    on cstr/gemma4-e4b-it-GGUF.
  • The 12B gemma4_unified variant is explicitly rejected by the converter with a
    clear message (not yet supported).

TADA TTS — query-time control + reliability (#197, #201)

  • Single-pass whole-text generation (#197) — TADA now generates the whole
    text in one pass like the upstream tada.py, instead of splitting on
    punctuation. Splitting an isolated "Hi." produced a 9.4 s pause + hum; the
    whole-text path removes the spurious pauses and hums.
  • Per-request flow-matching knobs (#197) — expose the acoustic FM controls at
    query time: num_fm_steps (accuracy vs speed), acoustic_cfg, and a new
    noise_temp. The talker sampler (top_k / do_sample /
    num_acoustic_candidates, temperature, rep-penalty) is now per-request and
    wired through every consumer (CLI, session ABI, server).
  • Switch voice per request without a restart (#201) — the HTTP/session path
    can change the voice reference between requests (chatterbox-style cached
    last-voice key); previously only a restart picked up a new voice.

Diarization — consent-gated speaker identification

  • New --diarize-speakers convenience alias (enables diarization with
    session-scoped speaker clustering → transient (speaker N) labels).
  • A named, persistent 1:N voiceprint database (--speaker-db /
    --enroll-speaker) is now off by default behind an explicit
    --speaker-db-consent flag (GDPR Art. 9 / biometric-data scoping). Session
    clustering needs no consent flag; only the persistent named DB does.

Server — diarized JSON output (#205, #206)

  • New diarized_json response format (#206) — structured per-segment speaker
    • text output over HTTP.
  • Fixed --max-len handling for the granite backend on the server (#205).

Bug fixes & hardening

Area Fix
TADA / Vulkan (#192) Native-Vulkan garbled/empty output was the codec, not the FM head — run the DAC codec on CPU when GPU = Vulkan (the codec graph miscomputes at length under MoltenVK; the talker/FM keep their native-Vulkan path). Gated CRISPASR_TADA_VULKAN_NATIVE=1, default CPU-fallback.
TADA / Vulkan (#192) Force F32 KV read on the native-Vulkan path to unblock the GQA REPEAT-f16 abort; direct-on-backend (gallocr) compute for the talker/FM graphs to avoid sched cross-backend corruption; cap codec expansion to prevent a runaway allocation.
TADA codec Dropped 805 MB of dead precomputed attention masks — the codec GGUF shrank from ~1055 MB to ~250 MB (byte-identical output); re-uploaded to cstr/tada-tts-{1b,3b-ml}-GGUF and updated registry size hints.
lfm2-audio (#199) GPU-safe embed + decode — fixes a CUDA ACCESS_VIOLATION crash.
dots.tts Vocoder compute-graph node budget sized for the 6×3 ResBlocks + MI-LSTM at 1024 frames; numerous PatchEncoder / DiT / KV-cache load + graph-size fixes during the port.
dots.tts (#200) Feed the whole text as a single chunk (no sentence-splitting) — removes the per-chunk repeated spoken-disclaimer and split artifacts.
dots.tts (#200) Fix a Metal residency-set teardown abort in the per-stage GPU diff harness (missing free_weights(rw) in 5 functions).
Build (#191) Robust link against system libopusfile; .opus support is now truly optional.
crispasr-sys (#203) build.rs auto-uses Ninja + ccache when available and passes --parallel to cmake --build.
CI Install hipBLAS / rocBLAS and set the ROCm prefix for HIP release builds.
CI Sync the Go cgo LDFLAGS for the new higgs-stt / dots-tts / ark-asr static libs (fixes the Go bindings link + the cgo-ldflags-drift check).
Static analysis Guard an all_times[i] index in the TADA decode expansion (cppcheck containerOutOfBounds).

Upgrading

No breaking changes to the C ABI, bindings, or CLI flags — all additions.

  • Diarization named speaker DB is now opt-in. Session-scoped clustering
    (--diarize / --diarize-speakers) is unchanged. The persistent named
    voiceprint database (--speaker-db / --enroll-speaker) now requires
    --speaker-db-consent; without it those flags are inert. This is a deliberate
    privacy default, not a regression.
  • TADA generates whole text in one pass by default (#197). If you relied on
    the previous punctuation-split behaviour, note that single-pass matches the
    upstream reference and removes spurious pauses/hums.
  • New per-request TADA knobs (num_fm_steps, acoustic_cfg, noise_temp,
    talker sampler) and per-request voice switching are additive; older bindings
    without the setters soft-no-op.

Full changelog

git log v0.8.5..v0.8.6 --oneline --no-merges

v0.8.5 — TADA multilingual TTS + ReazonSpeech JA ASR + CosyVoice3 GPU + C# bindings

Choose a tag to compare

@CrispStrobe CrispStrobe released this 27 Jun 19:29

CrispASR v0.8.5

This release makes TADA multilingual TTS production-ready, adds a new
Japanese RNNT ASR backend (ReazonSpeech), moves CosyVoice3 onto the GPU
with batched CFG, and ships C# bindings for the Session C ABI.


What's new

TADA TTS — multilingual, reliable, GPU-accelerated

The bulk of this release. TADA (Llama-3.2 backbone + per-token flow-matching
duration/acoustic head + TADA codec → 24 kHz) went from "English demo" to a
dependable multilingual TTS backend.

Reliable multilingual timing (num_acoustic_candidates)

  • TADA's per-token duration head is noise-sensitive: a single unlucky noise
    draw can collapse token durations into rushed, garbled speech (a property of
    the model — the PyTorch reference behaves identically with the same noise).
  • Ported the reference's num_acoustic_candidates ranking: several
    flow-matching candidates are drawn per token and the best is kept by
    reconstruction likelihood. Default 4 on the CLI and through the C ABI;
    override with TADA_NUM_CANDIDATES=N.
  • All candidates for a step solve in one batched flow-matching forward
    (~13N small forwards → ~13), so raising the count adds little wall-clock.
  • Validated by ASR roundtrip in German and French (single-candidate runs
    sometimes garble; candidates=4 is reliable).
  • Wired through the full session C ABI + every binding (Python, Go, Rust,
    Dart, Java, C#, Ruby, JS/WASM) via the new
    crispasr_session_set_tts_num_candidates(n) setter — bindings and the HTTP
    server get robust timing out of the box, not just the CLI.

Voice references — create your own with --make-ref (no Python)

  • New in-tree TADA encoder runtime + converters: build a voice-reference
    GGUF directly from a C++ pipeline with --make-ref, no PyTorch required.
  • Auto-download language voice refs on -l <lang>: the multilingual 3B-ml
    model pulls a matching reference (ar/ch/de/es/fr/it/ja/pl/pt) automatically.
  • Language-reference GGUFs published to cstr/tada-tts-{1b,3b-ml}-GGUF.

GPU + quantization

  • TADA now runs on the GPU runtime path (Metal/CUDA/Vulkan), sharing the
    backend with the codec.
  • Pos/neg CFG batched into a single B=2 graph per Euler step; prefill tokens
    batched and pos→neg KV copied.
  • Quantized FM Metal fallback + a mixed-precision Q4_K quantizer that
    matches the reference's BF16 noise rounding.
  • Vulkan: ggml_cont materialises contiguous copies before the B=2 FM ops.

Timing-embedding correctness (#192)

  • Fixed time-embedding during prompt-phase prefill and the time-transition
    boundary; only generated acoustic frames (not prompt-phase frames) are passed
    to the codec. Together these removed spurious trailing silence and rushed
    starts.
  • 1b = English-only; 3b-ml = multilingual — now documented, with the voice
    cloning + -l auto-download workflow.

Diff harness fairness

  • crispasr-diff for TADA is now a fair C++-vs-Python comparison (reseed before
    generate, store the prompt transcript), confirming the C++ forward pass
    matches the reference (time_before cos=1.0, codec cos=0.99998).

ReazonSpeech — Japanese RNNT ASR

  • New backend for reazon-research/reazonspeech-nemo-v2, a Japanese RNNT
    (transducer) ASR model.

CosyVoice3 — GPU generation + perf

  • GPU generation enabled (downloads colocated).
  • Batched CFG and lazy-loaded cloning encoders (only loaded when voice
    cloning is requested).
  • Right-sized autoregressive KV cache — lower memory, lower latency.
  • Full session wiring; latency-tuning + KV-sizing docs added.

C# bindings

  • New C# bindings for the CrispASR Session C ABI, with unit tests
    (InternalsVisibleTo wired so the test project can reach NativeMethods).

Qwen3-TTS

  • Encoder transformer is chunked to fix OOM on long reference audio (#187).

Bug fixes

Area Fix
TADA Noise-sensitive duration collapse → candidate ranking (default 4)
TADA Time embedding during prompt-phase prefill + time-transition boundary (#192)
TADA Codec fed prompt-phase frames instead of only generated frames
TADA PyTorch-compatible MT19937 noise + BF16 rounding parity
TADA Skip FM solver during prefill to avoid RNG offset
TADA Encoder Conv1d stride padding + tensor layout; float32 cast; transformers 5.x
TADA Language-ref converter: gated Llama → unsloth mirror, HF-token pass, tokenizer dict→str
Windows Guard setenv with _WIN32/_putenv_s in the crispasr-diff TADA path
CosyVoice3 Enable GPU generation; session wiring + formatting
Qwen3-TTS OOM on long reference audio — chunked encoder (#187)
Build Fully fix building against system libopusfile (#191)
Registry Add qwen3-forced-aligner to the model registry (#190)
CI Repair HIP checkout + Android mediandk link

Upgrading

No breaking changes to the C ABI, bindings, or CLI flags — all additions.

  • TADA now ranks 4 timing candidates per token by default (CLI, bindings,
    and server). Set TADA_NUM_CANDIDATES=1 (or set_tts_num_candidates(1)) to
    restore the previous single-draw behaviour.
  • The new crispasr_session_set_tts_num_candidates(n) setter is additive; older
    bindings without the symbol soft-no-op.

Full changelog

git log v0.8.4..v0.8.5 --oneline --no-merges

v0.8.4

Choose a tag to compare

@github-actions github-actions released this 24 Jun 16:37

CrispASR v0.8.4

Note: v0.8.3 was tagged before the VERSION file was bumped (binary
self-identified as 0.8.2). v0.8.4 supersedes it and fixes the version
mismatch. All features described here were already in v0.8.3 binaries;
this release adds the Qwen3-TTS one-breath fix, VibeVoice long-input GPU
crash fix, and the release-process hardening.


What's new

Audio format expansion — no ffmpeg required

CrispASR now decodes a much wider range of audio containers and codecs
without any dependency on ffmpeg:

  • Opus (.opus, bare Ogg-Opus): via libopus + libopusfile (FetchContent, auto-downloaded; opt-out with -DCRISPASR_OPUS_FETCH=OFF)
  • WebM: Ogg-demuxed Opus stream via the same path
  • AU / µ-law / AIFF: Sun Audio and classic broadcast formats
  • AMR-NB / AMR-WB (.amr): via opencore-amr FetchContent fork (-DCRISPASR_AMR_FETCH=ON; decoder-only, MIT-compatible)
  • M4A / AAC / ALAC / CAF on Apple platforms: via AudioToolbox — zero extra dependencies, native OS decode
  • M4A / AAC on Linux/Windows: via libfdk-aac loaded at runtime via dlopen — binary stays MIT-clean; falls back gracefully if the library is absent

Go and Ruby bindings expose the same set via their FetchContent link flags.
WASM/Emscripten builds use Opus with x86 SIMD disabled for portability.

Qwen3-TTS improvements

GQA_NATIVE + chunked codec decode (#183)

  • Switched attention kernel to GQA_NATIVE mode — O(N²)→O(N) scaling on Vulkan for long texts
  • Codec decode is now chunked: VRAM peak stays flat regardless of text length; RTF remains ~0.5×
  • Scratch scheduler reset between requests prevents cross-request memory bloat

1.7B small_to_mtp graph fold (#161)

  • The small_to_mtp projection that previously launched 16 separate GPU graphs per frame is now fused into the code_pred graph — ~12–15% faster on Metal, ~5–6% on CUDA P100
  • Opt-out via QWEN3_TTS_CP_MTP_NOFUSE=1

CUDA codec chunk cap

  • CUDA builds no longer OOM on very long inputs due to oversized codec batches; chunk size is now bounded

One-breath synthesis fix

  • Restored single-forward-pass synthesis path that was accidentally broken; multi-sentence inputs no longer stutter at sentence boundaries

VibeVoice TTS fixes

Long-input GPU crash (#171)

  • Fixed illegal memory access on CUDA when synthesising long text inputs

Vulkan / RDNA4 segfault (#184)

  • Fixed segfault on AMD RDNA4 GPUs caused by strided AdaLN views passed directly to Vulkan ops — ggml_cont now materialises contiguous copies before compute
  • Applies to all Vulkan backends (the ggml_cont on strided view_2d fix is backend-agnostic)

Bucket scheduler stabilisation (#184)

  • Bucket-cache LM step is re-enabled on GPU after fixing the gallocr state lifetime; bucket sched is always reset+alloc'd before use to prevent stale-pointer crashes

Cohere ASR

  • Added CRISPASR_COHERE_LEGACY_SA env flag to fall back to the pre-#161 self-attention path for users who hit the perf regression on non-GQA architectures

Orpheus GGUF consolidation

All Orpheus 3B GGUF variants (F16, Q8_0, Q4_K) are now consolidated in a single canonical repo cstr/orpheus-3b-0.1-ft-GGUF; the old cstr/orpheus-3b-base-GGUF repo shows a deprecation notice pointing to the new location. Model registry, regression manifest, test harness, and all HF READMEs updated.

iOS / visionOS / tvOS xcframework

  • AudioToolbox and CoreAudio frameworks added to xcframework slices (required for AAC/M4A decode on-device)
  • Opus and AMR disabled on iOS (FetchContent-built static libs are missing from libtool -static combined archives)
  • visionOS and tvOS slices skip Opus explicitly to avoid link failures
  • Per-slice failure markers added to build-xcframework.sh so partial failures surface individually in CI

Release process hardening (fixes #189)

  • validate-version CI job: release.yml now checks that the VERSION file matches the pushed tag before publish runs. A mismatched tag (the v0.8.3 mis-tagging root cause) now fails CI before any artifacts are published.
  • scripts/bump-version.sh: one-step helper that writes VERSION, runs sync-version.py to propagate to Cargo.toml / package.json / pyproject.toml / pubspec.yaml, commits release: bump VERSION to X.Y.Z, and creates an annotated tag — eliminating the manual bump-and-forget pattern.

Bug fixes

Area Fix
VibeVoice GPU crash on long inputs (#171)
VibeVoice Vulkan/RDNA4 segfault — strided AdaLN views
VibeVoice Stale gallocr bucket sched state
Qwen3-TTS One-breath synthesis regression
Qwen3-TTS CUDA OOM on long codec batches
Audio Windows Media Foundation mfapi.h include order (MSVC)
Audio MinGW uint32_t missing — <cstdint> before miniaudio
Build libopusfile private dependency not linked transitively
Build iOS xcframework FetchContent static lib path
CMake AMR FetchContent URL corrected to CrispStrobe fork
CI Go LDFLAGS sync script missing OPUS_FETCH=ON
CI clang-format on miniaudio_libopus.c

Upgrading

No breaking changes to the C ABI, Python binding, or CLI flags.

Packages that vendor cstr/orpheus-3b-base-GGUF should switch to
cstr/orpheus-3b-0.1-ft-GGUF. The model files are identical; only the
HuggingFace repo name changed.


Full changelog

git log v0.8.2..v0.8.4 --oneline --no-merges

v0.8.3 — audio format expansion + Vulkan/CUDA fixes + qwen3-tts perf

Choose a tag to compare

@CrispStrobe CrispStrobe released this 24 Jun 16:02

CrispASR v0.8.3

Patch release — audio format expansion, Vulkan/CUDA fixes, qwen3-tts performance.

New features

  • Audio format support: Opus, WebM, AU, AMR, M4A/AAC (#219). crispasr_audio_load
    now decodes .opus (via libopus/opusfile, BSD-3-Clause), .webm (Opus-in-WebM),
    .au (Sun/NeXT), .amr (AMR-NB/WB via opencore-amr), and .m4a/.aac (via
    fdk-aac dlopen on Linux, AudioToolbox on Apple). No ffmpeg dependency — all
    decoders are either statically linked or dlopen'd at runtime.

  • Apple AudioToolbox integration. On macOS/iOS, AAC/M4A/ALAC/CAF/AIFF files
    are decoded natively via AudioToolbox — zero additional dependencies.

Performance

  • qwen3-tts: GQA_NATIVE removes O(N^2) scaling (#183). Switching the talker
    and code-predictor attention from GQA_MANUAL_CONT to GQA_NATIVE eliminates
    CPU-side repeat_4d ops that forced 6658 backend switches per request on Vulkan.
    RTF stays ~0.5 regardless of text length (was climbing past 1.0 on long texts).
    Reported and measured by @proAkdag on AMD RDNA4/Vulkan.

  • qwen3-tts: chunked codec decode. The codec decoder now processes in chunks
    of QWEN3_TTS_CODEC_CHUNK frames (default 150) with left-context overlap, so
    peak VRAM depends on chunk size, not total sequence length. Env-tunable via
    QWEN3_TTS_CODEC_CHUNK and QWEN3_TTS_CODEC_CTX.

  • qwen3-tts: scratch scheduler reset. Codec and talker scratch schedulers are
    freed after each synthesis request, preventing the galloc high-water-mark from
    persisting across requests (3-12 GB VRAM bloat on long sequences).

  • qwen3-tts: 1.7B small_to_mtp fold (#161). The 1.7B model's small_to_mtp
    projection is folded into the code-predictor graph, removing a separate compute
    pass.

Fixes

  • vibevoice TTS segfault on Vulkan/RDNA4 and CUDA (#184). Two issues fixed:
    (1) Non-contiguous ggml_view_2d results in the diffusion prediction head's
    AdaLN split caused segfaults on Vulkan when passed to ggml_mul/ggml_add
    fixed with ggml_cont wrappers. Same pattern fixed across all backends
    (voxtral4b, zonos, indextts, kugelaudio).
    (2) The Lk-bucketed LM step cache skipped sched_reset+alloc_graph when
    reusing the same bucket, leaving stale gallocr compute buffer state after
    ctx->sched ran other graphs between calls — causing MUL_MAT illegal memory
    access on CUDA. Fixed by always resetting+reallocating (cached graph topology
    preserved, ~0.1 ms overhead). Reported by @logiclove.

  • iOS xcframework opus link errors. FetchContent-built static libraries
    (opus, ogg, opusfile) were not included in combined.a because the
    build-xcframework.sh glob missed the _deps/ directory. Fixed.

  • System opusfile pkg-config link (#185). PkgConfig::OPUSFILE only included
    libopusfile itself, missing private dependencies (libopus, libogg). Fixed by
    using ${OPUSFILE_STATIC_LIBRARIES} for full transitive linking. Thanks
    @BergmannAtmet.

  • Cohere legacy self-attention fallback (#161). Added
    CRISPASR_COHERE_LEGACY_SA env var for users who experience performance
    regression with the new attention path.

Upgrade

Drop-in for v0.8.2. No model re-download required.

v0.8.2 — chatterbox long-text fixes + long-form chunking + turbo emotion tags

Choose a tag to compare

@CrispStrobe CrispStrobe released this 22 Jun 06:24

CrispASR v0.8.2

Patch release — chatterbox robustness + chatterbox-turbo emotion tags.

Fixes

  • chatterbox: segfault on very long text (#182). A prompt longer than the
    model's text-position table (2050 positions for base T3; the char-level base
    tokenizer hits this on a ~4.5 KB paragraph, multibyte scripts with far less)
    read past the table and crashed. The token sequence is now bounded to the
    model's positional capacity (with a warning), with a defensive clamp at the
    embedding site. Five prefill sites (cond + uncond CFG, base + GPT-2 paths) were
    affected.

  • chatterbox: use-after-free in the long-form chunk loop. Reallocating the KV
    cache for a longer chunk left the cached decode step-graphs pointing at freed
    tensors → intermittent crash on the 2nd+ chunk (also affected the server
    /v1/audio/speech chunk loop). Cached bucket graphs are now invalidated on KV
    realloc.

Improvements

  • chatterbox CLI long-form --tts (§218). Long input is now sentence-chunked
    before synthesis (the same pipeline the server already used) — each chunk
    synthesises within the model's healthy horizon and the audio is concatenated
    with short pauses, so long prompts render in full instead of being truncated.

  • chatterbox-turbo emotion/style tags (§217). You can drive turbo prosody with
    bracketed tags in the input text: [laugh] [chuckle] [sigh] [gasp] [cough] [groan] [sniff] [shush] [clear throat] [whispering] [angry] [happy] [crying] [fear] [surprised] [sarcastic] [dramatic] [narration] [advertisement]. The
    tokenizer now emits these as their special token id (requires the re-uploaded
    cstr/chatterbox-turbo-GGUF files with the full 50276-token vocab; the
    converter now includes added_tokens.json).

Upgrade

Drop-in for v0.8.1. No model re-download required for the #182 fixes; the turbo
emotion tags need the refreshed turbo T3 GGUFs (re-uploaded to HF).

v0.8.1 — chatterbox-turbo load fix (#181)

Choose a tag to compare

@CrispStrobe CrispStrobe released this 21 Jun 21:18

CrispASR v0.8.1

Patch release — fixes a chatterbox-turbo loading regression introduced in v0.8.0.

Fixes

  • chatterbox-turbo: vocab-mismatch load regression (#181). v0.8.0 added a
    strict tokenizer↔embedding consistency check that rejected the published
    cstr/chatterbox-turbo-GGUF models with
    tokenizer has 50257 tokens, T3 text_vocab_size=50276. These files ship the
    stock 50257-token GPT-2 tokenizer against a 50276-row text embedding (19
    reserved rows) and loaded fine on v0.7.x. The mismatch is benign in this
    direction
    — BPE only emits ids < 50257, and special text tokens are added
    by id and bounds-checked against text_vocab_size, so the extra rows are never
    indexed out of range. The check is now directional: it hard-errors only
    when tokenizer > text_vocab_size (a real out-of-bounds risk) and warns +
    loads when tokenizer < text_vocab_size. No re-download needed — the turbo
    GGUFs already on disk load again. Reported by @niksedk (Subtitle Edit).

Upgrade

Drop-in for v0.8.0. chatterbox-turbo users blocked by the v0.8.0 load failure
should upgrade; everything else is unchanged.