The upstream Chatterbox README documents paralinguistic tags ([laugh],
[chuckle], [sigh], ...) as native to the Turbo family, and the vendored
Turbo pack passes them straight to the tokenizer -- it never parses them.
Our engine deleted them before the model saw them, so the feature looked
implemented and was inaudible.
* the text engine keeps a Turbo tag verbatim and records its name; on any
other pack the nine Turbo names stay literal text instead of being
swallowed as a voice name, and the run says so
* the v2 angle tokens are re-spelled for Turbo (<giggle> -> [giggle]) and
left untouched everywhere else
* generate_audio now builds one plan for every family, synthesises one
chunk per model call and joins the chunks; the classic path goes through
the engine too, which is what makes "[Alice]" open a character segment
* per-chunk seeds (seed + index) keep a chunked run reproducible without
giving every chunk the same prosody
* four appended widgets on ChatterboxTTS: enable_chunking,
max_chars_per_chunk, chunk_combination_method, silence_between_chunks_ms
* chunk boundaries prefer a sentence end and never land inside a tag
* Turbo's exaggeration is passed as 0.0: the family ignores it for
sampling and upstream warns about every non-zero value, once per chunk
Every entry point that conditions on a reference clip now takes the
waveform in memory: the vendored loaders gained load_audio_at (path,
ndarray or tensor -> float32 mono at the target rate, soundfile +
torchaudio, no librosa), and the resamples ride the new dsp module. The
node hands over preprocess_comfy_audio output at the right rate per
site (S3Gen 24k for conditioning, the tokenizer's 16k for the VC
source), so temp_wav_path and its temp-file machinery are gone -- which
also removes the 16-bit PCM quantization the file round-trip imposed.
Resampling is the one deliberate numerical difference: torchaudio's
sinc kernel instead of soxr, touching only clips supplied at call time.
The built-in-voice shared-assets E2E stays byte-identical
(md5 370acf3f9469d55759c3d6096b2628ff); the reference-clip E2E changes
measurably in the last digits, as expected and reported.
- ve/s3gen/s3gen_v3 safetensors + grapheme tokenizer are byte-identical
across every repo that ships them (sha256-verified): fetched at most
once into a reserved _shared store, hardlinked into each pack
- downloads carry pack-unique files only (allow_patterns); legacy
full-repo folders satisfy the store before anything is fetched
- vendored MTL loads ve/s3gen from either serialization, safetensors
first; upstream's strict load refused every SLP pack (P-036)
- .pt twins (s3gen.pt, s3gen_v3.pt, t3_cfg.pt, ve.pt) are never fetched
Vendored pack classes are not nn.Modules; the dtype cast
crashed on named_modules. Walk their Module attributes, and
delegate into each child's own tree (_modules is invisible
to __dict__ iteration).