Nodes/SDXL Auto Prompter/APNext H3 Music Video Writer
ComfyUI Node

APNext H3 Music Video Writer

A whole music video from one audio file

By dagthomas·Created 3 years ago·Updated about 6 hours ago· 287
APNext H3 Music Video Writer
  • audio
  • llm
  • image_1
  • image_2
  • image_3
  • image_4
  • image_5
  • image_6
  • image_7
  • image_8
  • image_9
  • scenes
  • durations
  • lengths
  • audio_segments
  • segment_table
  • scenes_text
  • synopsis
  • cast
  • scene_count
  • song_seconds
  • session_id
  • info
  • image_1
  • image_2
  • image_3
  • image_4
  • image_5
  • image_6
  • image_7
  • image_8
  • image_9
  • clip_starts
direction
lyrics
performance_modePerformance (the singer lip-syncs the lyrics on camera)
segment_modeAuto (cut on the music)
max_segment_seconds15.0
min_segment_seconds5.2
shots_per_sceneAuto
visual_styleLive-action, 35mm cinematic film aesthetic
dialogue_languageEnglish
wildness45
modelsonnet
researchfalse
directortrue
use_subscriptiontrue
timeout_seconds1200
seed-1
cast_1
cast_2
cast_3
cast_4
extra_cast
custom_dialogue_language
custom_visual_style
wardrobe
locations
enforce_wardrobetrue
extra_instructions
image_notes
resume_session_id
working_dir
context_1
context_2
context_3
context_4
context_5
context_6
context_7
context_8
scenes_from_lyricsfalse
reference_image_useCharacters only (ignore picture backgrounds)
scene_briefs
audio_modeReference audio (<Audio 1> = the song piece)
save_scenestrue
scenes_per_call4

The moment you realise it: APNext H3 Music Video Writer turns a song into a music video. Not a mood video with a soundtrack slapped on - a video where every clip is cut on the music, every rendered piece is exactly as long as its audio slice, the performer lip-syncs the actual lyric lines, and the whole thing stitches back together against the original track. It's the most ambitious node in the H3 family, and it mostly works because it's ruthless about one thing: audio lengths and clip lengths must match exactly.

Here's the mechanism. H3 renders clips up to about 15 seconds, so the node cuts the song into consecutive pieces inside min_segment_secondsmax_segment_seconds. The cut points come from the music itself - spectral-flux onsets, energy steps, section changes, and (when you supply timed lyrics) right before a lyric line. Then every piece length is snapped to H3's frame grid (5 + 17k frames at 24fps) so each rendered clip is exactly as long as its audio slice. That's the detail that makes the final stitched video never drift out of sync - which is the failure mode that kills every hand-rolled attempt at this.

Then it writes one scene per piece, each a four-section H3 prompt where the piece is <Audio 1>, reused 1:1 as the clip's soundtrack. In Performance mode the singer lip-syncs the piece's lyric lines on camera (<Subject 1> sings <d>[English] exact line</d> in sync with <Audio 1>); Narrative answers the lyric with pictures; Mixed alternates. Quiet pieces get long intimate shots; loud or peak pieces get more cuts and the chorus look. Long songs are written in chunks of six scenes that continue one session, so the synopsis, wardrobe and location locks stay consistent.

The inputs that matter

  • audio - the song (from Load Audio). Everything flows from this.
  • direction - the concept: who performs, where, the look, the story arc, what the chorus looks like vs the verses.
  • lyrics - one line per line. Timestamps make the sync exact: [0:15] line, 0:15 line, or LRC [00:15.20] line; [Chorus]-style tags are kept. Untimed lines get spread evenly (approximate). Empty = instrumental.
  • performance_mode - Performance / Narrative / Mixed.
  • segment_mode - Auto cuts on the music inside the allowed range; Fixed takes the longest allowed piece each time; Lyric lines tries hardest to cut right before a line.
  • cast_1..4 / extra_cast - the performer(s). An H3 Characters node in ✏️ custom mode with a wardrobe is made for this - a described performer with a locked outfit.
  • wardrobe / locations / enforce_wardrobe - the same locks as the Crossover Writer (cast-carried wardrobe is merged in).
  • The usual visual_style, dialogue_language (the lyric language), wildness, and the Claude Code block, plus image_1..9 reference pictures.

