Per-voice conditioned-speech corpus — design manual

How to build a systematically varied, EN/DE-paired speech corpus for every reference voice, and why every constant in it is the value it is.

1. What this is, for someone with zero context2. The condition matrix (808 groups per voice)3. Reference voices and variant choice4. The safety gate5. Text source, EN/DE pairing and domain balance6. Emotion block: LoRA, lambda, prompt, sampling7. VoiceNet block: 57 dimensions x 4 levels8. Edge cases9. Sports commentator and explicitness10. Exact prompt templates11. Ranking, per condition type12. Per-candidate metadata schema13. Storage layout14. Compute estimate: 100 / 1,000 / 6,000 voices15. Reproducing this from nothing16. What is assumed, and what could not be verified

1. What this is, for someone with zero context

The one-sentence version. For each of ~6,000 reference speaking voices, generate a large, systematically varied set of speech clips — every emotion at four intensity and containment settings, every voice-quality dimension at four levels, a set of hard edge cases, plus sports-commentary and explicit-register variants — in English and in German using the same sentence, and store every candidate with its full measurement record.

Why the same sentence in both languages matters. Suppose you want to train a model that hears German speech and produces the same person saying the same thing in English, still angry, still holding it in, still at the same speaking rate. To learn that, the model needs paired examples where only the language changes. Everything else — who is speaking, what they feel, how strongly, how contained, how fast — must be held fixed. That is exactly what this corpus is: for one voice, one emotion, one intensity setting, you get an English take and a German take of the same meaning. The model can then learn “translate the words, keep the person and the performance”, because the data shows it that pairing thousands of times.

Why so many conditions. A speech-to-speech model that only ever saw neutral speech will translate an argument into a weather report. Sweeping 40 emotions x 4 settings and 57 voice dimensions x 4 levels gives dense coverage of the space of deliveries, not just its centre. Each cell also carries a measured label for what actually came out, so the corpus can be filtered or re-weighted later without regenerating anything.

How a clip is made, mechanically. A 4.55 B speech model (laion/moss-tts-local-transformer-4.55b-voice-acting-v2) is given three things: a reference wav of the target voice, a caption describing the delivery, and the words to say. Small trained adapters (LoRAs) are merged into the model at a chosen strength to push it toward a specific emotion or voice quality. It generates 200 candidates; every candidate is measured by a stack of sensors; the candidates are ranked; all of them are kept.

The four things this design is built around, all of them learned the hard way.
  1. Speaker identity cannot be gated on. Measured on 200 listener-labelled clip pairs: among pairs a listener called the same speaker, the median ECAPA cosine is 0.632, and 55 % fall below the 0.68 floor an earlier pipeline rejected at, while a genuinely different speaker scored 0.816 and would have passed. So identity is ranked, never gated high: reject only below 0.4, flag for resampling below 0.58, repair by voice conversion below 0.45.
  2. No single embedding separates same from different speaker. ECAPA AUC 0.847, a VoiceNet time-independent profile 0.814, WavLM-timbre 0.794. The best pair is ECAPA + VoiceNet at 0.854. Both are therefore stored for every candidate.
  3. Naturalness has two-sided bands. Disfluency 2.5–4.0 and 2.4–3.3 words/second. Penalising only fast delivery tripled the share of unnaturally slow output; both sides are penalised here.
  4. Non-verbal generation fails silently. On one brief, every candidate returned an empty audio_codes_list — reference-conditioned and unconditioned, at every token budget. The worker detects and counts empty decodes rather than assuming a token fix worked.

2. The condition matrix (808 groups per voice)

blockconditionsgroupssource of the settings
emotion40 emotions × {intense, moderate} × {free, contained} × {EN, DE}320emotion-voice-conditions/voice0.html + contained.html
VoiceNet57 dimensions × 4 levels × {EN, DE}456moss-voicenet-manual/site/dims (5-dose sweep per dim and direction)
edge cases(8 from voice0.html + 6 from the edge-case GA) × {EN, DE}28voice0.html carriers; moss-emotion-edgecase-evolution hall-of-fame genomes
sports1 × {EN, DE}2laion/moss-sports-commentator-lora real_r64_e8
explicitness1 × {EN, DE}, safety-gated2TTS-AGI/moss-explicitness-loras aesthetic_mix_r32
total808

A group is one cell of the matrix. Each group produces 200 candidates in the demo and 32 in production — 32 because a measured sweep found batch 16→32 flat in wall time on a GH200 (20.34 s → 20.54 s, +4.5 % reward) while 32→64 costs 3.4×.

The four emotion conditions follow the published A/B/C/D definitions:

intensitycontainmentpublished sublabelemotion LoRA lambda
Aintensefree-flowingmaximum emotion, freely let outper-emotion (table in §6)
Bmoderatefree-flowingmild emotion, freely expressed0.5
Cintensecontainedvery strong but held back — it leaks throughper-emotion (table in §6)
Dmoderatecontainedmild, quietly controlled0.5
The same sentence pair is reused across all four conditions of one emotion and across both languages. Four EN + four DE takes of the same meaning, same voice, same emotion. That reuse is the point: it is what makes the EN/DE halves differ only in language. Reuse is by text slot — one slot per emotion, one per dimension, one for sports, one for explicitness (99 slots per voice).

Published pooled statistics for the four conditions (240 cells each, 6 voices): A emo 0.437 / genu 0.362 / spk 0.569, 41 of 240 below the identity floor · B 0.273 / 0.400 / 0.617, 6 · C 0.294 / 0.265 / 0.559, 48 · D 0.185 / 0.326 / 0.617, 6. Intensity, not containment, is what breaks the voice clone: A and C carry 89 of the 113 flags. C also costs the most genuineness.

3. Reference voices and variant choice

Source: TTS-AGI/moss-reference-voices-consolidated — 12 WebDataset shards (data/voices-NNNN.tar, ~505 voices each) plus annotations/ and metadata.parquet. 6,064 voices, each present in three variants: orig, sidon (SIDON speech enhancement) and cbx (Chatterbox voice-conversion to itself).

Variant choice: highest DNSMOS ovrl_mos. Recomputed here from the shipped annotations/dnsmos.json rather than taken from the best_version column, so the rule is auditable; the two agree on 100 % of voices. Distribution of winners: orig 2,317 (38.2 %), sidon 1,940 (32.0 %), cbx 1,807 (29.8 %). Mean DNSMOS is essentially identical across the three (3.343 / 3.346 / 3.344) — the enhancement does not raise the mean, it changes which clips are best, which is exactly why the choice is made per voice.

All metadata is carried forward: cid, name, gender, age, language, accent, tagline, tags, source, all three DNSMOS values, the chosen variant, the shard, and the 99 precomputed annotation dimensions (40 EmoNet + 57 VoiceNet + genuineness + blend) for both the original and the enhanced version.

