Nodes/ComfyUI-OldTimeRadio/ Image Gen Dispatcher (cache + ledger + image_done)
ComfyUI Node

Image Gen Dispatcher (cache + ledger + image_done)

The node that actually draws the stills — with a cache that never lies

By jbrick2070·Created 5 months ago·Updated about 20 hours ago· 7
Image Gen Dispatcher (cache + ledger + image_done)
    • patched_ledger_json
    • image_done
    • report
    script_json{}
    image_policy_json{}
    image_prompts_json{}
    gate_in
    episode_id

    Here's the moment the pack actually spends GPU on pictures. OTR_ImageGenDispatcher is the terminal C node for the image branch: it takes the image policy from OTR_ImageDirector and the per-object prompts from OTR_MetaBriefImagePromptGen, renders every still, stamps the ledger, and emits an image_done signal that lets the video branch start. It's the image-side equivalent of the voice dispatchers - and it's where the pack's cache philosophy pays off.

    The mechanism that matters is content-addressed caching. For each image object, the dispatcher builds a cache key from (role, object_id, prompt_hash, seed, engine_id, engine_version). On a cache hit it reuses the existing image - no GPU spent. On a miss it generates, then writes the still content-addressed at output/otr/stills/{portrait_content_hash}.png, never overwriting. Change the prompt, seed, or engine and you get a new hash, new pixels, new file - and every downstream consumer that keys on that hash (like a 3D mesh cache) invalidates correctly. This is the anti-frustration design done right: rerunning an episode with identical inputs is nearly free.

    There's a hard cap wired in too: fresh-mode renders are limited to min(fresh_cap, beat_budget) - never over-generate, per the director's plan. And it's fail-closed: if the selected engine isn't usable, it raises rather than silently swapping to a different model. No quiet Flux substitution, ever.

    Inputs and outputs

    Required: script_json (the frozen ledger - the dispatcher stamps ledger['images'] into it), image_policy_json (from ImageDirector), and image_prompts_json (the versioned {"objects":[...]} payload from MetaBriefImagePromptGen - portraits plus scene stills). Optional: gate_in (an ordering signal, e.g. audio_done) and episode_id - every still materializes into episodes/<episode_id>/stills/ plus a stills_manifest.json, and an unkeyed dispatch is loud.

    Outputs: patched_ledger_json (the ledger with images stamped in), image_done (the gate that mirrors audio_done - wire it to OTR_ShotLock), and report.

    Install and gotchas

    Pack-level install (ComfyUI Manager → ComfyUI-OldTimeRadio, restart). The local image default is Z-Image-Turbo (Apache-2.0), which a fresh run needs on disk; heavier engines like flux_gen1 (BFL non-commercial) and ideogram4_local (non-commercial, 16 GB-class) are opt-in. If the console names a missing weight, that's the fail-closed contract - install it or pick the procedural path. The dispatcher takes a shared GPU-residency lease for local engines and re-probes NVML on release, so don't fight it for VRAM by running other GPU work in parallel on the same card mid-episode.

    CategoryOldTimeRadio/v2/image

    Inputs (5)

    NameTypeDefaultDescription
    script_jsonSTRING{}Frozen ledger JSON; the dispatcher stamps ledger['images'] into it.
    image_policy_jsonSTRING{}OTR_ImageDirector policy (engine per role + granularity + seed).
    image_prompts_jsonSTRING{}OTR_MetaBriefImagePromptGen output: the versioned {"objects":[...]} payload (portraits + scene stills).
    gate_inoptSTRINGOptional ordering signal (e.g. audio_done); opaque STRING.
    episode_idoptSTRINGEpisode id (still-spine ST-3/DS-3; wired in the saved json). Every still materializes into episodes/<episode_id>/stills/ + stills_manifest.json. Falls back to the ledger's episode_id; an unkeyed dispatch is LOUD.

    Outputs (3)

    NameTypeDescription
    patched_ledger_jsonSTRING
    image_doneSTRING
    reportSTRING