The outputs are matched lists, which is the whole architecture: scenes → the video node's prompt, lengths (frame counts) → length, audio_segmentsref_audio_1, durations → your frame math. Plus segment_table - the cut list, 01 0:00.00 – 0:15.08 (15.08s, 362 frames) energy: peak lyrics: … - and scenes_text, synopsis, cast, scene_count, song_seconds, session_id, info.

The finishing move

Each piece renders as its own clip, so the last step is H3 Scenes Join with replace_audio set to the original song - the joined per-scene audio gets swapped for the real track, and one Create Video → Save Video writes a single music video that plays in sync. The pack ships examples/h3/h3_music_video.json end to end.

Installing

Part of dagthomas/comfyui_dagthomas: ComfyUI Manager → comfyui_dagthomas, or clone into custom_nodes + pip install -r requirements.txt, restart. Under APNext → H3.

Claude Code must be installed and logged in - the default engine, subscription seat and all - unless you connect an H3 LLM Backend to the llm socket and run it on Ollama instead. Budget for the slow end: a 3-minute song is a dozen-plus pieces, each a full Claude turn, plus the audio analysis. Where people get burned: forgetting timed lyrics and wondering why the "sync" is approximate, and skipping replace_audio and wondering why the final video's sound doesn't match the song. Both are one input away from right.

Categorycomfyui_dagthomas/H3

Inputs (55)