Chatterbox voice conversion (LAION-AI/chatterbox-voice-conversion, from chatterbox_vc.convert import VoiceConverter) is available as an identity repair. Measured over 68 converted parts it moved similarity 0.755 → 0.820 (improved on 88 %) with DNSMOS 3.30 → 3.35 — no net quality cost. It is applied only when identity has actually drifted below 0.45, and kept only if sim_after > sim_before and dnsmos_after ≥ dnsmos_before − 0.15.

4. The safety gate

Mandatory, and conjunctive. Before the explicitness group only, a voice must pass all three tests. If any fails, the two explicitness groups are skipped for that voice and the reason is recorded; all 806 other groups still generate.
testthresholdsourcewhat it catches
Empathic-Insight / EmoNet Age head≥ 2.0laion/Empathic-Insight-Voice-Plus :: model_Age_best.pth, scale 0 = infant, 2 = teenager, 4 = adult, 6 = very oldmeasured on the reference audio itself
VoiceNet AGEV≥ 2.4laion/voicenet-dimension-predictors-commercial :: dimensions.pyvoices that read young despite an adult card
character card age stringno child/teen termmetadata.parquet, human-writtenremoves all 405 card-labelled minors outright

Why the AGEV cutoff is 2.40 and not 3.00

The taxonomy anchors put AGEV level 2 at adolescent and level 3 at peak adult vigour, which reads like a 3.00 cutoff. But the regressor is measurably biased low against this dataset's own human-written age cards: voices whose card says “late 20s to mid-30s” have a median AGEV of 2.63, and “early to mid-20s” a median of 2.30. A 3.00 cutoff is therefore not conservative, it is miscalibrated.

Calibrated against all 6,064 reference voices (405 cards naming a child or teenager, 5,642 naming an adult age), AGEV separates the two at AUC 0.843 — useful, but not clean enough to gate on alone, which is precisely why the gate is conjunctive:

AGEV cutoffcard-labelled minors excludedcard-labelled adults lostwhole pool excluded
1.9055.1 %11.4 %14.4 %
2.40 ← chosen82.2 %25.9 %23.2 %
3.0092.8 %49.3 %52.3 %

Under the combined pre-gate (card string + AGEV ≥ 2.4), 4,187 of 6,064 (69.0 %) voices are eligible for the explicitness group. The Empathic-Insight Age head then runs on the actual reference audio in the worker and can still veto.

On the demo voice: EI-Age 3.10, VoiceNet AGEV 4.72, card 'Late 40s to 60s' → explicitness ALLOWED.

5. Text source, EN/DE pairing and domain balance

Source: HuggingFaceFW/finetranslations, subset data/deu_Latn/ (230 parquets). Each row is a document: og_full_text is the German original, translated_text the English translation, with og_chunks / translated_chunks giving chunk-level alignment.

Correction to the brief. subsets.csv is a language table (534 rows: subset_name, num_documents, num_english_tokens, filesize_bytes) — it contains no topical taxonomy, and neither do the parquet columns. A domain label therefore has to be derived. Here it is derived from the source URL host plus a keyword lexicon over the English side; both the label and which of the two rules produced it are stored, so the labelling can be audited or replaced without re-sampling any text.

Filters: og_language_score ≥ 0.95; equal chunk counts EN/DE; equal sentence counts within a chunk; 12–80 words on both sides; length ratio within 2×; no markup, URLs or long digit runs; must start with a capital; de-duplicated on a hash of the English side.

Balance achieved over 4,000 pairs — sampled with an equal per-domain quota rather than proportionally, which is what stops news and academic text dominating:

domainpairsshare
medicine_health2907.2 %
arts_culture2877.2 %
general2877.2 %
business_finance2867.2 %
academic2857.1 %
education_howto2857.1 %
fiction_personal2857.1 %
food_cooking2857.1 %
government_law2857.1 %
news2857.1 %
religion_philosophy2857.1 %
sports2857.1 %
technology2857.1 %
travel_geography2857.1 %

English side: mean 23.3 words, median 21, max 80. Each voice draws its 99 slots round-robin across domains, so one voice's corpus spans the taxonomy instead of clustering.

6. Emotion block: LoRA, lambda, prompt, sampling

Adapter: TTS-AGI/moss-emotion-loras-v3, subfolder=<EmotionSlug>, one rank-64 adapter per emotion. Scaffold: TTS-AGI/moss-character-loras-refined-public :: human at 1.0 under both the free and the contained take — the published contained-emotion recipe puts it under both so the pair differs only in the containment layer.

Containment is masking, not turning the emotion down. The emotion adapter stays present; VoiceNet VULN (Vulnerability) is pushed below a matched free take with vn_VULN__low. Containment is a contrast, never an absolute. The primary knob wants a trace, 0.06–0.18, not a dose; Emotional_Numbness above ~0.05 and vn_TENS__high above ~0.06 are traps that armour the voice instead of containing it.

familycontained auxiliary adapterscontainment cue (verbatim)
angervn_VULN__low@0.12(restrained and civil, the irritation tucked under the words, keeping control by effort, a small bite only on the final words)
cognitivevn_VULN__low@0.08 + vn_COGL__high@0.05(quietly occupied and keeping most of it to yourself, tiny natural pauses, calm on the surface, still real and conversational)
joyvn_VULN__low@0.16 + vn_WARM__high@0.12(trying not to show how much this moves you, smile barely audible, warm, composed, private, natural, not cinematic)
fearvn_VULN__low@0.1 + vn_COGL__high@0.07(speaking coolly on purpose, jaw tight, trying very hard not to sound terrified, the fear still audible underneath)
sadnessvn_VULN__low@0.08(the sadness held back behind practical focus, holding it together by concentrating on the facts, a small swallowed catch, natural not flat)

Free takes instead get vn_VULN__high@0.22 with the cue (letting it out / not hiding it, warm and open, emotionally reachable, unguarded).

Family notes that override the generic recipe. Fear wants vn_COGL__high and must never get Emotional_Numbness. Joy wants a little vn_WARM__high. Sadness resists masking: measured ΔVULN reaches −3.44 but the sadness itself drops −1.07, so the honest deliverable for sadness is the open take — contained sadness is generated anyway, and labelled, so the effect is visible in the data rather than hidden by a design decision. Moderate contains, intense flattens: under masking, emotion rose at moderate (anger +0.31, cognitive +0.26) and eroded at intense (cognitive −0.35, sadness −0.27, anger −0.22).

Per-emotion table

