Nodes/ComfyUI-OldTimeRadio/ Scene Sequencer
ComfyUI Node

Scene Sequencer

Laying every line onto the timeline

By jbrick2070·Created 5 months ago·Updated about 20 hours ago· 7
Scene Sequencer
  • tts_audio_clips
  • announcer_audio_clips
  • scene_audio
  • render_log
script_json[]
start_line0
end_line999
output_dir
dialogue_offset_ms0

OTR_SceneSequencer is the editor's timeline made into a node: it takes the script, the rendered voice clips, and the music cues, and lays them all onto one continuous scene_audio track - TTS for each line, music in its place, pauses where they belong. It's the "sequence" step between the voice engines and OTR_EpisodeAssembler, and it's where a pile of individual line clips becomes something that sounds like a radio play instead of a phone call.

The required script_json is the parsed script (tooltip: from LLMScriptWriter). From it, the node knows the order of lines, who speaks, and where the music_inter beats sit.

The inputs that matter

Two audio buses feed in, and they're deliberately separate:

  • tts_audio_clips - the pre-rendered character dialogue from OTR_BatchCharacterVoices (or the Bark/Parler batch on the legacy path). Matched to dialogue lines in order; absent, lines get placeholder silence.
  • announcer_audio_clips - the announcer lines from OTR_AnnouncerVoice, consumed in script order for lines whose character is ANNOUNCER. The "Voice of God" bookends stay on their own bus, away from the character pool.

That split is the reason the announcer never accidentally reads a character line or vice versa - a separation that's easy to lose in a one-bus design.

Then the timing knobs: start_line/end_line (chunked processing - render lines 0–50, then 50–100, if you want to iterate on part of a scene) and dialogue_offset_ms (shift all dialogue on the timeline; positive = delay, negative = advance - your fix for dialogue that sits slightly late against the music). The music side takes music_cue_audio plus music_cue_manifest_json from OTR_StableAudioTheme, sliced per manifest sample count - never the padded tail. output_dir overrides where intermediates go.

Outputs: scene_audio (AUDIO - feed to OTR_EpisodeAssembler's scene_audio) and render_log.

Install and gotchas

Pack-level install (ComfyUI Manager → ComfyUI-OldTimeRadio, restart). No models here - it's audio assembly (numpy/soundfile territory). Two gotchas worth knowing. First, if dialogue and music arrive misaligned, reach for dialogue_offset_ms rather than regenerating voices - it's a 10 ms step up to ±500 ms, designed exactly for this. Second, the announcer/character bus separation is a contract: dropping announcer clips into tts_audio_clips works but breaks the Voice-of-God separation the pack relies on for consistent bookends. Keep the buses as designed and the episode will sound like it was directed rather than assembled.

CategoryOldTimeRadio

Inputs (7)

NameTypeDefaultDescription
script_jsonSTRING[]Parsed script JSON from LLMScriptWriter
tts_audio_clipsoptAUDIOPre-rendered TTS audio clips (from Bark/Parler batch). If provided, dialogue lines use these clips instead of placeholder silence. Clips are matched to dialogue lines in order. ANNOUNCER lines are NOT expected here - they flow through announcer_audio_clips on a separate bus.
announcer_audio_clipsoptAUDIOPre-rendered ANNOUNCER audio clips from KokoroAnnouncer. Consumed in script order for dialogue lines whose character_name is ANNOUNCER. Keeps the Voice of God bookends separated from the Bark character pool.
start_lineoptINT00–9999First line to render (for chunked processing)
end_lineoptINT9991–9999Last line to render
output_diroptSTRINGOverride directory for per-line audio files. Empty (the shipped default) = the episode's own audio dir from the ledger, which is where every downstream stage looks. Expert field: pointing it elsewhere strands the files.
dialogue_offset_msoptFLOAT0-500–500Shift all dialogue clips on the timeline (ms). Positive = delay, negative = advance.

Outputs (2)

NameTypeDescription
scene_audioAUDIO
render_logSTRING