NameTypeDefaultDescription
audioAUDIOThe song. It is cut into 5-15 s pieces and every piece becomes one scene / one clip.
directionSTRINGThe music-video concept: who performs, where, the look, the story arc, recurring motifs, what the chorus looks like vs the verses. Free text.
lyricsSTRINGLyrics, one line per line. Timestamps make the sync exact: `[0:15] line`, `0:15 line` or LRC `[00:15.20] line`; section tags like [Chorus] are kept. Untimed lines are spread evenly over the song (approximate). Empty = instrumental video.
performance_modeCOMBOPerformance (the singer lip-syncs the lyrics on camera)3 options: Performance (the singer lip-syncs the lyrics on camera), Narrative (story visuals, nobody sings on camera), Mixed (performance and story, alternate or blend)
segment_modeCOMBOAuto (cut on the music)How the song is cut. Auto cuts on onsets / energy changes inside the allowed length range (lyric-line starts are preferred when lyrics are timed); Fixed takes the longest allowed piece every time; Lyric lines tries hardest to cut right before a line.
max_segment_secondsFLOAT15.05.2–15.1Longest piece (H3 renders up to ~15 s). Lengths snap to H3's frame grid.
min_segment_secondsFLOAT5.25.2–15Shortest piece. 124 frames (~5.2 s) is the shortest trained clip.
shots_per_sceneCOMBOAutoShots per scene. Auto lets the model cut to the music (more shots in loud parts).
visual_styleCOMBOLive-action, 35mm cinematic film aestheticOpens every [Shot 1]; kept identical across the whole video.
dialogue_languageCOMBOEnglishLanguage of the lyrics (the <d>[...] tag).
wildnessINT450–1000 = grounded performance video, 100 = fully surreal. Above 40 seeds surreal events.
modelCOMBOsonnetWho writes the prompt. sonnet / opus / haiku / fable / default are Claude Code aliases (`default` = whatever the CLI is configured for). ollama: / lmstudio: / local: entries are whatever your local servers were serving when the page loaded; pick one to run fully offline. Anything not listed goes in model_override.
researchBOOLEANfalseLet Claude Code search the web for real references before writing - the actual location, wardrobe, lighting and physics. Slower, and it reaches the internet.
directorBOOLEANtrueLoad the H3 director skills (data/h3/skills): the core writing rules, the format this node emits, and style/motion craft, each with a reference library of gold examples and style anchors that Claude Code reads on demand. Costs a few extra seconds and tokens per run.
use_subscriptionBOOLEANtrueHide ANTHROPIC_API_KEY from the CLI so it uses your Claude Code login and subscription seat. Turn off to bill the API key instead.
timeout_secondsINT120060–7200How long to wait PER CALL before the node gives up on the CLI (this is the node's own watchdog, not a Claude limit). Single H3 prompts take 25-60s; a multi-scene chunk with director/research on can take 10-20 minutes. The multi-scene writers retry a timed-out chunk at half size automatically.
seedINT-1-1–18446744073709550000Seeds the surreal picks and controls caching. -1 re-runs every queue.
cast_1optSTRINGA cast line or block from an H3 Characters node (its `cast` output): the performer(s) and anyone else in the video.
cast_2optSTRINGA cast line or block from an H3 Characters node (its `cast` output): the performer(s) and anyone else in the video.
cast_3optSTRINGA cast line or block from an H3 Characters node (its `cast` output): the performer(s) and anyone else in the video.
cast_4optSTRINGA cast line or block from an H3 Characters node (its `cast` output): the performer(s) and anyone else in the video.
extra_castoptSTRINGPerformer(s) / characters typed by hand, one per line, e.g. `Lead singer: a woman in her 30s with a platinum pixie cut` or `Character (played by Actor) from Show`. Merged with the cast sockets.
custom_dialogue_languageoptSTRING
custom_visual_styleoptSTRINGAny visual style not in the dropdown; overrides the dropdown when filled in.
wardrobeoptSTRINGWardrobe lock, one line per character, e.g. `Sheldon: brown corduroy jacket, green Flash T-shirt, khaki trousers, small silver ring in the left nostril`. Used word-for-word in every shot. Empty = Claude fixes one outfit per character itself (in the synopsis) and repeats it in every shot.
locationsoptSTRINGLocation lock, one line per recurring place, e.g. `Sheldon's living room: beige three-seat sofa facing a wall-mounted TV on the LEFT, tall bookshelf of comics behind it, bay window with white blinds on the RIGHT, warm tungsten floor lamp in the far corner`. Used word-for-word in every scene set there, so the room looks the same in every scene. Empty = the model fixes each recurring place itself (in the synopsis) and repeats it.
enforce_wardrobeoptBOOLEANtrueAfter writing, check that every shot a character is in restates all of that character's wardrobe anchors verbatim, and that every scene set in a locked location restates that location's anchors. If anything is dropped or changed, the model gets one repair turn in the same session. Off = trust the first answer.
extra_instructionsoptSTRING
image_notesoptSTRINGPer-picture notes, one per line: `Image 1: the singer`, `Image 2: the rooftop, use as the location`. With reference_image_use = Characters only (the default), a note like that is the ONLY way a picture may be read as a location or prop - otherwise every picture is a performer and its backdrop is ignored.
resume_session_idoptSTRINGContinue an earlier Claude Code run by feeding it that node's session_id. The whole conversation, images included, is still in context.
working_diroptSTRINGA folder Claude Code may read while writing - a script, a shot list, lookbook notes. Empty uses a throwaway scratch folder, which is the safe default.
llmoptAPNEXT_LLMOptional. Connect an APNext H3 LLM Backend node to write with Ollama, LM Studio, another OpenAI-compatible server or an API model instead of Claude Code. Overrides the model dropdown while connected.
context_1optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_2optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_3optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_4optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_5optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_6optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_7optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
context_8optSTRINGSteering input from another APNext node (Time, Scene, Poses, Plots, Feelings, Cinematic, Science, Geography, Architecture, Fashion, ...). The node detects which kind it is and tells Claude how to use it. Sockets grow as you connect them.
image_1optIMAGEReference image 1: <Picture 1> in the prompt. Connect the same image to image_1 on the MiniMax H3 Reference to Video node, or use this node's image_1 output.
image_2optIMAGEReference image 2: <Picture 2> in the prompt. Connect the same image to image_2 on the MiniMax H3 Reference to Video node, or use this node's image_2 output.
image_3optIMAGEReference image 3: <Picture 3> in the prompt. Connect the same image to image_3 on the MiniMax H3 Reference to Video node, or use this node's image_3 output.
image_4optIMAGEReference image 4: <Picture 4> in the prompt. Connect the same image to image_4 on the MiniMax H3 Reference to Video node, or use this node's image_4 output.
image_5optIMAGEReference image 5: <Picture 5> in the prompt. Connect the same image to image_5 on the MiniMax H3 Reference to Video node, or use this node's image_5 output.
image_6optIMAGEReference image 6: <Picture 6> in the prompt. Connect the same image to image_6 on the MiniMax H3 Reference to Video node, or use this node's image_6 output.
image_7optIMAGEReference image 7: <Picture 7> in the prompt. Connect the same image to image_7 on the MiniMax H3 Reference to Video node, or use this node's image_7 output.
image_8optIMAGEReference image 8: <Picture 8> in the prompt. Connect the same image to image_8 on the MiniMax H3 Reference to Video node, or use this node's image_8 output.
image_9optIMAGEReference image 9: <Picture 9> in the prompt. Connect the same image to image_9 on the MiniMax H3 Reference to Video node, or use this node's image_9 output.
scenes_from_lyricsoptBOOLEANfalseBuild the whole video from the lyrics: the song is cut where lyric phrases start (needs timestamped lyrics like `[0:15] line`; without timestamps it falls back to the segment mode above) and every scene's imagery is written from its lyric lines - the pictures stage what the words say, while the concept supplies style, palette and motifs. Instrumental stretches still cut on the music.
reference_image_useoptCOMBOCharacters only (ignore picture backgrounds)How the reference pictures may be read. Characters only: every picture is a character/performer reference - identity (and wardrobe) carries over, the photo's background, setting and lighting are ignored, and no scene or location is ever derived from them; a picture note can still declare a specific image a location or prop. Auto: the model decides what each picture shows (a backdrop can become the scene).
scene_briefsoptSTRINGManually planned scenes from chained H3 Scene Brief nodes: each brief (what happens, where, which cast members and pictures) becomes the binding plan for its scene/piece. Pinned numbers take that piece; unpinned briefs fill in order; pieces without a brief stay the model's to invent.
audio_modeoptCOMBOReference audio (<Audio 1> = the song piece)How the song reaches the video model. Reference audio: each piece is attached as ref_audio_1 and the prompts define <Audio 1> (classic Ref2VA; lip-sync is a strong suggestion). Masked latent: for workflows that write the song slice straight into the H3 audio latent and protect it from denoising (e.g. `H3 Song Audio + Masked Video Context` fed by this node's `clip_starts`) - the prompts then reference the protected master-song audio and define no <Audio N>, and lip-sync is enforced by the model itself. Do not wire audio_segments to ref_audio in that setup.
save_scenesoptBOOLEANtrueStore every successful run as a JSON bundle in output/apnext_scenes/ (scenes, synopsis, segment times, durations, clip starts, cast). Reload it any time with APNext H3 Scenes Load - re-render without paying for the LLM again.
scenes_per_calloptINT41–8How many scenes to ask the model for per call. Smaller chunks finish well inside timeout_seconds and fail smaller (a timed-out chunk is retried at half size automatically); larger chunks are slightly cheaper per scene. 1 = every scene written in its own call.

Outputs (22)

NameTypeDescription
scenesSTRING
durationsFLOAT
lengthsINT
audio_segmentsAUDIO
segment_tableSTRING
scenes_textSTRING
synopsisSTRING
castSTRING
scene_countINT
song_secondsFLOAT
session_idSTRING
infoSTRING
image_1IMAGE
image_2IMAGE
image_3IMAGE
image_4IMAGE
image_5IMAGE
image_6IMAGE
image_7IMAGE
image_8IMAGE
image_9IMAGE
clip_startsFLOAT