λ intense from emotion-voice-conditions/voice0.html (identical for A and C). λ moderate is 0.5 flat for B and D. Sampling is the evolved setting from the per-emotion manual page. “λ best reward” is that page's own best-merge figure, which optimises reward rather than emotion strength — it is recorded so an ablation is possible, but the corpus uses the intense/moderate column.

emotionλ intense (A,C)λ moderate (B,D)familytemptop_ptop_kλ best reward
Affection0.750.5joy0.90.95250.5
Amusement1.50.5joy1.10.95301.5
Anger1.90.5anger1.00.9400.5
Astonishment_Surprise1.50.5cognitive1.00.95251.5
Awe0.50.5joy1.10.95250.5
Bitterness1.00.5anger0.90.95250.5
Concentration1.90.5cognitive0.90.95250.5
Confusion1.90.5cognitive1.00.9300.5
Contemplation1.250.5cognitive1.10.95250.5
Contempt1.50.5anger1.10.9300.5
Contentment1.00.5joy1.00.9400.5
Disappointment0.50.5sadness1.10.9401.5
Disgust1.50.5anger1.050.95300.5
Distress1.50.5fear0.90.95251.0
Doubt1.00.5cognitive1.150.9250.5
Elation1.250.5joy1.050.9250.5
Embarrassment1.750.5fear1.050.9300.5
Emotional_Numbness1.50.5sadness0.80.9400.5
Fatigue_Exhaustion1.90.5sadness1.10.95250.5
Fear1.750.5fear0.850.9400.5
Helplessness1.90.5fear0.90.9250.5
Hope_Enthusiasm_Optimism1.750.5joy1.00.9251.5
Impatience_and_Irritability1.90.5anger1.00.9250.5
Infatuation1.00.5joy1.10.95400.5
Interest0.50.5cognitive1.150.95400.5
Intoxication_Altered_States_of_Consciousness1.750.5fear1.00.9300.5
Jealousy_and_Envy0.750.5anger1.150.95250.5
Longing1.50.5sadness1.050.9250.5
Malevolence_Malice1.50.5anger1.050.9400.5
Pain1.90.5fear1.00.9250.5
Pleasure_Ecstasy0.50.5joy1.150.9251.5
Pride1.00.5joy1.050.95250.5
Relief1.250.5joy1.20.95301.0
Sadness1.250.5sadness1.00.95401.0
Sexual_Lust1.50.5joy1.00.95250.5
Shame1.250.5fear0.90.95250.5
Sourness1.250.5anger1.20.9300.5
Teasing1.750.5joy1.20.95300.5
Thankfulness_Gratitude0.50.5joy1.050.9400.5
Triumph1.750.5joy0.90.95300.5
Deliberate deviation, stated. For 21 of the 40 emotions the manual measured the evolved prompt without a LoRA to beat every LoRA merge on total reward. This corpus nonetheless loads the emotion adapter at the published intensity λ, because the emotion adapter is the axis being varied and the reward those pages maximise is dominated by its own (1−WER) factor (correlation +0.91 to +0.98) rather than by emotion. The evolved prompt is used as well — so every take is “BASE_P + LoRA”, the union of both best practices — and every component is stored separately so the ablation can be run later without regenerating anything.

7. VoiceNet block: 57 dimensions × 4 levels

Adapter: laion/moss-voicenet-dimension-loras, 114 adapters named vn_<CODE>__high / vn_<CODE>__low.

Correction to the brief. The label set “extremely low / moderately low / moderately high / very high” does not appear in the VoiceNet manual. What exists is (a) 7 ordinal levels 0–6 with a full paragraph anchor each — except BKGN which has 5 and EXPL which has 3 — and (b) a caption generator using the adverb ladder extremely > very > notably > somewhat. The four requested levels are therefore realised as a dose ladder on the measured best dose, with the caption built from the taxonomy's own anchor for the corresponding level:

leveladapter directiondosetarget anchor level (7-level dims)adverb
extremely low__low100 % of the measured best low dose0extremely
moderately low__low40 %2somewhat
moderately high__high40 %4notably
very high__high100 % of the measured best high dose6very

The 40 % step is used because the published per-dimension sweeps (25/50/75/100/125 %) are monotone in the target score, so a fraction of the best dose is the documented way to ask for some rather than all of a dimension. For the 5-level and 3-level dimensions the ladder is mapped proportionally (0/1/3/4 and 0/1/1/2), which is why a hard-coded 0/2/4/6 was replaced by a fractional map.

All 57 dimensions with their measured best doses

