CrispASR

Environment variables

CrispASR exposes a large number of environment variables — tuning knobs, device placement overrides, benchmark timers, and debug/dump switches. This page is the single reference for all of them: the naming convention, the cross-cutting variables, the per-backend variables, and the ones CrispASR deliberately does not own.

This document was introduced for issue #265 (“consistency and documentation”). The same change standardized every backend-owned variable onto one prefix and unified the reference-voice cache location (see below).

Naming convention

Every CrispASR-owned variable is named:

CRISPASR_<BACKEND>_<FEATURE>

for example CRISPASR_OMNIVOICE_CODEC_GPU, CRISPASR_IRODORI_CODEC_GPU, CRISPASR_PARAKEET_BENCH. Process-global variables that are not tied to one backend drop the <BACKEND> segment (CRISPASR_MODELS_DIR, CRISPASR_KV_ON_CPU).

Legacy aliases and deprecation warnings

Historically many backends used a bare prefix (OMNIVOICE_CODEC_GPU, QWEN3_TTS_BENCH, CHATTERBOX_DEBUG, …). Those bare names still work as legacy aliases so existing scripts, notebooks, and Kaggle A/B kernels keep running. The alias is derived automatically by stripping the CRISPASR_ prefix, so for any CRISPASR_FOO_BAR documented here the bare FOO_BAR is also honored.

The first time a run reads a value from a legacy name, CrispASR prints a one-time notice to stderr:

[crispasr] warning: environment variable 'OMNIVOICE_CODEC_GPU' is deprecated and
will be removed in a future release; use 'CRISPASR_OMNIVOICE_CODEC_GPU' instead
(the old name still works for now). ...

Migrate to the canonical CRISPASR_-prefixed name at your convenience. To silence the warnings (e.g. for a pipeline that scrapes stderr and cannot migrate yet), set:

CRISPASR_SUPPRESS_ENV_DEPRECATION=1

The lookup + aliasing is implemented once in src/core/crispasr_env.h (crispasr_env::get / truthy / present); new backends should read env vars through that helper with a canonical CRISPASR_-prefixed name.

Value/truthiness conventions

Most variables are read with one of two conventions — check the surrounding suffix legend, but as a rule:

Common suffix legend

The same feature suffixes recur across nearly every backend. Rather than repeat them per backend below, they mean:

Suffix Meaning
_BENCH Print per-stage wall-clock timings for that engine.
_DEBUG / _DIAG Verbose debug logging.
_DUMP_DIR / _DUMP / _DUMP_* Write intermediate tensors / stages to disk (diagnostics, diff-harness).
_FORCE_SCALAR Disable SIMD kernels (numeric-parity debugging).
_GPU / _USE_GPU / _FORCE_METAL Force that stage/codec onto the GPU.
_CPU / _CPU_ONLY / _FORCE_CPU Force that stage/codec onto the CPU.
_NO_FA / _FLASH_ATTN Toggle flash-attention.
_FASTCONV (_DEBUG) Enable the baked-F32 / matmul conv fast path for a codec/vocoder.
_CFG_INTERVAL (_DEBUG) Interval-CFG cadence for a flow-matching decoder.
_SEED RNG seed for reproducible generation.
_*_FILE / _*_PATH / _*_GGUF Override an asset/model/fixture path (mostly dev/test).

Global / cross-cutting variables

These are not tied to a single backend.

Paths, cache, and models

