braidio.multivoice#
Multi-voice narration: cycle a pool of voices across segments (issue #10).
When one voice reads flat, variety across voices is a stronger lever than any single-voice setting. This renders narration by splitting it into segments (sentences) and assigning each a voice drawn from a pool — randomly (seeded, so it’s reproducible) and avoiding immediate repeats so it doesn’t feel like a rigid round-robin. Speed is jittered slightly per segment, even within one speaker, to break regularity.
Two curated pools of premade ElevenLabs voices (all production quality,
deliberately less familiar than “George”, 2M/2F in POOL_4, wider in
POOL_MANY). For a truly large “many people / interviews” pool, the
shared Voice Library (thousands) can be tapped, but quality varies there, so
those need curation — the premade pools below are the safe default.
Functions
|
Assign a voice to each of |
|
Group consecutive segments into turns of |
|
Render |
|
Split narration into sentence-level segments (markup removed). |
|
Classes
|
A pooled narration voice. |
- class braidio.multivoice.Voice(id, name, gender, accent='', note='')[source]#
Bases:
objectA pooled narration voice.
- braidio.multivoice.assign_voices(n, pool, *, seed=0, avoid_repeats=True)[source]#
Assign a voice to each of
nturns — random, seeded, no immediate repeats (so it isn’t a rigid round-robin).
- braidio.multivoice.group_turns(segments, *, min_turn=1, max_turn=1, seed=0)[source]#
Group consecutive segments into turns of
min_turn..max_turnsegments.A turn is what one voice speaks before the next takes over. Bigger turns = each speaker talks longer (fewer switches). Each turn’s segments are joined into one utterance so prosody is continuous within a speaker. Turn sizes are seeded-random within the range.
- braidio.multivoice.render_multivoice(segments, pool, *, out_path, api_key=None, work_dir='data/tts/multivoice', seed=7, min_turn=2, max_turn=4, avoid_immediate_repeat=True, model_id='eleven_multilingual_v2', base_settings=None, speed_base=1.0, speed_jitter=0.04, crossfade_s=0.1, gap_s=0.0, target_lufs=-16.0)[source]#
Render
segmentscyclingpool→out_path.Segments are first grouped into turns of
min_turn..max_turnsegments (bigger = each voice talks longer). One voice per turn, no immediate repeat, with a jittered speed even within a speaker.gap_sinserts silence between turns (0 = none). Returns[(voice, turn_text), …]for reporting.api_keyis an optional per-request ElevenLabs key threaded to everybraidio.tts.narrate()call;None(default) keeps the$ELEVENLABS_API_KEYfallback.Note
overlapping/interrupting speakers and clip ducking are separate, upcoming parameters (tracked as issues) — this renders turns sequentially.