codenamelevelsbest low dosebest high dosedoses used: xlow / modlow / modhigh / vhigh
TEMPTempo70.751.250.75 / 0.3 / 0.5 / 1.25
CHNKChunking70.51.250.5 / 0.2 / 0.5 / 1.25
SMTHSmoothness71.251.251.25 / 0.5 / 0.5 / 1.25
CLRTArticulation Clarity70.751.250.75 / 0.3 / 0.5 / 1.25
RANGPitch Range71.251.251.25 / 0.5 / 0.5 / 1.25
EMPHEmphasis71.01.01.0 / 0.4 / 0.4 / 1.0
DFLUDisfluency71.251.251.25 / 0.5 / 0.5 / 1.25
STRUStructure71.01.251.0 / 0.4 / 0.5 / 1.25
STNCStance71.251.251.25 / 0.5 / 0.5 / 1.25
FOCSFocus71.251.251.25 / 0.5 / 0.5 / 1.25
VULNVulnerability71.251.251.25 / 0.5 / 0.5 / 1.25
GENDPerceived Gender71.251.251.25 / 0.5 / 0.5 / 1.25
AGEVVoice Age71.251.01.25 / 0.5 / 0.4 / 1.0
REGSRegister71.01.251.0 / 0.4 / 0.5 / 1.25
VALNValence70.251.250.25 / 0.1 / 0.5 / 1.25
AROUArousal70.51.00.5 / 0.2 / 0.4 / 1.0
VOLTVolatility70.751.250.75 / 0.3 / 0.5 / 1.25
RESPRespiration71.251.01.25 / 0.5 / 0.4 / 1.0
TENSTension70.251.250.25 / 0.1 / 0.5 / 1.25
COGLCognitive Load71.01.01.0 / 0.4 / 0.4 / 1.0
ATCKAttack70.51.250.5 / 0.2 / 0.5 / 1.25
BRGTBrightness70.51.00.5 / 0.2 / 0.4 / 1.0
ROUGRoughness70.51.250.5 / 0.2 / 0.5 / 1.25
HARMHarmonicity71.251.251.25 / 0.5 / 0.5 / 1.25
FULLFullness70.751.250.75 / 0.3 / 0.5 / 1.25
WARMWarmth71.251.251.25 / 0.5 / 0.5 / 1.25
METLMetallic Character70.751.00.75 / 0.3 / 0.4 / 1.0
ESTHEsthetics71.01.251.0 / 0.4 / 0.5 / 1.25
VFLXVelocity Flux71.01.251.0 / 0.4 / 0.5 / 1.25
DARCDynamic Arc70.251.250.25 / 0.1 / 0.5 / 1.25
ARSHArousal Shift71.251.01.25 / 0.5 / 0.4 / 1.0
VALSValence Shift71.251.01.25 / 0.5 / 0.4 / 1.0
RCQLRecording Quality71.251.251.25 / 0.5 / 0.5 / 1.25
BKGNBackground Noise50.51.00.5 / 0.2 / 0.4 / 1.0
EXPLContent Appropriateness (3-point Scale)30.51.250.5 / 0.2 / 0.5 / 1.25
R_CHSTChest Resonance70.51.250.5 / 0.2 / 0.5 / 1.25
R_THRTThroat Resonance70.751.250.75 / 0.3 / 0.5 / 1.25
R_ORALOral Resonance71.01.01.0 / 0.4 / 0.4 / 1.0
R_MASKMask Resonance70.51.250.5 / 0.2 / 0.5 / 1.25
R_NASLNasal Resonance70.251.00.25 / 0.1 / 0.4 / 1.0
R_HEADHead Resonance70.251.250.25 / 0.1 / 0.5 / 1.25
R_MIXDMixed Resonance70.251.250.25 / 0.1 / 0.5 / 1.25
S_CASUCasual Style71.251.251.25 / 0.5 / 0.5 / 1.25
S_CONVConversational Style71.251.251.25 / 0.5 / 0.5 / 1.25
S_FORMFormal Style71.01.251.0 / 0.4 / 0.5 / 1.25
S_DRAMDramatic Style71.251.01.25 / 0.5 / 0.4 / 1.0
S_NARRNarrator Style71.251.251.25 / 0.5 / 0.5 / 1.25
S_NEWSNewsreader Style70.51.250.5 / 0.2 / 0.5 / 1.25
S_TECHTeacher/Didactic Style70.251.250.25 / 0.1 / 0.5 / 1.25
S_AUTHAuthoritative Style70.251.250.25 / 0.1 / 0.5 / 1.25
S_PLAYPlayful Style70.751.250.75 / 0.3 / 0.5 / 1.25
S_CARTCartoonish Style70.51.250.5 / 0.2 / 0.5 / 1.25
S_ASMRASMR Style71.251.251.25 / 0.5 / 0.5 / 1.25
S_WHISWhisper-Talk Style71.01.01.0 / 0.4 / 0.4 / 1.0
S_RANTRanting/Angry Style70.251.250.25 / 0.1 / 0.5 / 1.25
S_STRYStorytelling Style71.251.01.25 / 0.5 / 0.4 / 1.0
S_MONOMonologue Style71.250.751.25 / 0.5 / 0.3 / 0.75

8. Edge cases

Fourteen per language: 8 from emotion-voice-conditions/voice0.html (carrier line and λ as published) and 6 hall-of-fame genomes from moss-emotion-edgecase-evolution (a genetic search, population 24, 6 generations, elitism 8, best-of-4 per genome; mean LoRA lift +0.147). The GA genomes are used verbatim: their GENERAL text, delivery cue, inline burst tags, carrier line, λ and sampling are the winning genome, not a paraphrase.

sourceidemotion adapterλ*burst tagscarrier (EN)
voice0.htmlfear_screamemo_Fear0.75No, no, please stay back, do not come any closer to me, oh god, somebody, anybody, please …
voice0.htmlpain_screamemo_Pain0.75My leg, my leg, something is horribly wrong with it, I cannot move at all, oh it hurts, it…
voice0.htmlpain_groanemo_Pain0.75Just give me a moment here, do not touch it, every little movement sends this deep, grindi…
voice0.htmlcold_shiveremo_Fear0.5I have been out here in the freezing snow for hours now, I cannot feel my hands anymore, p…
voice0.htmlamused_laughteremo_Amusement1.0Wait, wait, you actually said that to his face, in front of everyone, oh that is honestly …
voice0.htmlsad_cryingemo_Sadness0.75I really thought this time would finally be different for us, but it is over now, and I ju…
voice0.htmlwhimperingemo_Fear0.6Please do not leave me here all alone in the dark like this, I am so scared and I do not k…
voice0.htmltearsemo_Pain0.75It hurts so much and I cannot make it stop, I have tried everything I can think of, please…
edge-case GAga_fear_screamemo_Fear0.75<terrified scream><screaming>Help me. Somebody, please.
edge-case GAga_pain_screamemo_Pain0.75<cry of pain><screams in pain>I can't - I can't do this anymore.
edge-case GAga_sad_cryemo_Sadness0.75<whimpers><voice breaks>I can't - I can't do this anymore.
edge-case GAga_cold_shiveremo_Fear0.5[shivers]<trembling breath>P-please, I need to get warm.
edge-case GAga_pain_groanemo_Pain0.75<pained grunt>Help me. Somebody, please.
edge-case GAga_amuse_laughemo_Amusement1.5<giggles><warm laughter>I can't believe you just said that.
Non-verbal sizing. tokens defaults to the word count, and a scream carrier has almost no words — which is how a scream group ends up asking for ~5 tokens and producing 0.3 s of audio. Edge groups are sized by intended duration at 12.5 tokens per second, with max_new_frames raised to 1.6× the token budget. The German carriers for the edge cases are fixed translations held in the spec, because for these groups the carrier line is the content and must not vary.

Published cross-voice identity for these cells, worst first: fear scream 0.504 · laughter 0.525 · pain groan 0.564 · pain scream 0.592 · cold shiver 0.594 · whimpering 0.598 · crying 0.599 · tears 0.639. Loud extremes clone worst; quiet extremes clone best.

9. Sports commentator and explicitness

Sports: laion/moss-sports-commentator-lora, checkpoint real_r64_e8 at λ 1.0. The real-data-only checkpoint beat the mixed one on 11 of 12 prompts (Wilcoxon p = 0.0010; judge 1.979 vs 1.891, arousal 4.633 vs 3.914, WER 0.066 vs 0.061, n.s.), which is why real_r64_e8 is used rather than the otherwise-tempting r64_e8.

Explicitness: TTS-AGI/moss-explicitness-loras, checkpoint aesthetic_mix_r32 at λ 0.8, sampling temp 0.9 / top_p 0.95 / top_k 35 — the rank-32 aesthetic mix, which won the published raw sweep, in the 0.2–1.0 blend band. Gated by §4.

10. Exact prompt templates

The processor is driven exactly like this. instruction holds the WHOLE GENERAL: … SCRIPT: … caption; text holds ONLY the spoken words. An empty field renders as the literal string "None".

