Nodes/IAMCCS-nodes/IAMCCS Dialogue Tag Editor
ComfyUI Node

IAMCCS Dialogue Tag Editor

Write dialogue once, get timing, speakers, and lip-sync prompts for free

By IAMCCS·Created 11 months ago·Updated 8 days ago· 113
IAMCCS Dialogue Tag Editor
  • cine_linx
  • cine_linx
dialogue_data{ "schema": "iamccs.dialogue_scene", "schema_version": 4, "global_prompt": "cinematic field and reverse-field dialogue, hard cut coverage, one dominant speaking face per shot, visible mouth movement, natural audio-driven performance, silent listener reaction, stable identities, coherent eyelines", "settings": { "editor_profile": "dialogue", "engine_profile": "tts_audio_suite_chatterbox", "output_mode": "speaker_stems_for_overlap", "audio_lane_mode": "speaker_stems_timeline", "speaker_stems_zero_start": false, "speaker_stem_srt_local_zero": false, "inline_edit_mode": "metadata_only", "default_gap_seconds": 0.12 }, "speakers": [ { "id": "A", "name": "Man A", "voice": "speaker_a_low_tense", "reference_text": "Keep your voice low. We do not know who is listening.", "language": "en", "voice_design": { "gender": "male", "age": "adult", "pitch": "low", "style": "tense", "accent": "", "dialect": "", "instruct": "male, adult, low pitch, tense" } }, { "id": "B", "name": "Man B", "voice": "speaker_b_controlled_whisper", "reference_text": "Good. Now we finally have something worth protecting.", "language": "en", "voice_design": { "gender": "male", "age": "adult", "pitch": "medium", "style": "controlled whisper", "accent": "", "dialect": "", "instruct": "male, adult, medium pitch, controlled whisper" } } ], "lines": [ { "id": "line_001", "speaker": "A", "text": "You said the signal was dead. Then why is that receiver still blinking?", "emotion": "tense", "style": "low", "paralinguistic": "Breathing", "overlap_after": 0.18, "ref": 1, "track": 0, "local_prompt": "hard cut, Man A close-up, Man A speaks clearly, visible mouth movement, tense controlled delivery, Man B listens quietly" }, { "id": "line_002", "speaker": "B", "text": "Because someone on the other side wants us to think we are alone.", "emotion": "serious", "style": "whisper", "paralinguistic": "none", "overlap_after": 0.12, "ref": 2, "track": 1, "local_prompt": "hard cut, Man B close-up, Man B speaks clearly, visible mouth movement, guarded quiet answer, Man A listens quietly" }, { "id": "line_003", "speaker": "A", "text": "If we open that door, we may be giving them exactly what they came for.", "emotion": "fearful", "style": "dry", "paralinguistic": "Sigh", "overlap_after": 0.1, "ref": 1, "track": 0, "local_prompt": "hard cut, Man A tighter close-up, Man A speaks clearly, visible mouth movement, fear held under discipline" }, { "id": "line_004", "speaker": "B", "text": "Then we do not open it. We make them knock twice.", "emotion": "coldness", "style": "authority", "paralinguistic": "none", "overlap_after": 0.0, "ref": 2, "track": 1, "local_prompt": "hard cut, Man B close-up, Man B speaks clearly, visible mouth movement, decisive controlled authority" } ] }
frame_rate24.00
speech_wpm130
min_line_seconds0.80
default_gap_seconds0.12
output_modespeaker_stems_for_overlap
inline_edit_modemetadata_only

Planning dialogue for AI video is where a lot of ambitious projects fall apart, because "the character speaks this line" carries a lot of hidden info: who says it, how long it takes, whether it overlaps the other character, and what the video prompt should be for that shot. The Dialogue Tag Editor is an app-style planner that captures all of that in one structured JSON blob and converts it into a cine_linx payload that the whole IAMCCS chain - TTS, AudioBoard, Shotboard - can consume. Type the scene once, get the timing math and per-line video prompts for free.

How it works

The node is powered by a dialogue_data JSON document (edited in its UI) that describes speakers and lines. Each line carries a speaker id, the text, emotion, style, paralinguistic cues (breathing, sigh), overlap_after, a track, and - crucially - a local_prompt written for the video side, like "hard cut, Man A close-up, Man A speaks clearly, visible mouth movement, tense controlled delivery."

The backend then does the bookkeeping: speech_wpm (default 130) converts words to estimated speaking time, min_line_seconds floors each line, default_gap_seconds adds pauses between lines, and everything gets laid out on track numbers. output_mode picks between speaker_stems_for_overlap (one stem per speaker so lines can overlap naturally) and flatten_for_single_track. inline_edit_mode chooses metadata_only or tts_audio_suite_inline_tags, depending on whether downstream TTS wants inline tags.

