minimax_h3_ref2va: how a shot reaches MiniMax H3 Ref2VA, what each reference slot holds, how sheets, voices and audio policies work, and what comes out.
How the default target works. The other targets are described in
AUTHORING.md and their own seriesmith/targets/video/<id>/ folders.
minimax_h3 is a different target: H3 hosted on Comfy Router (builtin:router_video),
with none of the slots, sheets or audio policies below.
The Ref2VA ComfyUI workflow (H3_Ref2VA_Shotlist_v1.json)
seriesmith drives this graph for you: load
seriesmith/targets/video/minimax_h3_ref2va/workflow.json to see it (save your own copy
in ComfyUI under the name above to change how H3 renders; INSTALL.md).
For each take its loader becomes SeriesmithShotLoader, given the one shot as JSON
and its reference pictures as uploads, and its saver SeriesmithSaveTake, which reports
every file it writes for seriesmith to put in the take (comfy_nodes/shot.py; restart
ComfyUI when it changes).
No audio dependencies. The nodes read and write PCM wav with the Python
standard library and fall back to ffmpeg for mp3/m4a/flac. In particular they
do not call torchaudio.save, which since torchaudio 2.13 routes through
torchcodec and raises ImportError when it is missing — you do not need to
install torchcodec.
Reference slots
Slots 1–3 carry the shot’s subjects — characters first, then props and vehicles, in the order the script lists them. Slot 4 always carries the location plate. There is no style reference image. The style is already carried by every sheet and plate (all drawn in it) and stated in the prompt text, so a dedicated style slot buys redundant conditioning. The background buys concrete layout, palette, lighting direction and depth for this shot — and keeps one location looking like one place across every cut in a sequence. The background is written into the prompt as a proper<Subject N> sourced
from <Picture 4>, because H3’s spec lists scenes and environments as Subject
content; a bare <Picture N> means “use this exact frame as a keyframe”, which
is not what a location plate is for. Its retention marker is
partially_preserved — layout and light are kept, framing is not.
Reference sheets
Author each character as a horizontal 4-panel strip — 3/4 body, side, back, face close-up — at 4096×1024 or larger.ref_image_size: max scales the short
side to 2048, so a horizontal strip keeps every panel sharp where a square grid
would halve it.
Each shot uses only one panel of each sheet (panel_mode: auto): the face
close-up for a single-character close shot, the three-quarter body everywhere
else. A reference image with more than one figure in it gets drawn as more than
one person, so multi-panel strips are no longer fed by default. full, pair,
face and body force a crop (render --panel-mode). The socket-to-prompt
mapping is fixed, so prompts are stable regardless of cast size:
A change of clothes is a second subject, not a note in the prompt. Give it
of: in the
series config and its own design; it inherits the character’s name and voice, and
its sheet path is derived from theirs (refs/gina/gina_sheet_4panel.png →
refs/gina/gina_towel_sheet_4panel.png). The script names the variant on who: and goes on
calling the character by name in the dialogue. The point is that the retention marker stays
fully_preserved against a sheet that is actually wearing the towel: H3 preserves a subject
whole — face, hair, proportions and wardrobe — so the only way to contradict the sheet is
to weaken the whole subject, which loosens the face in order to change the clothes.
A variant’s views are generated from the character’s own: the towel’s back panel is an
edit of their back panel, on any image target that reads references (flux2_klein_edit,
flux_kontext, minimax_h3_still). On a text-to-image target there is nothing to edit
from, so it draws the variant from its design on the character’s seed — closer than a
fresh draw, but not the same thing.
Props and vehicles are single clean images on a flat background and are never
panel-cropped; only character sheets get panel_mode. Unused
subject sockets take the background plate — it is smaller than a character
strip and reinforces the location rather than biasing identity toward whichever
subject got duplicated.
Voices without bodies
NAME (V.O.): and NAME (O.S.): mark a line as spoken by someone who is not
on screen. Such a speaker is not added to the visible cast: they cost no
reference slot, are never drawn, and need no character sheet — only a voice
description in the series config (and a voice_sample if the shot uses clone).
Only who: puts a character on screen. Before this existed, any speaking name
was auto-added to the cast, so a phone voice from another house burned a slot
and got rendered into frame.
A
(V.O.) speaker who is in who: — a character narrating over their own
shot — additionally gets H3’s required lips-closed clause (“while their lips remain
completely closed”), so H3 doesn’t animate their mouth over the narration.
A speaker with no visual reference is identified by their voice description
followed by (Sx), per H3’s spec, rather than an invented <Subject>.
A shot may have no who: at all — an establishing plate with voiceover over
it. The location then fills all four slots and becomes <Subject 1>.
Audio references
ref_audio_0..2 carry one clip each, and how many are used depends on the
policy:
The per-speaker rule is the one that bites: a two-hander in
clone mode needs
two samples, and feeding one voices the second character from the first one’s
sample. Unused sockets receive null. H3 takes at most three standalone audio
references, so a clone shot is capped at three speakers and the compiler
errors above that rather than silently dropping one.
Audio policies
Set per shot withpolicy: in the script, else from the series config’s audio.mode.
H3 emits one mixed track — there are no stems — which is what these policies work
around.
generate deliberately passes None, not silence — a silent clip on a
reference socket tells H3 to match silence.
A dub shot also has a retention setting (fully_copy, partially_copy, reference); see
RECORDED_DIALOGUE.md.
Speech pacing
A shot’s length has to hold its dialogue. H3 will fit any line into any window by speeding the delivery up, so an over-packed shot doesn’t fail — it just comes back sounding like a chipmunk reading a contract.--check and a normal compile emit the same findings as warnings, each with
the dur: that would fit and how many syllables the window actually holds.
Three ways out of a crammed shot: lengthen it, cut words, or split it in two —
and splitting is often the right answer, because a line that needs 6 seconds
usually wanted a reaction cut in the middle of it anyway.
Resolution
1344×768 is H3’s native canvas and both axes are multiples of 32.
1280×720 is not legal — 720 is not divisible by 32, and the loader raises
rather than letting H3 fail deep in the graph. Crop to 1344×756 and upscale at
conform for true 16:9.
Or render the final pass at 960×544 and upscale the picked takes to 1920×1088
(seriesmith upscale, then seriesmith assemble --upscaled --size 1920x1080): a take costs
under half as much to try, and only the kept ones are upscaled. docs/AUTHORING.md,
Final resolution, says which to choose.
Continuous shots
Ref2VA renderscontinuous: latent: the previous take’s last frames (39 by default) are
held at the head of the render, video and audio, by SeriesmithChainLatent, and trimmed
off again before the saver (SeriesmithChainTrim). continuous: first needs a first
keyframe, which Ref2VA doesn’t read: such a shot builds on minimax_h3_fl2va instead.
CONTINUOUS.md has how it works.
What you get out
VAEDecode emits the full frame batch as IMAGE before anything muxes it, so
save_frames gives you a PNG sequence, and H3’s audio is always written
separately as _h3.wav. There is no alpha channel — compositing here means
grading, effects and titles, not lifting a character off a background. Budget
16–50 GB of PNG per 12-minute episode at 1344×768.
The mp4 is pinned with -frames:v and never uses -shortest: H3’s audio often
runs a few milliseconds short of length/fps, and -shortest silently drops
the final frame, which breaks conform.
The saver also writes two JPEGs straight from the frames in memory: _tNN.jpg
(the middle frame) and _tNN_strip.jpg (8 evenly spaced frames, for hover
scrub), and a record of what it did (status, finished, frames, the names
of the files it wrote and its status line), which seriesmith merges into the
take’s _tNN.json (written queued when the take was reserved). A failure in
the thumbnails is reported in the status line, never raised, so it can’t cost
you the mp4.