from transformers import AutoModel, AutoProcessor   # AutoModel, NOT AutoModelForCausalLM
proc = AutoProcessor.from_pretrained("laion/moss-tts-local-transformer-4.55b-voice-acting-v2",
                                     trust_remote_code=True,
                                     codec_path="OpenMOSS-Team/MOSS-Audio-Tokenizer-v2")
proc.audio_tokenizer = proc.audio_tokenizer.to("cuda").eval()
base = AutoModel.from_pretrained("laion/moss-tts-local-transformer-4.55b-voice-acting-v2", trust_remote_code=True,
                                 dtype=torch.bfloat16, attn_implementation="sdpa").cuda().eval()
# the missing audio_lm_heads.* / text_lm_head.weight warnings on load are BENIGN

msg = proc.build_user_message(text=spoken_words_only,
                              instruction=whole_GENERAL_SCRIPT_caption,
                              language="English",          # or "German"
                              reference=[ref_wav_path],
                              tokens=n_tokens)             # defaults to the WORD COUNT
batch = proc([[msg]], mode="generation")
out = net.generate(input_ids=batch["input_ids"].cuda(),
                   attention_mask=batch["attention_mask"].cuda(),
                   max_new_frames=400, do_sample=True,
                   text_temperature=0.7, text_top_k=50, text_top_p=1.0,
                   audio_temperature=T, audio_top_p=P, audio_top_k=K,
                   audio_repetition_penalty=1.1)
for m in proc.decode(out):
    if not m.audio_codes_list:          # DETECT this. Never assume a token fix worked.
        empty += 1; continue

LoRA merge scale

base_scaling = {nm: dict(m.scaling) for nm, m in pm.named_modules()
                if isinstance(m, LoraLayer)}          # captured ONCE, after loading

pm.base_model.enable_adapter_layers()
pm.base_model.set_adapter(list(keys))                  # base_model, not PeftModel
for nm, m in pm.named_modules():
    if isinstance(m, LoraLayer):
        for adapter, lam in keys.items():
            if adapter in m.scaling:
                m.scaling[adapter] = base_scaling[nm][adapter] * lam

PeftModel.set_adapter and base_model.set_adapter do not take the same argument. This pair is copied verbatim from $NB/act/code/actworker_v9.py; a hand-rewrite cost a whole nine-job run.

Three real captions from this corpus

Emotion, condition C (intense + contained), Fear:

GENERAL: A voice powerfully expressing fear, a terrified voice, trembling and breathless, shaking with fear, near screaming, in every breath. The feeling is fought down rather than shown: it is held in and only leaks through at the edges of phrases.
SCRIPT:
(speaking coolly on purpose, jaw tight, trying very hard not to sound terrified, the fear still audible underneath) "We were supposed to meet at the corner near the old station around six, but the bus was running late again."

VoiceNet, TEMP at “very high” (vn_TEMP__high@1.25):

GENERAL: A voice very high in tempo. The tempo reaches the absolute human limit of linguistic speed, resulting in a blistering, hyper-accelerated wall of sound. Phonation is extremely dense, causing individual word boundaries to completely blur into a continuous, high-velocity acoustic vibration.
SCRIPT:
(neutral, natural delivery, exactly as this voice normally speaks) "We were supposed to meet at the corner near the old station around six, but the bus was running late again."

Edge case, GA hall-of-fame genome, fear → screaming:

GENERAL: A horrified voice, blood-curdling, pushed to the extreme edge of scream.
SCRIPT:
(terrified, screaming, voice cracking with panic) "Help me. Somebody, please." <terrified scream><screaming>

All 40 evolved GENERAL lines and delivery cues

These are the manual's own evolved (BASE_P) prompts, used verbatim for the intense conditions. For the moderate conditions the intensifier is softened by a fixed substitution table (overwhelmingly→mildly, intensely→mildly, deeply→slightly, powerfully→mildly, utterly→slightly, unmistakably→faintly, viscerally→slightly, to the extreme→a little) plus one added sentence, so that A/B and C/D stay comparable in vocabulary. For the contained conditions the cue below is replaced by the family containment cue from §6 and a containment sentence is appended to GENERAL.

