Nodes/arkennemasis Nodes/arkennemasis Video Assemble (clips + music + subs)
ComfyUI Node

arkennemasis Video Assemble (clips + music + subs)

Concat, level speech, duck the music, burn the subs

By Hishamahmer·Created 2 months ago·Updated 8 days ago· 9
arkennemasis Video Assemble (clips + music + subs)
  • videos
  • caption_style
  • final_path
  • video
output_dir
filenamefinal
scenes_json
music_path
music_volume0.18
normalize_speechtrue
burn_subtitlestrue
word_timings
subtitle_size0
crf18

Scene List fans a plan out so one chain renders every scene; Video Assemble is the node that brings it all back together. It declares INPUT_IS_LIST, so ComfyUI hands it the whole collection of finished clips in a single call, in order, however many there are. Then it does the four jobs that turn loose clips into a film: concatenate, level each clip's speech, trim and duck a music bed under it, and burn subtitles timed from the same scene plan that generated the video.

The problem it fixes before the first frame

Two things would wreck a naive "just join the clips" approach, and both are handled locally here. First, video models mix speech very quietly - measured around -20 to -27 dB on H3 output against roughly -16 LUFS for normal web video. Without levelling, the finished cut sounds nearly mute. normalize_speech (default on) levels each clip to EBU R128 -16 LUFS. Second, the music bed has to sit under the dialogue: music_volume defaults to 0.18, low enough not to fight the speech the clips already carry.

The inputs

Required: videos (wire the scene chain's video output - the loop delivers every scene to this one socket), output_dir (wire from Run Folder; relative paths resolve inside ComfyUI's output directory), and filename (default final).

Optional, and they carry most of the actual features:

  • scenes_json - the same plan that made the clips. Its voiceText fields become the subtitles, timed from each clip's real duration, so cue N starts exactly where clips 1..N-1 ended. That's deliberately better than transcribing the finished audio and hoping the words line up.
  • music_path - absolute path to a music file; blank = no bed. Trimmed to the video length automatically.
  • burn_subtitles (default on) and caption_style - wire a Caption Style node here for fonts and one of five subtitle styles (classic, karaoke, highlight, underline, word-by-word). Leave it unconnected for plain white captions; subtitle_size (default 0 = scale to about 4% of frame height) only applies then.
  • crf - x264 quality, default 18, "visually lossless."

Outputs: final_path (the mp4) and video.

Two implementation details that tell you this was debugged for real

Subtitle timing runs a silencedetect pass on each clip to find where the narration actually stops - a dubbed shot is a fixed slot with a silent tail, so the audio stream's duration no longer says anything about the speech, and captions spread across the whole slot would drift seconds behind the voice. And the whole thing runs through ffmpeg (found on PATH or via imageio-ffmpeg), so the find_ffmpeg failure mode is the one to know about: if nothing's on PATH and imageio-ffmpeg isn't installed, assemble fails at startup.

Install

ArkVideoAssemble is one of the 61 nodes in the comfyui-arkennemasis pack, in arkennemasis/Video:

cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
pip install -r comfyui-arkennemasis/requirements.txt   # then restart ComfyUI

Or ComfyUI Manager → Install via Git URL with the repo URL. It needs ffmpeg available and no API key. This is the node that makes the whole loop worth building: one canvas, N scenes, one film out - 5 scenes or 50, same wiring.

Categoryarkennemasis/Video

Inputs (12)

NameTypeDefaultDescription
videosVIDEOWire the scene chain's video output here. The loop delivers every scene to this one socket, in order.
output_dirSTRINGWhere to write final.mp4. Relative paths resolve inside ComfyUI's output directory. Wire from Run Folder.
filenameSTRINGfinal
scenes_jsonoptSTRINGThe same plan that made the clips. Its voiceText fields become the subtitles, timed from each clip's real duration.
music_pathoptSTRINGAbsolute path to a music file. Blank = no bed. Trimmed to the video length automatically.
music_volumeoptFLOAT0.180–10.18 sits under spoken dialogue. The clips carry their own speech, so this must stay low.
normalize_speechoptBOOLEANtrueLevel each clip to EBU R128 -16 LUFS. Without it the finished cut sounds nearly mute.
burn_subtitlesoptBOOLEANtrue
caption_styleoptARK_CAPTION_STYLEWire a Caption Style node here to choose the font and one of the five subtitle styles. Leave it unconnected for plain white captions at subtitle_size.
word_timingsoptSTRINGMeasured word timings from ArkWordTimings. Supplied, the moving caption styles mark the REAL word and the cue boundaries come from the audio too. Left unwired, both fall back to an estimate that drifts.
subtitle_sizeoptINT00–2000 = scale to the video (about 4% of frame height), which is what you want when one workflow renders previews and finals at different sizes. Only used when caption_style is NOT connected — the style node carries its own size.
crfoptINT180–51x264 quality; lower is better. 18 is visually lossless.

Outputs (2)

NameTypeDescription
final_pathSTRING
videoVIDEO