braidio.render#

Render a Script into an audio file.

Walks the beats (filtered by the rights Profile): narration beats are synthesized (braidio.tts) — as one call, or as paced turns when the WeaveConfig asks for a smaller segmentation_unit (braidio.pacing); segment beats are resolved via a SegmentSource and extracted (padded + faded); scene breaks become a sting or a pause (braidio.structure). Every spoken or clipped part is loudness-normalized, then either woven on a timeline (clips tuck under narration — braidio.weave.weave_timeline()) when a WeaveConfig enables it, or concatenated.

This is the no-graph fast path; the same core is reused by the nw-app transforms (which add provenance + partial re-render).

Functions

render_production(script, *, source[, ...])

Render script under profile → a single audio file.

braidio.render.render_production(script, *, source, api_key=None, config=None, profile=Profile.PERSONAL, rights=None, delivery=None, cast=ConversationCast(roles={'A': 'cgSgspJ2msm6clMCkdW9', 'B': 'iP95p4xoKVk53GoZ742B'}, model_id='eleven_v3', settings={'stability': 0.45}), out_path=None, voice_id=None, crossfade_s=0.12, normalize=True, music_bed=None, structure=None, end_fade_s=0.35, end_silence_s=0.7, return_timeline=False, tts_dir='data/tts', clips_dir='data/clips', episodes_dir='data/episodes')[source]#

Render script under profile → a single audio file. Returns the path.

With return_timeline=True returns (path, TimelineBreakdown) instead — the render records what it spent time on (per-beat kind, source interval, duration, and offset) rather than leaving it to be reconstructed afterward, plus, in TimelineBreakdown.settings, the settings that produced those timings (see braidio.timeline.render_settings()). Recording them is what keeps a render reproducible: the pacing knobs below mean one script has many possible cuts, so a persisted breakdown has to say which one it is.

Segment beats are resolved through source (a SegmentSource). When config has clip_edge_overlap_s > 0, a clip is placement="under", or a music_bed is given, the parts are woven on a timeline; otherwise they are concatenated. rights (if given) sets which segment rights are publishable. music_bed lays an instrumental underscore under the whole production (see braidio.music.MusicBed).

structure (a braidio.structure.MusicStructure) is how the production marks its structure with music: a scene-break beat plays its sting (or a pause when there is none / the break is marked "none"), and a spotlit segment beat drops the bed out for its duration. None uses the inert defaults — no sting asset, no clip spotlit by default — so a script without scene breaks or spotlight flags renders exactly as before.

Pacing inside a narration beat is a config choice. By default (WeaveConfig.segmentation_unit == "beat") a beat is one TTS call — one prosodic arc, no silence anywhere in it. Set a smaller segmentation_unit and the beat is cut into turns of min_turn..max_turn units, each synthesized separately with a jittered speed_base ± speed_jitter (where the model has a speed knob) and followed by gap_turn_s scaled to how strongly the boundary closes — see braidio.pacing. Those four knobs do nothing here at the default unit, which is the historical behavior kept byte-identical.

api_key is an optional per-request ElevenLabs key threaded to every synthesized beat — both narration (braidio.tts.narrate()) and dialogue (braidio.conversation.render_dialogue()). When None (default) each synthesizer falls back to $ELEVENLABS_API_KEY (unchanged behavior); an explicit key lets a caller (e.g. a per-user BYO-key request) override the environment without mutating it. Segment beats never call ElevenLabs, so the key does not touch them.

Return type:

Path | tuple[Path, object]