Nodes/ComfyUI-OldTimeRadio/ LFC Ledger Freeze Cascade (v2.0)
ComfyUI Node

LFC Ledger Freeze Cascade (v2.0)

The freeze that turns a script into a contract

By jbrick2070·Created 5 months ago·Updated about 5 hours ago· 7
LFC Ledger Freeze Cascade (v2.0)
    • script_text
    • script_json
    • news_used
    • estimated_minutes
    • freeze_verdict
    • episode_seed
    • v2_ledger_json
    script_text
    script_json
    news_used
    estimated_minutes
    technical_model
    enable_phase_7_audio_readinesstrue
    enable_phase_8_video_readinesstrue

    In OldTimeRadio the whole episode is a JSON "ledger" that flows node to node, and at one point it stops being a draft and becomes a contract. OTR_LedgerFreezeCascade is that point. It finalizes the writer's accepted script - no more quality-driven reauthoring - and stamps the version every downstream consumer will read. Think of it as the moment a screenplay gets locked before production: the cast, voices, and shots all get scheduled against this exact document, and rerunning from it is deterministic.

    The node reads the production ledger directly (via peek_ledger()); the script_text socket is the wire that keeps the graph visually in line. It then re-serializes script_json from the post-freeze ledger so everyone downstream sees the final state.

    The phases that do the actual work

    Two phases are on by default, and they're the ones you'll care about:

    • Phase 7 - audio readiness (enable_phase_7_audio_readiness, default ON). Expands things TTS would stumble over: Dr.Doctor, &and, 42forty-two. Deterministic and cheap, and it's why the voices don't read "St. Louis" as "st dot louis". This is one of those hidden quality wins you only notice when it's off.
    • Phase 8 - video readiness (enable_phase_8_video_readiness, default ON). An audit that checks cast portraits and voiced-line visual coverage. It mutates nothing - it stamps meta.video_readiness so the video stage knows whether every speaking role has a picture. On, and the video branch can trust the ledger.

    The technical_model input is validated via require_model - an unwired socket raises a loud MissingModelInputError rather than silently running with a guess.

    There's a small legacy trap in the schema: render_selection, render_max_n, protagonist_only, and manual_line_ids are all marked deprecated compatibility inputs, ignored. They're kept so old saved workflows don't break, but setting them does nothing. Don't go hunting for a way to render "dramatic peaks only" - it's gone.

    Outputs

    Seven outputs: script_text, script_json (the frozen, re-serialized ledger - feed this to CastLock), news_used, estimated_minutes, freeze_verdict, episode_seed (INT), and v2_ledger_json. It's marked as an output node, so a stripped story-only workflow (validator → writer → freeze) can terminate here with the frozen ledger on disk and no media stage at all.

    Install and gotchas

    Pack-level install (ComfyUI Manager → ComfyUI-OldTimeRadio, restart; v2.0-alpha). No models - pure ledger logic. The main thing to remember is the freeze is a one-way door: downstream, the ledger is canonical, and changes belong upstream in the writer, not here. If you're hacking on the ledger JSON by hand, you're fighting the pipeline's determinism guarantees - the pack would rather you change the writer's inputs and re-run.

    CategoryOldTimeRadio/v2

    Inputs (7)

    NameTypeDefaultDescription
    script_textSTRINGPassthrough from OTR_LedgerScriptWriter. The cascade reads the production ledger directly via peek_ledger(); this socket exists so the graph wires the writer and cascade in line.
    script_jsonoptSTRINGForwarded from the writer's script_json slot. The cascade re-serializes this from the post-freeze ledger so downstream consumers see the final state.
    news_usedoptSTRINGPassthrough of the writer's news_used slot. Not touched by the cascade.
    estimated_minutesoptINTPassthrough of the writer's estimated_minutes INT slot. Not touched by the cascade.
    technical_modeloptSTRINGTechnical model ID from the writer. Required for compatibility on a normal current-ledger run; freeze does not acquire or generate with this model. Validated via _otr_model_inputs.require_model -- an unwired or blank socket raises MissingModelInputError loud.
    enable_phase_7_audio_readinessoptBOOLEANtrueLFC Phase 7 -- audio readiness. Expands abbreviations (Dr. -> Doctor), symbols (& -> and), and numbers (42 -> forty-two) so TTS produces pronounceable output. Default ON (deterministic + cheap).
    enable_phase_8_video_readinessoptBOOLEANtrueLFC Phase 8 -- video readiness audit. Checks cast portraits + voiced-line visual coverage. Mutates nothing; stamps meta.video_readiness. Default ON.

    Outputs (7)

    NameTypeDescription
    script_textSTRING
    script_jsonSTRING
    news_usedSTRING
    estimated_minutesINT
    freeze_verdictSTRING
    episode_seedINT
    v2_ledger_jsonSTRING