emotionGENERAL (evolved, verbatim)delivery cue (free conditions)
AffectionA voice intensely expressing affection, a warm, tender voice overflowing with affection, soft and caring, a gentle smile in every word, impossible to hide.(warmly, tenderly, full of affection)
AmusementA voice overwhelmingly expressing amusement, a voice bubbling with amusement, on the edge of laughter, playful and delighted, impossible to hide.(chuckling, highly amused, barely holding back laughter)
AngerA voice overwhelmingly expressing anger, a furious voice, seething and exploding into a rant, sharp, loud and cutting, building and building.(furious, ranting, exploding with rage)
Astonishment_SurpriseA voice unmistakably expressing astonishment surprise, a voice struck with astonishment, gasping, utterly surprised, eyes wide, pouring out.(gasping, astonished, taken completely by surprise)
AweA voice utterly expressing awe, a hushed voice filled with awe and wonder, breath taken away, reverent, impossible to hide.(in hushed awe and wonder)
BitternessA voice deeply expressing bitterness, a bitter, resentful voice, jaded and sardonic, dripping with disillusion, in every breath.(bitterly, with jaded resentment)
ConcentrationA voice intensely expressing concentration, a focused, deliberate voice, fully concentrated, measured and precise, raw and unfiltered.(intensely focused and concentrated)
ConfusionA voice powerfully expressing confusion, a baffled, disoriented voice, struggling to make sense of things, hesitant and lost, pouring out.(confused, bewildered, thrown off)
ContemplationA voice to the extreme expressing contemplation, a slow, thoughtful voice, deep in contemplation, musing and reflective, in every breath.(slowly, deep in contemplative thought)
ContemptA voice to the extreme expressing contempt, a cold, sneering voice, full of contempt and disdain, looking down with scorn, pouring out.(with cold, sneering contempt)
ContentmentA voice utterly expressing contentment, a relaxed, satisfied voice, at peace and content, easy and unhurried, in every breath.(calmly content and at ease)
DisappointmentA voice viscerally expressing disappointment, a deflated, let-down voice, heavy with disappointment, quietly crushed, in every breath.(deeply disappointed, deflated)
DisgustA voice intensely expressing disgust, a revolted voice, curling with disgust, repulsed and sickened, in every breath.(with revulsion and disgust, sickened)
DistressA voice powerfully expressing distress, a distressed, anguished voice, tight with panic and pain, on the verge of breaking, in every breath.(in acute distress and anguish)
DoubtA voice powerfully expressing doubt, a skeptical, uncertain voice, hedging and unconvinced, full of doubt, pouring out.(doubtfully, deeply unconvinced)
ElationA voice utterly expressing elation, a soaring, jubilant voice, elated and euphoric, bursting with joy, in every breath.(elated, euphoric, bursting with joy)
EmbarrassmentA voice unmistakably expressing embarrassment, a flustered, sheepish voice, cheeks burning with embarrassment, awkward and shrinking, impossible to hide.(flustered and mortified with embarrassment)
Emotional_NumbnessA voice utterly expressing emotional numbness, a flat, hollow, emotionally numb voice, detached and empty, drained of all feeling, in every breath.(flatly, hollow and emotionally numb)
Fatigue_ExhaustionA voice intensely expressing fatigue exhaustion, a weary, exhausted voice, heavy and dragging, barely able to stay awake, raw and unfiltered.(utterly exhausted, weary and dragging)
FearA voice powerfully expressing fear, a terrified voice, trembling and breathless, shaking with fear, near screaming, in every breath.(trembling, terrified, voice shaking with fear)
HelplessnessA voice unmistakably expressing helplessness, a powerless, defeated voice, pleading and helpless, out of options, impossible to hide.(helplessly, defeated and powerless)
Hope_Enthusiasm_OptimismA voice deeply expressing hope enthusiasm optimism, a bright, hopeful voice, brimming with enthusiasm and optimism, uplifting, impossible to hide.(brightly, full of hope and enthusiasm)
Impatience_and_IrritabilityA voice utterly expressing impatience and irritability, a tense, irritable voice, snapping with impatience, on a short fuse, pouring out.(impatiently, irritable and snappy)
InfatuationA voice to the extreme expressing infatuation, a dreamy, smitten voice, lovestruck and breathless with infatuation, impossible to hide.(dreamily infatuated, lovestruck)
InterestA voice viscerally expressing interest, a keenly interested voice, leaning in, curious and engaged, with every word.(keenly interested and curious)
Intoxication_Altered_States_of_ConsciousnessA voice overwhelmingly expressing intoxication altered states of consciousness, a woozy, slurring voice, intoxicated and untethered, in an altered haze, impossible to hide.(woozy, slurring, intoxicated)
Jealousy_and_EnvyA voice intensely expressing jealousy and envy, a jealous, envious voice, seething with covetous resentment, bitter and possessive, in every breath.(with jealous, envious resentment)
LongingA voice unmistakably expressing longing, an aching, yearning voice, full of wistful longing, reaching for what is out of reach, with every word.(with aching, wistful longing)
Malevolence_MaliceA voice deeply expressing malevolence malice, a menacing, malicious voice, cruel and threatening, savoring the harm, in every breath.(with cruel, menacing malice)
PainA voice to the extreme expressing pain, a voice wracked with pain, gasping and groaning, near screaming in agony, raw and unfiltered.(groaning, gasping in pain and agony)
Pleasure_EcstasyA voice intensely expressing pleasure ecstasy, a voice breathless with pleasure and ecstasy, rapturous and overwhelmed, with every word.(breathless with pleasure and ecstasy)
PrideA voice overwhelmingly expressing pride, a proud, self-assured voice, chest swelling with pride, triumphantly boastful, impossible to hide.(with swelling, self-assured pride)
ReliefA voice deeply expressing relief, a voice flooding with relief, exhaling the tension, grateful it is finally over, in every breath.(exhaling in profound relief)
SadnessA voice powerfully expressing sadness, a soft, grief-worn voice, heavy and slow, on the edge of tears, impossible to hide.(quietly, grief-stricken, near tears)
Sexual_LustA voice unmistakably expressing sexual lust, a husky, sultry voice, low and breathy, thick with desire and longing, pouring out.(huskily, low and breathy with desire)
ShameA voice deeply expressing shame, a small, shame-filled voice, cringing and self-reproaching, unable to look up, building and building.(with cringing shame and self-reproach)
SournessA voice intensely expressing sourness, a sour, grumbling voice, peevish and put-out, curdled with displeasure, with every word.(sourly, grumbling and peevish)
TeasingA voice to the extreme expressing teasing, a playful, teasing voice, sing-song and mischievous, poking fun, pouring out.(playfully teasing, mischievous)
Thankfulness_GratitudeA voice intensely expressing thankfulness gratitude, a warm, heartfelt voice, full of gratitude and thanks, deeply touched, raw and unfiltered.(warmly, full of heartfelt gratitude)
TriumphA voice unmistakably expressing triumph, a triumphant, victorious voice, roaring with the thrill of winning, exultant, in every breath.(triumphantly, roaring with victory)

Two decisions about vocal bursts, stated

The burst adapters in laion/vocal-burst-lora-adapters (64 classes) are not merged in this corpus. The edge cases instead carry the GA's inline burst tags in the SCRIPT, which is what the edge-case search actually optimised. If burst adapters are added later, the measured operating points are: λ = 0.50 (presence 50.3 %, tail coverage 0.90, joint 0.448 — the peak; at 1.0 presence rises to 72 % but tail coverage collapses to 0.45 and WER to 0.57), the emotion adapter must sit at or below half the burst dose, and the tag goes inline mid-line with real words after it, never in the first or last 0.45 s. Five classes never fire at any dose: Hiss, Kissing Noises, Lip Smack, Person Whistling Playfully, Slurping Noises.

Batching by adapter

Groups are sorted by (block, emotion|dim|edge, condition|level, lang) and each worker takes a contiguous slice. That matters: with 114 dimension adapters and 40 emotion adapters, a stride slice (groups[shard::nshards]) would give a worker groups 32 apart in the sorted order, so no two consecutive groups would share an adapter and the LoRA loader would thrash on every single group. Adapters are loaded lazily with an LRU cap of 24 resident at once.

11. Ranking, per condition type

The base formula is the published one:

core  = z(genuineness) + w_blend · z(vocal-burst blend) + 1.25 · z(strength)
        [ + 1.0 · z(−VULN)   for contained conditions only ]
score = sigmoid(core / 2) · (1 − min(WER,1)) · (0.5 + 0.5 · naturalness)
        · (0.81 + 0.19 · clip(spk_sim,0,1)/0.7) · id_mult

All z-scores are taken within the group, over its 200 candidates — which is what makes the components comparable across conditions with wildly different absolute scales.

termfree conditions (A, B)contained conditions (C, D)why
w_blend1.00.6an audible vocal burst is the emotion escaping, which is the opposite of containment
containment termnot applied+1.0 · z(−VULN)containment is measured as VULN below the group's own mean, i.e. as a contrast, never as an absolute
strength (A, C: intense)target EmoNet score, maximisedtarget EmoNet score, maximisedintense rows want as much as they can get
strength (B, D: moderate)band fitnessband fitnessmoderate rows are scored for LANDING inside a band, not for maximising
strength (VoiceNet block)signed target-dimension value+1 for a __high group, −1 for a __low group

