Skip to content

CrispASR v0.8.9

Latest

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.