Nodes/IAMCCS-nodes/IAMCCS_ShotboardVideoEditorRenderOptionalR49
ComfyUI Node

IAMCCS_ShotboardVideoEditorRenderOptionalR49

Turn that keyframe editor manifest back into video (and pick your audio policy first)

By IAMCCS·Created about a year ago·Updated 3 days ago· 118
IAMCCS_ShotboardVideoEditorRenderOptionalR49
    • video
    • frames
    • report
    ◄editor_manifest_json►
    ◄audio_policyconcat_clip_audio►
    ◄fps_modefrom_manifest►
    ◄override_fps24►
    ◄tail_trim_frames_per_clip0►

    Editing a manifest is cheap. Editing video is not. That's the whole bargain of the IAMCCS Shotboard Video Editor chain: you assemble takes as JSON, then a render step turns the final manifest into actual frames in one pass.

    IAMCCS_ShotboardVideoEditorRenderOptionalR49 is that render step. Two inputs matter, one has more consequences than it looks like, and the node has one specific gotcha around how much audio it decides you wanted.

    What it is

    Required, and it's all string-or-number widgets:

    • editor_manifest_json - the manifest from the collector. Multiline, so you can paste it, but normally wired.
    • audio_policy - what to do about sound. Valid values: concat_clip_audio, use_master_audio, first_video_audio, silent.
    • fps_mode - from_manifest or override_fps.
    • override_fps - a STRING, default "24". Only used when fps_mode says so.
    • tail_trim_frames_per_clip - 0 to 12, default 0. Trims the tail of each clip by N frames.

    Outputs: video (a Comfy VIDEO, into the exporter), frames (IMAGE, if you want to keep them in-graph), and report (STRING - read it).

    How it works

    It parses the manifest, falling back to sane defaults on session key and fps, then sorts video clips by start time and take index. That sort is why the manifest can accumulate takes out of order across queue passes and still render in the right sequence: order is derived from timestamps, not from insertion order.

    Then the audio decision, which is the part worth actually understanding:

    • concat_clip_audio (default) - joins each clip's own audio in timeline order. This is the right answer for multishot work where every shot has its own native sound.
    • use_master_audio - ignores the per-clip audio and lays your master track over the whole assembly. This is what you want when you've built a music bed or a mixed dialogue track, and it's the difference between a rough cut and something that sounds finished.
    • first_video_audio - takes audio from the first clip only. Useful when you've generated one continuous audio source and stitched picture to it.
    • silent - no audio at all. For a video-only intermediate, or when you're intentionally passing picture to a separate audio pass.

    The mixing respects the editor's mute and solo states: a clip muted on the timeline, or sitting on a muted track, doesn't make it into the mix, and if solo is active the node honours it. Clips whose role marks them as master audio are held out of the editor-audio mix rather than double-counted - otherwise your master plays twice, offset by however much you trimmed.

    fps_mode defaults to from_manifest because the manifest carries the generation's frame rate and that's usually the truth. Choosing override_fps and leaving it at 24 on a 24 fps project does nothing; choosing it and setting 30 will resample your programme, which is a legitimate thing to do for delivery and a bad thing to do by accident.

    tail_trim_frames_per_clip is the seam fixer. When each shot's final frame slightly overlaps the next one's first - common when takes were generated with a bit of context head - trimming a frame or two per clip tightens the cut. It's capped at 12 because beyond that you're editing, not de-duplicating.

    The legacy-value handling

    Two inputs are typed as STRING on purpose, and the node normalises them at the top of every run: values that aren't in the valid set get replaced with defaults and recorded as a migration in the report, and a numeric fps_mode is reinterpreted as override_fps with that number. This is a pack that has been through a lot of revisions, and this is what surviving them looks like. When a node tells you it migrated a widget value, believe it and save the workflow.

    Install

    Part of IAMCCS-nodes:

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

    Restart and hard-refresh. ComfyUI Manager → IAMCCS Nodes is the easier route. One copy only in custom_nodes; duplicates cause stale definitions and frontend weirdness.

    No requirements.txt in the repo, no pip step for the pack itself. ComfyUI 3.0.0+ and your own models. The decoding/encoding work happens elsewhere in the chain, so this node is mostly manifest parsing and tensor assembly - but it's the step where the whole programme's frames exist in memory at once, so it's the memory peak of the editor branch, not the exporter.

    Common issues

    "No video clips found in editor manifest." The manifest came through empty, or with clips that aren't typed as video. Check the collector's report - if it collected and you're still getting this, you've got a session key mismatch and you're reading a different (empty) session.

    Sound is missing on a shot. Three candidates: it was muted on the timeline, audio_policy is set to use_master_audio and that master doesn't cover it, or the clip's linked audio never made it into the manifest. The linked-clip pairing is the usual culprit.

    Audio doubled or phasing. A master-audio clip got mixed twice - once as editor audio, once as master. The node filters these by clip role, so if you see it, the manifest's role tags have been changed.

    Everything is one frame short at every cut. Raise tail_trim_frames_per_clip from 0. Conversely, if shots are being clipped, set it back to 0.

    Non-terminal gotcha. Like its siblings in the R45 chain, this node is a non-terminal subclass - it only runs when something downstream requests its outputs. In the Universal workflow that's the lazy exporter, gated by the final gate. Wire it dead-last and nothing happens.

    Where it fits

    Collector → this → R45 Video Editor Exporter · Lazy → R45 Final Master / Optional Editor Gate. The render node's job ends at "here's a clean video object and the frames"; codecs, container, metadata and RTX upscaling belong to the exporter, and keeping those concerns apart is why you can re-encode a delivery without re-assembling the timeline.

    CategoryIAMCCS/Cine/Multigeneration

    Inputs (5)

    NameTypeDefaultDescription
    editor_manifest_jsonSTRING—
    audio_policySTRINGconcat_clip_audio—
    fps_modeSTRINGfrom_manifest—
    override_fpsSTRING24—
    tail_trim_frames_per_clipINT00–12—

    Outputs (3)

    NameTypeDescription
    videoVIDEO—
    framesIMAGE—
    reportSTRING—