Variable Purpose
CRISPASR_MODELS_DIR Directory searched for GGUF models (also the auto-download target root).
CRISPASR_CACHE_DIR Base cache directory for auto-downloaded models/assets. Resolution order is CRISPASR_CACHE_DIRCRISPASR_MODELS_DIR → platform default ($HOME/.cache/crispasr; %USERPROFILE%\.cache\crispasr on Windows).
CRISPASR_SCRATCH_DIR Scratch directory for temporary run artifacts.
CRISPASR_DUMP_DIR Global tensor-dump directory (diagnostics).
CRISPASR_GGUF_MMAP / CRISPASR_GGUF_PRELOAD Control GGUF mmap vs. preload-into-RAM loading.
CRISPASR_GGUF_MAX_ALLOC_CHUNK Lower the per-buffer allocation cap in bytes (default 1.5 GiB) used to split a model across several backend buffers on drivers with a small maxMemoryAllocationSize (#276).
CRISPASR_MLOCK mlock model weights into RAM.
CRISPASR_IGNORE_CPU_ISA =1 exactly (no other value works) continues past the startup build-vs-host CPU instruction-set check (#380) instead of exiting; the process will SIGILL at the first compute op the CPU can’t run.

GPU / device placement

Variable Purpose
CRISPASR_N_GPU_LAYERS Number of transformer layers to offload to the GPU.
CRISPASR_ARG_DEVICE Default device selection for the CLI.
CRISPASR_KV_ON_CPU Keep the KV cache on the CPU.
CRISPASR_KV_QUANT / _KV_QUANT_K / _KV_QUANT_V / _KV_READ_F32 KV-cache quantization / read format.
CRISPASR_GPU_PREF_CPU_LEGACY 1 restores the pre-T18 behaviour where --gpu-backend cpu fell through to the best GPU. Off by default: the fall-through silently constructed a Metal device the flag exists to avoid.
CRISPASR_METAL_PIPELINE_CACHE_MAX_MB Size cap in MiB (default 64) above which the on-disk Metal pipeline-cache archive is skipped at init — opening it costs ~1 ms/MB. 0 = uncapped (always use it). macOS only.

Device selection across compiled backends also honors the standard ggml / CUDA variables CUDA_VISIBLE_DEVICES and GGML_VK_VISIBLE_DEVICES — see “Variables CrispASR does not own” below.

Session / long-audio chunking

Variable Purpose
CRISPASR_SESSION_AUTOCHUNK Enable auto-chunking in the session API for long audio.
CRISPASR_SESSION_CHUNK_SECONDS Chunk length (seconds) for session auto-chunking.
CRISPASR_SESSION_PERBACKEND_CHUNK Use per-backend chunk-window tuning instead of a flat window.
CRISPASR_SESSION_UNIFIED_DISPATCH Route surfaces through the unified library dispatch path.
CRISPASR_SLICE_PIPELINE Force the CLI’s encode ∥ decode slice pipeline on/off. The override may only turn it OFF, or ON where it is already safe — it can never switch off one of the safety conditions (-p N, --return-logits, gap-fill re-entry, single slice).

Post-decode hygiene (PLAN.md §W2–W7)

All OFF unless set. Each of these can delete or alter user-visible text, so none of them switches on by surprise; a wrong deletion is worse than a surviving artifact. Applied on both the CLI and the session C-ABI.

Variable Purpose
CRISPASR_SEG_MAX_CHARS Truncate any segment longer than N code points, backing up to the last 。..!!??、, but never below 75% of the cap. A line past the cap is almost always a repetition hallucination that survived the n-gram collapse.
CRISPASR_SEG_DROP_NONVERBAL Drop segments that are entirely a non-verbal marker — [Music], (applause), (喘ぎ声), . Running speech merely containing such a word is never dropped.
CRISPASR_SEG_LOGPROB_THOLD Drop segments whose average log-probability is below this. Post-hoc, on top of the decoder’s own fallback gate.
CRISPASR_SEG_LOGPROB_MARGIN Loosen that threshold by this much for segments ≤1.6 s — a short segment’s mean logprob is noisier, so it gets more room, not less.
CRISPASR_SEG_MERGE_REPEATS Collapse runs of near-identical adjacent segments into one spanning the whole run. Catches a phrase repeating across segment boundaries, which per-segment loop fixes cannot see.
CRISPASR_SEG_MERGE_SIMILARITY Similarity bar for the above (default 0.90; LCS over code points).
CRISPASR_SEG_MERGE_GAP_CS Never merge across a gap wider than this many centiseconds (default 200). Two identical lines a minute apart are two real utterances.
CRISPASR_SEG_MERGE_MIN_RUN Minimum consecutive similar segments before merging (default 3), so an ordinary repeated “yes.” pair survives.

Alignment and VAD sanity checks

Variable Purpose
CRISPASR_ALIGN_SENTINEL 0 disables the forced-alignment collapse check. On by default, detect + warn only. Catches ctc_forced_align() returning words at t0 == t1 == 0 — its two silent-zero paths (characters absent from the CTC vocab, or a word the Viterbi path never visited) produce garbage timestamps inside a successful return.
CRISPASR_ALIGN_SENTINEL_REDISTRIBUTE 1 opts into repair: respace the words across the clip in proportion to character count. Off by default — a wrong auto-repair would be just as invisible as the collapse.
CRISPASR_VAD_FAILOVER 0 disables the VAD sanity check. On by default: if a clip over 120 s comes back with under 1% speech coverage (or a couple of segments covering under 10% of a very long clip), the VAD is wrong and the run falls back to fixed full-clip chunks rather than losing the transcript.
CRISPASR_NGRAM_LOOPFIX_OFF 1 disables the repeated-n-gram collapse entirely, exposing the RAW decoded text. Diagnostic: for telling whether a loop originates in the decode itself or is merely being masked.
CRISPASR_ORDER_WARN 0 disables the one-shot “segment timestamps go backwards” warning. On by default; detect + warn only. Cues that merely overlap are deliberately not flagged (gap-fill jitter).
CRISPASR_ALIGN_NO_ROMANIZE 1 passes non-Latin reference text through raw instead of auto-romanizing it for a CTC aligner with a Latin vocabulary (#252). Since #419 the romanization is only the aligner’s internal label — aligned words hand back the original script, so srt/vtt/-sp/-sow output no longer flips Cyrillic/CJK transcripts to transliteration.
CRISPASR_ALIGN_DEBUG 1 prints the romanized reference transcript the aligner actually used.

Decoding / beam search (shared)

Variable Purpose
CRISPASR_MAES_BETA / _MAES_GAMMA / _MAES_NUM_STEPS MAES beam-search parameters.
CRISPASR_TDT_BATCH / CRISPASR_RNNT_BATCH Batch the TDT / RNNT joint decode.
CRISPASR_RNNT_GGML_PERSTEP Per-step (vs. persistent-graph) ggml RNNT decode.
CRISPASR_RNNT_GPU_ENC_PROJ Parakeet’s backend encoder-to-joint projection is default on CUDA. 0 restores the scalar CPU projection; 1 opts other GPU backends in.
CRISPASR_NGRAM_LOOPFIX_OFF Disable the n-gram decode-loop breaker.
CRISPASR_STREAM_SLICE_MEMO Memoize per-slice streaming partial decodes by absolute sample range (#404). Default ON — finals byte-equal, wall −12 % CPU / −6 % GPU in the quiet-box A/B; =0 re-decodes closed slices every step.
CRISPASR_GAP_FILL / _GAP_FILL_MIN_CS Re-transcribe spans a first pass left empty (long audio); on by default for parakeet, threshold non-JA 300 cs / JA 100 cs.

G2P / phonemizer

Variable Purpose
CRISPASR_CMUDICT_PATH Path to the CMUdict pronunciation dictionary.
CRISPASR_DE_DICT_PATH / _FR_DICT_PATH / _ES_DICT_PATH / _RU_DICT_PATH Language-specific pronunciation dictionaries.
CRISPASR_RU_HETERONYMS_PATH Path to the Russian heteronym list. Only read when CRISPASR_G2P_RU_HETERONYM_WARN is on — it is diagnostic data, not a lookup tier.
CRISPASR_G2P_RU_HETERONYM_WARN 1 prints one line per input word that the upstream project flagged as genuinely ambiguous. Those 17,359 words are DISJOINT from the 812,953-entry vocabulary — they were removed because upstream could not choose a reading — so they have no dictionary entry and the letter-to-sound rules pick one reading from spelling alone. Common words are in that set (все, уже, потом, чем, небо, тест). Off by default; on, it turns a mispronunciation that looks like a rule bug into a named, explained limitation. Writing the ё or an explicit combining acute (замо́к) in the input resolves many of them, and both are honoured.
CRISPASR_G2P_RU_ANALOGY 0 disables the Russian stress-analogy tier, which finds a known relative of an OOV word (strip up to 3 letters, glue a short list of inflectional endings back on) and borrows its stress. On by default and measured on 10,000 held-out dictionary words: stressed-syllable index right 93.9% with it and 47.1% without; exact IPA match 79.4% vs 40.9%. The lever exists because it is the one tier that can take a stress from a word that merely LOOKS related.
CRISPASR_G2P_DICT_SOURCE / _G2P_MODEL_PATH G2P dictionary source / neural G2P model path.
CRISPASR_ESPEAK_DATA_PATH eSpeak-NG data directory.
CRISPASR_MISAKI_DICT_PATH Path to the misaki US contextual-word dictionary (default ~/.cache/crispasr/misaki-us.txt) used by the English misaki G2P (#316).
CRISPASR_KOKORO_G2P Kokoro G2P backend selection.
CRISPASR_KOKORO_MISAKI_IPA 0 disables the espeak-IPA → misaki-alphabet conversion Kokoro needs (#316), restoring the raw G2P spelling for A/B. On by default.
CRISPASR_G2P_DE_UNSTRESS 1 reads the German closed class the way espeak reads it in a SENTENCE (sieziː) instead of the citation form our per-word dictionary stores (zˈiː). Off by default: it takes phoneme agreement with espeak from 45.9% to 87.1%, but the ASR round-trip could not resolve a difference, and that metric measures intelligibility rather than naturalness (#316).
CRISPASR_KOKORO_DE_MISAKI_ALPHABET 1 applies misaki’s tied-sequence collapse for German (tsvˈaɪʦvˈI), which is what the published training recipe does. Off by default: it made the ASR round-trip worse on the kokoro-de-hui-base model we ship, which appears to predate that part of the recipe (#316). The ʏy vocabulary fixup is applied either way.
CRISPASR_T5_REPEAT_BREAK 0 disables the decode-loop break for madlad/T5 translation, restoring exact PyTorch-blueprint behaviour. On by default: MADLAD greedy-decodes into a repeated token cycle on some short inputs and burns the whole token budget on it. The blueprint does the same — this is a deliberate improvement on it, not a parity fix (#333).
CRISPASR_T5_NO_KV_REUSE 1 re-forwards the whole decoder prefix each step instead of appending to the KV cache. Same output, much slower; an A/B lever for isolating cache bugs (#333).
CRISPASR_T5_KEEP_EMBED 1 keeps shared.embed.* and lm_head.* at source precision when quantizing a T5 model. Off by default because it was measured and loses: on madlad400 it makes q8_0 3.38→3.62 GB and q4_k 2.04→2.41 GB for a worst-stage cosine that does not improve (0.999922→0.999920, 0.992929→0.992606). The Q4_K loss accumulates through the 32 encoder blocks, not in the embedding lookup (#333).
CRISPASR_KOKORO_PUNCT 0 drops punctuation from the phoneme string for the German/French/Spanish built-in G2Ps, restoring pre-0.8.26 behaviour for A/B. On by default: Kokoro’s vocabulary contains ,.;:!? and they are how it pauses (#316). English is not gated — it is settled against misaki.

Watermark / provenance

Variable Purpose
CRISPASR_NO_WATERMARK Disable the audio watermark.
CRISPASR_WATERMARK_LEGACY Use the legacy watermark path.
CRISPASR_WATERMARK_DETECT Which statistic --detect-watermark uses: frames (per-frame t + decoy specificity) or sign / 0 (the older averaged-spectrum sign test, kept for A/B and for re-reading an older release’s score).
CRISPASR_NO_C2PA_REMUX Skip the C2PA MP4 remux step.
CRISPASR_CONSENT_LOG Path to a JSON-Lines sink for voice-cloning consent records. Without it the records only go to stderr, which is interleaved with model-load noise and so a poor evidential artefact.

Quantization / diff-harness / misc

Variable Purpose
CRISPASR_QUANT_LMHEAD Quantize the LM head during crispasr-quantize.
CRISPASR_IMATRIX_OUT Importance-matrix output path.
CRISPASR_ACTDUMP_OUT / _ACTDUMP_TENSOR Activation dump output / target tensor.
CRISPASR_DIFF_NO_GPU / _DIFF_USE_GPU / _DIFF_SLICES / _DIFF_STAGES crispasr-diff harness controls.
CRISPASR_MEL_SERIAL Force the serial STFT. The parallel mel/STFT path is DEFAULT ON since #305; this is the opt-out. (The older opt-in CRISPASR_MEL_PARALLEL is no longer read.)
CRISPASR_MEL_TIMING Print mel/STFT stage timings.
CRISPASR_HQ_RESAMPLE 0 selects the cheap linear resampler for CLI input decoding instead of the high-quality one.
CRISPASR_CORE_ATTN_EAGER_F32 Force the shared attention helper’s eager (non-flash) path to F32 accumulation.
CRISPASR_CORE_ATTN_DUMP_FA_LAYER Dump the shared attention helper’s flash-attn inputs/outputs for one layer index.
CRISPASR_VERBOSE Global verbose output.
CRISPASR_NO_WARMUP / CRISPASR_WARMUP Skip / force the model warmup pass.
CRISPASR_SERVER_WORKERS / CRISPASR_API_KEYS HTTP server worker count / API keys.
CRISPASR_TEST_STREAM_THROW Test-only: lets the server’s streaming worker throw on the magic input __throw_test__ (both the variable and the input are required, so it cannot fire in production).

Container / launcher

Read by the Docker images and .devops/run-server.sh, not by the C++ itself — crispasr-diagnostics echoes them so a support dump shows how the container was started.

Variable Purpose
CRISPASR_BACKEND Backend the container’s entrypoint should select (docker-compose*.yml, .env.example).
CRISPASR_USE_CUDA_COMPAT 1 prepends /usr/local/cuda/compat to LD_LIBRARY_PATH in the CUDA images — for hosts whose driver is older than the image’s CUDA runtime.

Vendored ggml (CrispASR-added)

CrispASR’s in-tree ggml/ carries a few CrispASR-prefixed knobs on top of upstream’s GGML_* set. They are read by getenv directly (no legacy alias).

Variable Purpose
CRISPASR_GGML_ALLOC_TRACE Trace ggml-alloc graph-allocation decisions.
CRISPASR_GGML_ALLOC_TRACE_MAX_PASSES Number of allocation passes that trace prints (default: unlimited once the trace is on).
CRISPASR_METAL_N_CB Override the Metal backend’s command-buffer count (#83).
CRISPASR_METAL_PROFILE 1 whole-graph host/GPU split, 2 per-op breakdown, 3 per-op plus a per-node trace announced before each encode — with 3 the last line names the node an encode faulted on.
CRISPASR_METAL_STRICT_FP Compile the Metal kernels with fast-math OFF (#83). Costs throughput; buys bit-identical CPU/GPU output where operand reordering was downconverting F32 intermediates.
CRISPASR_METAL_FORCE_BARRIER 1 forces a memory barrier before every Metal op (concurrency-hazard bisection, #83).
CRISPASR_METAL_IM2COL_FLAT 0 restores the legacy IM2COL Metal kernel. The flat kernel (one thread per dst element) is the default.
CRISPASR_FORCE_BLIT_COPY Use the blit-encoder copy path even for a shared (unified-memory) Metal buffer (#83).
CRISPASR_FORCE_DMB Insert a full memory barrier after the host memcpy into a shared Metal buffer (#83).

Reference-voice cache (voice cloning)

Encoding a reference clip for voice cloning (a codec encoder, a Conformer / Perceiver, or an ASR pass) is slow and produces a small, reusable blob. Every voice-cloning TTS backend caches that blob through one shared mechanism (src/core/tts_ref_cache.h), so the location and disable switch are identical across backends (issue #265 unified OmniVoice — which previously used a bespoke ~/.cache/crispasr cache — onto this path):

Variable Purpose
CRISPASR_TTS_REF_CACHE Set to 0 to disable reference-voice caching everywhere.
CRISPASR_TTS_REF_CACHE_DIR Override the cache directory (default <TMPDIR>/crispasr-tts-refcache).

Content-addressed entries are keyed by a hash of the raw reference (plus, for some backends, an encoder-weight fingerprint) and tagged per backend (irodori-latent, openvoice2-se, omnivoice-voice, f5-reftext, …) so no two backends read each other’s blob. OmniVoice additionally honors the legacy CRISPASR_OMNIVOICE_VOICE_CACHE=0 as an alias for the shared disable switch.

Variables CrispASR does not own

These are read by CrispASR but are OS / third-party conventions and are intentionally not renamed to the CRISPASR_ prefix:

Variable Origin
HOME, USERPROFILE, LOCALAPPDATA, XDG_CACHE_HOME OS home / cache dirs.
TMPDIR, TEMP, TMP OS temp dir (also the default ref-cache root).
HF_TOKEN, HUGGING_FACE_HUB_TOKEN HuggingFace auth (Hub convention).
CUDA_VISIBLE_DEVICES CUDA device selection.
GGML_VK_VISIBLE_DEVICES ggml Vulkan device selection.
LLAMA_* Vendored llama.cpp (talk-llama example).

Sibling modular libraries (own conventions)

The in-tree modular libraries keep their own established prefixes and are synced from their sibling repos, so their variables are not part of the CRISPASR_ scheme:

Test fixtures

The live/integration test suite reads a few CRISPASR_-prefixed fixture variables (model/audio paths); tests/env-live-tests.sh sets sensible defaults. Like every other variable here, the pre-standardization bare names are still honored as deprecated aliases:

Variable Purpose
CRISPASR_PARAFORMER_MODEL / _PARAFORMER_MODEL_Q4K / _PARAFORMER_AUDIO_ZH / _PARAFORMER_AUDIO_EN Paraformer test model / audio paths.
CRISPASR_AUDIOSEAL_GGUF AudioSeal test model path.
CRISPASR_PIPER_TEST_MODEL Piper phonemize test model path.
CRISPASR_OV2_DUMP_DIR OpenVoice2 HiFi test dump directory.
CRISPASR_MODEL_BTC_CHORDS BTC chord-recognition test model path. Defaults to $CRISPASR_MODELS_DIR/btc-chords-large-f32.gguf.

Per-backend variables

Every variable below is the canonical CRISPASR_-prefixed name; the bare form (without CRISPASR_) is accepted as a deprecated alias. See the suffix legend above for the meaning of the common _BENCH / _DEBUG / _DUMP_* / _GPU / _CPU / _FORCE_SCALAR / _FASTCONV / _CFG_INTERVAL / _SEED suffixes.

AAC codec

ARK-ASR

AudioSeal watermark

BananaMind TTS

Bark

Beat-This (beat tracking)

BERT encoder

BTC chord recognition

The shipped BTC weights are CC-BY-NC-SA (trained on Isophonics / Robbie Williams / UsPop2002 chord annotations) even though the upstream BTC code and CrispASR itself are MIT. The registry refuses to download them without --accept-license cc-by-nc-sa-4.0 (or CRISPASR_ACCEPT_LICENSE). A commercial product must supply its own weights.

Canary / Canary-CTC / Canary-Qwen

Chatterbox

Chatterbox S3Gen

Chatterbox sub-modules

Cohere

Confucius4 TTS

CosyVoice3

CosyVoice3 (diff-harness assets)

CREPE (pitch)

CSM TTS

Dia TTS

dots.tts

ECAPA (LID / speaker)

F5-TTS

FastConformer (shared encoder)

FastPitch

Ffmpeg

FireRed ASR / VAD

FunASR / SenseVoice

Gemma-4 E2B

GLM-ASR

Granite speech / NLE

HiFT vocoder

HTDemucs (source separation)

All three optimisation gates are output-equivalent: the per-stage diff reports 45/45 stages passing with them ON or OFF.

Higgs STT

IndexTTS

Irodori TTS

Kokoro

KugelAudio

Kyutai STT

LFM2-Audio

M2M-100 translate

MarbleNet VAD

Mel-Band RoFormer (source separation)

MeloTTS

Mimi codec

MiMo-ASR

mini-omni2

Moonshine

MOSS family

MP3 codec

Diarization — foxnose (#324)

GigaAM-v3

Nemotron

OmniASR

OmniVoice

OpenVoice2

Opus codec

Orpheus

OuteTTS

Paraformer

Parakeet

Parler-TTS

Piano transcription

Piper

Pocket-TTS

Pyannote segmentation

Qwen3-ASR

Qwen3-ASR / Qwen3-TTS

SenseVoice

Sidon

Sherpa

Silero LID

SpeechT5

T5 translate

TabCNN (guitar tablature)

TaDa TTS

TitaNet speaker

Three compute paths exist and all are kept working; the default is the fastest one measured per platform.

path selected by measured, M1, 2 s segment
legacy (Accelerate / hand-rolled) default where HAVE_ACCELERATE 71.7 ms
ggml graph, CPU default elsewhere; CRISPASR_TITANET_GGML=1 277.3 ms
ggml graph, GPU CRISPASR_TITANET_GGML=1 CRISPASR_TITANET_GPU=1 31.9 ms (but see below)

All three agree to cosine 1.000000 with each other and 0.999996 against NVIDIA’s nemo_en_titanet_large.onnx export fed the same mel — so the choice is purely about speed.

CRISPASR_TITANET_GPU=1 is opt-in because it loses on real workloads despite winning the micro-benchmark. Diarization embeds one segment per call at variable lengths, so every call reshapes the graph and the GPU allocator re-reserves; and CRISPASR_SPEAKER_EMBED_WORKERS runs several embedders at once, which contend for the one GPU. End-to-end on a 600 s clip, 47 segments:

workers=4, legacy   9994 ms    <- default, fastest
workers=1, legacy  12673 ms
workers=1, GPU     15275 ms
workers=4, GPU     49866 ms

Keep it for evaluating a discrete GPU (where the balance may differ) or for CRISPASR_SPEAKER_EMBED_WORKERS=1 on a machine with weak CPU cores. Bucketing segment lengths so the graph shape stops changing is the work that would make this path win generally.

CRISPASR_TITANET_DUMP_MEL=<path> writes the computed mel as [T][n_mels] float32 — the counterpart to CRISPASR_TITANET_REF_MEL. Feeding that dump to an upstream ONNX export separates the front-end from the network, which a single end-to-end cosine cannot do.

VibeVoice

VoxCPM2

Voxtral / Voxtral-TTS

Voxtral-4B

VAD (encoder/decoder Silero-style)

VAD (WebRTC)

Wav2Vec2

Whisper (Tiron speaker attribution)

WavTokenizer

Zonos

CRISPASR_COSYVOICE3_CAMPP_TAIL

legacy makes cosyvoice3’s CAM++ speaker encoder use the old partial-tail divisor. Default is the same convention as every other CAM++ backend.

Both paths synthesise correctly — the TTS→ASR roundtrip is 8/8 on each — so this is a CONSISTENCY switch, not a correctness one. The eight speaker embeddings baked into the shipped cosyvoice3-voices.gguf were produced with the old divisor, so by default a voice cloned from a WAV and the same voice taken from the bank differ by cos ~0.998. Set this to legacy if you need those two paths to agree.

Why cosyvoice3 specifically is unsettled: its upstream is campplus.onnx, and two onnxruntime builds disagree about AveragePool(ceil_mode=1) on the same clip. CRISPASR_CAMPP_LEGACY_SEGPOOL also exists but is GLOBAL — it would drag chatterbox, confucius4, dots-tts and fireredtts3 away from their own settled PyTorch references to answer a cosyvoice3-only question.