CoachBate Shot Loader
The node that runs your whole LTX movie while you sleep
- video_prompt
- duration_seconds
- shot_id
- video_filename_prefix
- start_image
- end_image
- start_image_prompt
- negative_prompt
- negative_audio_prompt
- total_shots
- start_image_strength
- end_image_strength
- end_image_timestamp
- global_prompt
- local_prompts
- segment_lengths
- h3_ref_image_1
- h3_ref_image_2
- h3_ref_image_3
- h3_ref_image_4
- h3_ref_image_5
- h3_ref_image_6
- h3_ref_audio_1
- h3_ref_audio_2
- h3_ref_audio_3
Ever stared at a 50-shot shot list and thought "I am not clicking Queue 50 times"? That's the exact problem this node exists to delete. CoachBate Shot Loader reads a shotlist.json file, hands your graph one shot per queue run, and auto-advances to the next one. Pair it with Auto Queue and a 40-shot LTX-2.3 sequence processes itself while you go do something else.
This is the pack's flagship, and the reason the pack exists at all. The author built it for his own shot-by-shot LTX-2.3 video production, so it's tuned for that world: a clip per shot, start/end frame conditioning, audio prompts, filename prefixes that map straight into VHS save nodes. Note it's a data driver, not a generator - no model weights, no VRAM, no extra downloads. It just feeds values in.
How it works
The mechanism is simple and robust: the JSON is read fresh from disk on every run, so you can edit the shotlist mid-queue and the next shot picks up your changes. DONE shots are skipped automatically, and a class-level counter (stored_index) advances one step per execution - the same self-advancing pattern ComfyUI's built-in JSON Array Iterator uses.
Three modes control the counter: increment (forward, the default), decrement (backward), and fixed (always the same shot, handy for debugging one entry). Missing start/end image files don't crash the run - you get an orange toast and that shot is skipped so the pipeline keeps moving. There's also a POST /coachbate/skip HTTP endpoint that advances past the current shot without a full re-run, which production scripts use to bail on a bad take.
Inputs that matter
json_path- absolute path to your shotlist JSON. The file can be a bare array or wrapped in{"shots": [...]}.mode-increment/decrement/fixed. You'll live inincrement.shot_number- 1-based starting position. Seeds the counter on first run, then updates itself.framerate- used to convert segment durations to frame counts. Must match your video generation FPS.
The outputs
There are a lot of them, but the ones you'll wire up first: video_prompt and negative_prompt into your CLIP text encoders, duration_seconds into your frame-count math (fps × duration), video_filename_prefix into Save Video, and start_image / end_image through a Load Image into LTX start/end-frame conditioning, with start_image_strength / end_image_strength alongside. total_shots tells you how many non-DONE shots remain.
The extras - global_prompt, local_prompts, segment_lengths - exist for Prompt Relay / LTX Director-style workflows. local_prompts holds pipe-separated sub-prompts with per-segment durations; segment_lengths converts those to comma-separated frame counts, snapped to the 8n+1 pattern video models expect. Ignore them until you need them.
Shot list format
Four fields are required per shot: shot_id, video_filename_prefix, duration_seconds, and video_prompt. Everything else (start_image, strengths, negatives, status, even your own production-tracking fields) is optional, and unknown fields are loaded and ignored - so you can stash metadata without breaking anything. Set "status": "DONE" on a shot to skip it permanently.
Looping every shot automatically
- Set
modetoincrement. - Open the queue drop-down next to the Queue button and pick Auto Queue.
- Click Queue once. The node runs shot 0, advances, re-fires, and keeps going until the queue wraps or you stop it.
The node even paints a status box on its face - 3/12 001-BATE ENTERS GYM / 16s ➡️ 002-BATE TRAINS - so you can see where you are without opening anything.
Common issues
- "All shots have status DONE" error - the node refuses to loop forever. Check your
statusfields. - Orange toast "Skipping: start_image not found" - a conditioning image path is wrong; the shot is skipped rather than failed, so the queue keeps running.
- Wrong clip length -
duration_secondsis seconds, not frames. Multiply by your framerate.
Installation
Install via ComfyUI Manager (search "CoachBate") or:
cd ComfyUI/custom_nodes
git clone https://github.com/CoachBate/ComfyUI-CoachBate.git
Restart ComfyUI; the node appears under CoachBate in Add Node. The pack has no Python dependencies, so there's nothing heavy to install - just the pack and whatever video model you already run. It's alpha-stage personal tooling, so don't be surprised by the occasional rough edge.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| json_path | STRING | Absolute path to the shotlist JSON file | |
| shot_number | INT | 11–9999 | Shot number to start from (1-based). In increment mode: seeds the starting position on first run. Updated automatically after each shot. |
| mode | COMBO | increment | fixed: always output shot_index. increment/decrement: advance one shot per run using the stored counter. |
| framerate | INT | 241–120 | Frames per second used to convert segment durations in local_prompts to frame counts. |
Outputs (25)
| Name | Type | Description |
|---|---|---|
| video_prompt | STRING | — |
| duration_seconds | INT | — |
| shot_id | STRING | — |
| video_filename_prefix | STRING | — |
| start_image | STRING | — |
| end_image | STRING | — |
| start_image_prompt | STRING | — |
| negative_prompt | STRING | — |
| negative_audio_prompt | STRING | — |
| total_shots | INT | — |
| start_image_strength | FLOAT | — |
| end_image_strength | FLOAT | — |
| end_image_timestamp | FLOAT | — |
| global_prompt | STRING | — |
| local_prompts | STRING | — |
| segment_lengths | STRING | — |
| h3_ref_image_1 | STRING | — |
| h3_ref_image_2 | STRING | — |
| h3_ref_image_3 | STRING | — |
| h3_ref_image_4 | STRING | — |
| h3_ref_image_5 | STRING | — |
| h3_ref_image_6 | STRING | — |
| h3_ref_audio_1 | STRING | — |
| h3_ref_audio_2 | STRING | — |
| h3_ref_audio_3 | STRING | — |