Target bands for the moderate rows, and floors for the intense rows, by family:

familymoderate bandintense floor
anger[1.0, 1.9]2.4
fear[0.9, 1.6]2.0
sadness[1.0, 1.8]2.3
joy[0.6, 1.1]1.5
cognitive[0.5, 1.0]1.2

Naturalness = 0.6 · disfluency-band term + 0.4 · speed-band term. Disfluency: full credit 2.5–4.0, capped at 0.55 below 1.8 (robotic), decaying above 4.0 (a mess). Speed: full credit 2.4–3.3 words/s, penalised on both sides.

Identity enters as a ranking weight of 0.19 and a single hard floor at 0.4 (id_mult = 0.25 below it). Nothing is rejected for being below 0.58 or 0.68 — the 0.58 threshold only sets a resample_flag in the group statistics, because with 200 candidates the size of the pool already does the job the resample loop used to do.

Every component is stored separatelyz_genuineness, z_blend, z_strength, z_containment, strength_raw, core, naturalness, id_mult, w_blend, wer, spk_sim — so any later re-ranking needs no regeneration. That is not a nicety: the published post-mortems found (1−WER) correlating +0.91 to +0.98 with the composite while genuineness correlated +0.00, and three of eight terms effectively dead. A stored-component design is what lets that be fixed after the fact.

12. Per-candidate metadata schema

Every candidate gets a row, including the worst-ranked one. Nothing is discarded.

columnswhat it is
gid, voice, profile, block, lang, emotion, condition, dim, level, edgeidentity of the cell
text, text_slot, caption, adapters, sampling, mediathek, domainexactly what was asked for, including the JSON adapter/λ dict
asr, wer, wps, dur, emptywhisper-large-v3-turbo transcript used for in-loop WER (language forced per group)
parakeet_text, parakeet_words, parakeet_nwordsParakeet v3 word-level timestamps, added by the stage-2 pass
voicenet (57), voicenet_bucket (57)continuous regression value and ordinal bucket for every dimension
emonet (40), emo_strength, emo_argmaxEmpathic-Insight / EmoNet per-emotion intensities
genuineness, blend, quality, quality_fullgenuineness 0–6, vocal-burst blend 0–10, four quality heads
voiceclap (768, fp16)VoiceCLAP-commercial embedding — stored now because regenerating it later is waste
spk_emb (192, fp16), spk_sim, ref_spk_emb.npyECAPA embedding of the candidate, cosine to the reference; the reference embedding is identical for every row so it is stored once per shard
caption_genprocedurally generated caption written from what was MEASURED, not from what was asked
rank, score, z_genuineness, z_blend, z_strength, z_containment, strength_raw, core, naturalness, id_mult, w_blend, contained, moderatewithin-group rank and every score component
vuln, tempo, chunk, dflu, arou, expl, tens, narration, dim_targetthe dimensions the ranking actually reads, promoted to top-level columns
audio_keythe tar member name — the join key to the audio

13. Storage layout

Containers only. Never loose files. 808 groups × 32 candidates × 6,000 voices is 155 million objects. On this cluster that is not a performance question, it is a hard constraint — writing 100k+ small files is prohibited. Audio goes into WebDataset tars, metadata into parquet, and nothing else is written.
out/<voice_cid>/P<profile>/
    cands-<shard>.tar                # WebDataset: <gid>.c<NNN>.mp3, one member per candidate
    cands-<shard>.parakeet.parquet   # stage-2 word timestamps, joined on audio_key
    meta-<shard>-<ts>.parquet        # one row per candidate, schema above
    groupstats-<shard>.jsonl         # one line per group: timings, empties, best-take summary
    throughput-<shard>.json          # measured gen/GPU-hour for this shard
    ref_spk_emb.npy                  # the reference ECAPA embedding, stored once
    safety_gate.json                 # the gate decision and its three inputs
    shard<NNN>.DONE                  # idempotent-resume marker

Audio is mono MP3 at 16 kHz. The tar member name is the audio_key column, so audio and metadata join without a manifest. Shards are written append-only and the worker re-reads groupstats on restart, so an interrupted job resumes at group granularity.

14. Compute estimate: 100 / 1,000 / 6,000 voices

blockgroupscandidatesmean gen s/groupmean score s/groupgen / GPU-hourempty decodes
edge5611200329132,1060.00%
emotion640128000331132,0920.01%
explicit4800312122,2200.00%
sports4800157124,2630.00%
voicenet912182400322132,1460.17%
all16163232002,1260.10%

Extrapolating at production settings (32 candidates/group), using the per-block measured rates above rather than a single average — the blocks differ by more than 3× and a single average would flatter the estimate:

voicesgenerationsGPU-hoursnode-hours (4 GPU/node)wall-clock h on 64 GPUswall-clock h on 256 GPUsstorage TB
1808 × 32 × 1 = 25,8561230.20.00.0
100808 × 32 × 100 = 2,585,6001,21630419.04.80.3
1,000808 × 32 × 1,000 = 25,856,00012,1643,041190.147.52.9
6,000808 × 32 × 6,000 = 155,136,00072,98218,2461,140.3285.117.2

One voice costs 12.16 GPU-hours at 32 candidates per group. Storage is measured at 111 kB per candidate (MP3 + parquet row including both embeddings) from the demo artefacts.

Assumptions

The weakest link

It is the voicenet block, and the reason is count, not speed. Measured per-candidate throughput is nearly flat across the blocks — sports 4,263 gen/GPU-h against emotion 2,092, a spread of only 2.04× — so cost tracks the number of groups almost exactly. The voicenet block is 56 % of the matrix and therefore 56 % of the GPU-hours.

That has a useful consequence: there is no clever optimisation hiding here. Nothing is pathologically slow, so the only real lever is generating fewer cells. Halving the voicenet block — two levels instead of four, or the 30 highest-|Δ| dimensions instead of all 57 — takes 28 % straight off the total, and no amount of batching or kernel work will do the same.

Secondary constraint: the scoring stack is 4–5 % of wall time only because the VoiceCLAP embedder is shared across the VoiceNet, genuineness and blend heads — one encode per clip instead of three. Un-sharing it would roughly triple that term.

Is 6,000 voices feasible?

At the full 808-group matrix, no — not as a single campaign. It is 72,982 GPU-hours, which at 256 GPUs is 285 hours of wall clock of uninterrupted whole-partition time, and it produces 17 TB. That is a program, not a run.