Output is a single updated cine_linx - the editor merges all this into the shared bundle rather than emitting a dozen parallel wires.

Inputs that matter

  • dialogue_data - the big JSON; edit it in the UI, don't hand-roll it.
  • speech_wpm and default_gap_seconds - the two you'll tune to match your voice actor's pacing.
  • output_mode - speaker_stems_for_overlap if characters interrupt each other, otherwise flatten.
  • Optional cine_linx - chain a previous planner's output if you want to build on existing timeline metadata.

Install

Ships with IAMCCS-nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/IAMCCS/IAMCCS-nodes.git

Or ComfyUI Manager → "IAMCCS" → install → restart. No extra dependencies.

Gotchas

The wpm math is an estimate, not a measurement - real actors pause, breathe, and rush, so expect your first plan's timings to be off and tune default_gap_seconds up for natural pacing. Also, the editor writes the plan into the linx; it does not generate audio or video itself. If nothing downstream consumes the cine_linx (like the Dialogue AudioBoard Bridge), you've written a very pretty spec that nobody reads. It's one node in a larger pipeline - that's its job.

CategoryIAMCCS/Cine/Audio

Inputs (8)

NameTypeDefaultDescription
dialogue_dataSTRING{ "schema": "iamccs.dialogue_scene", "schema_version": 4, "global_prompt": "cinematic field and reverse-field dialogue, hard cut coverage, one dominant speaking face per shot, visible mouth movement, natural audio-driven performance, silent listener reaction, stable identities, coherent eyelines", "settings": { "editor_profile": "dialogue", "engine_profile": "tts_audio_suite_chatterbox", "output_mode": "speaker_stems_for_overlap", "audio_lane_mode": "speaker_stems_timeline", "speaker_stems_zero_start": false, "speaker_stem_srt_local_zero": false, "inline_edit_mode": "metadata_only", "default_gap_seconds": 0.12 }, "speakers": [ { "id": "A", "name": "Man A", "voice": "speaker_a_low_tense", "reference_text": "Keep your voice low. We do not know who is listening.", "language": "en", "voice_design": { "gender": "male", "age": "adult", "pitch": "low", "style": "tense", "accent": "", "dialect": "", "instruct": "male, adult, low pitch, tense" } }, { "id": "B", "name": "Man B", "voice": "speaker_b_controlled_whisper", "reference_text": "Good. Now we finally have something worth protecting.", "language": "en", "voice_design": { "gender": "male", "age": "adult", "pitch": "medium", "style": "controlled whisper", "accent": "", "dialect": "", "instruct": "male, adult, medium pitch, controlled whisper" } } ], "lines": [ { "id": "line_001", "speaker": "A", "text": "You said the signal was dead. Then why is that receiver still blinking?", "emotion": "tense", "style": "low", "paralinguistic": "Breathing", "overlap_after": 0.18, "ref": 1, "track": 0, "local_prompt": "hard cut, Man A close-up, Man A speaks clearly, visible mouth movement, tense controlled delivery, Man B listens quietly" }, { "id": "line_002", "speaker": "B", "text": "Because someone on the other side wants us to think we are alone.", "emotion": "serious", "style": "whisper", "paralinguistic": "none", "overlap_after": 0.12, "ref": 2, "track": 1, "local_prompt": "hard cut, Man B close-up, Man B speaks clearly, visible mouth movement, guarded quiet answer, Man A listens quietly" }, { "id": "line_003", "speaker": "A", "text": "If we open that door, we may be giving them exactly what they came for.", "emotion": "fearful", "style": "dry", "paralinguistic": "Sigh", "overlap_after": 0.1, "ref": 1, "track": 0, "local_prompt": "hard cut, Man A tighter close-up, Man A speaks clearly, visible mouth movement, fear held under discipline" }, { "id": "line_004", "speaker": "B", "text": "Then we do not open it. We make them knock twice.", "emotion": "coldness", "style": "authority", "paralinguistic": "none", "overlap_after": 0.0, "ref": 2, "track": 1, "local_prompt": "hard cut, Man B close-up, Man B speaks clearly, visible mouth movement, decisive controlled authority" } ] }Edited by the IAMCCS Dialogue Tag Editor app UI.
frame_rateFLOAT24.001–120
speech_wpmFLOAT13060–260
min_line_secondsFLOAT0.800.1–30
default_gap_secondsFLOAT0.120–10
output_modeCOMBOspeaker_stems_for_overlap2 options: speaker_stems_for_overlap, flatten_for_single_track
inline_edit_modeCOMBOmetadata_only2 options: metadata_only, tts_audio_suite_inline_tags
cine_linxoptIAMCCS_SUPERNODE_LINX

Outputs (1)

NameTypeDescription
cine_linxIAMCCS_SUPERNODE_LINX