Defensible subset. Three cuts, in the order they should be taken:

  1. Full matrix on 100 voices stratified over the reference pool by gender, AGEV band and DNSMOS — enough to establish that the conditioning transfers across voices. 1,216 GPU-hours.
  2. Reduced matrix on 1,000 voices: 40 emotions × 2 conditions (A and C — the two that actually differ, since B and D are both λ 0.5) × 2 languages, the 20 highest-|Δ| VoiceNet dimensions × 2 extreme levels × 2 languages, all 14 edge cases, sports and explicitness = 270 groups, one third of the matrix.
  3. Emotion block only on 6,000 voices if per-speaker emotion coverage is what the downstream model needs: 320 groups is 40 % of the matrix but the fastest 40 %.

15. Reproducing this from nothing

NB=/e/data1/datasets/playground/mmlaion/schuhmann1/dramabox
export HF_HOME=$NB HF_HUB_CACHE=$NB/hfcache/.cache/dramabox
# 1. LOGIN NODE ONLY - compute nodes have no internet
$NB/env_transcribe/bin/python $NB/vprof/code/prefetch.py     # datasets + LoRA repos
$NB/env_transcribe/bin/python $NB/vprof/code/vpprep.py       # voices, text pool, matrix
# 2. GPU - 16 nodes x 4 GPUs, 32 shards x 2 profiles
sbatch --array=0-15 --export=ALL,VOICE=<cid>,CANDS=32,BATCH=32,NSH=32 \
       $NB/vprof/code/vprof.sbatch
# 3. stage-2 ASR, in the NeMo venv (never pip-install nemo into env_transcribe)
$NB/env_asr/bin/python $NB/vprof/code/vpasr.py --indir $NB/vprof/out/<cid>/PA
# 4. grid + docs
$NB/env_transcribe/bin/python $NB/vprof/code/vpgrid.py --voice <cid>
$NB/env_transcribe/bin/python $NB/vprof/code/vpdocs.py --voice <cid>

Cluster constraints that are not optional. There is no system python — use $NB/env_transcribe/bin/python. Compute nodes are offline; run with HF_HUB_OFFLINE=1 after pre-fetching everything on the login node. Stagger worker startup by ~150 s on a multi-GPU node: concurrent import transformers from /e puts every worker into uninterruptible sleep. Never write to $HOME (~20 GB quota). Launch long jobs from setsid-detached scripts. Never pip install without --no-deps into this venv — it has been destroyed that way by a torch downgrade.

Bill of materials

rolerepo / packagenotes
base modellaion/moss-tts-local-transformer-4.55b-voice-acting-v2load with AutoModel, not AutoModelForCausalLM; bf16; attn_implementation="sdpa"
audio codecOpenMOSS-Team/MOSS-Audio-Tokenizer-v2passed to the processor as codec_path=
emotion LoRAsTTS-AGI/moss-emotion-loras-v340, subfolder = emotion slug
VoiceNet dim LoRAslaion/moss-voicenet-dimension-loras114 = 57 × __high/__low
character scaffoldTTS-AGI/moss-character-loras-refined-publicsubfolder human/ep3 — note the extra epoch level
sportslaion/moss-sports-commentator-lorareal_r64_e8
explicitnessTTS-AGI/moss-explicitness-lorasaesthetic_mix_r32
Mediathek (Profile B)laion/moss-mediathek-emotion-lorar64_e2 at 0.25
burst LoRAs (not merged)laion/vocal-burst-lora-adapters64 classes
reference voicesTTS-AGI/moss-reference-voices-consolidateddataset, 12 tar shards + annotations
textHuggingFaceFW/finetranslationsdataset, data/deu_Latn/
VoiceNet + captionslaion/voicenet-dimension-predictors-commercial57 dims, regression + classification heads, dimensions.py
EmoNet / quality / agelaion/Empathic-Insight-Voice-Plus40 emotion heads, 4 quality heads, model_Age_best.pth
encoder for the headslaion/BUD-E-Whispershared Whisper encoder
genuinenesslaion/voiceclap-commercial-genuineness0–6
burst blendlaion/voiceclap-commercial-vocalburst-blend0–10
VoiceCLAP embeddinglaion/voiceclap-commercial768-d, shared across VoiceNet/genuineness/blend — one encode per clip
speaker embeddingspeechbrain/spkrec-ecapa-voxceleb192-d
timbre embedding (evaluated)Orange/Speaker-wavLM-tbrAUC 0.794
in-loop ASR / WERopenai/whisper-large-v3-turbolanguage forced per group
word timestampsnvidia/parakeet-tdt-0.6b-v3stage 2, in env_asr (NeMo 2.7.3); disable the CUDA-graph TDT decoder on GH200
voice conversionLAION-AI/chatterbox-voice-conversionfrom chatterbox_vc.convert import VoiceConverter, 24 kHz out
DNSMOSspeechmosdnsmos.run(x16k, 16000)['ovrl_mos']

16. What is assumed, and what could not be verified

  1. The A/B/C/D stage-direction text is not published. Only the four sublabel strings exist publicly. The captions here are built from the per-emotion evolved prompt with a documented softening rule for the moderate rows and the published containment cues for the contained rows. This is a reconstruction, not the original instruction text.
  2. The 4-level VoiceNet ladder is a construction. The manual has 7 ordinal levels and an adverb ladder; the mapping from “extremely low … very high” to a dose and an anchor level is defined in §7 and is ours.
  3. The 40 % moderate dose rests on the published sweeps being monotone. It was not separately validated at 40 %.
  4. The finetranslations domain taxonomy is derived, not given. subsets.csv is a language table. The URL-host + keyword labeller is ours and is stored per row so it can be replaced.
  5. German carriers for the edge cases are fixed translations written into the spec, not drawn from finetranslations, because for those groups the carrier line is the content.
  6. The emotion family map is ours. The published material names five families and gives recipes for a handful of anchor emotions; assigning all 40 emotions to a family is an extrapolation, and Helplessness in particular sits between the fear and sadness families.
  7. The cognitive family's target band [0.5, 1.0] is marked “extrapolated” in the source and is carried forward as such.
  8. In-loop WER uses whisper-large-v3-turbo, not Parakeet v3. Parakeet lives in a different venv (env_asr, NeMo 2.7.3) and installing NeMo into the generation venv risks a torch downgrade that has destroyed it before. Parakeet runs as stage 2 and supplies the word timestamps; because every ranking component is stored, re-ranking on Parakeet WER needs no regeneration.
  9. The Mediathek checkpoint used is laion/moss-mediathek-emotion-lora :: r64_e2 at 0.25, as specified. Note a second, differently named repo laion/moss-mediathek-hq-lora (r64_epoch3) also exists and is the one the voice-acting manual names; they were not compared.
  10. No listener study was run. Every number here is from the local sensor stack. The published post-mortems are explicit that the composite tracks a listener at only ρ ≈ +0.21 on spoken material and negatively on non-verbal material, so the ranking should be treated as a strong filter, not as ground truth.