Nodes/comfyui_merge_video/Video Merge Node
ComfyUI Node

Video Merge Node

Finishing frames with subtitles and audio

By DEMOUSL·Created 5 months ago·Updated 5 months ago· 0
Video Merge Node
  • video_frames
  • voice_audio
  • background_audio
  • output_video_path
  • Filenames
srt_text1 00:00:00,000 --> 00:00:02,000 示例字幕
fps25.0
subtitle_styleclassic_white
filename_prefixMergeVideo
font_nameMicrosoft YaHei
font_size0
voice_volume1.00
bgm_volume0.35
video_codeclibx264
audio_codecaac
encoder_presetveryfast
audio_bitrate_k192
crf18

Generating frames is the easy half. After Wan, LTX or AnimateDiff hands you a decoded IMAGE batch, you're looking at raw frames - no subtitles, no voice, no music, no muxed file you can actually post. Most people drag that clip into CapCut and finish it there. VideoMergeNode from the comfyui_merge_video pack wants that last mile to happen inside ComfyUI instead: one output node that takes your frame batch, an SRT subtitle string, and two audio tracks, and writes a finished .mp4 straight into your output folder. No API, no key, no manual ffmpeg step.

It's a small pack - a single node, a single commit - so don't expect a maintained ecosystem around it. But the thing it does is exactly the boring glue that most video workflows lack, and it does it in one click.

How it works

The mechanism is ffmpeg doing what ffmpeg does, but driven from the graph. Your video_frames tensor is piped in as raw frames at the fps you set, the SRT is burned in with ffmpeg's subtitles filter using an ASS-style force_style, and that gets encoded as H.264. Then the two AUDIO tracks are resampled to 48 kHz stereo, padded or trimmed to the exact video duration, volume-mixed, and muxed in. Because it writes exactly frame_count frames and trims audio to duration, you don't get the classic bug of every naive merge: a black tail tacked onto the end of your clip.

The inputs that actually matter

  • video_frames (IMAGE) - your decoded video frame batch, straight out of the VAE.
  • voice_audio and background_audio (AUDIO) - both use ComfyUI's native AUDIO type, so feed them whatever your TTS or audio nodes emit. Voice defaults to full volume, BGM to 0.35, which is a sane starting mix.
  • srt_text - a multiline STRING that must be valid SRT (with --> timestamps). It validates this, so a typo gets you a clean error instead of silent garbage. Heads up: the default is a Chinese sample subtitle - swap it for your own or every render will say 示例字幕.
  • fps - this is the sync lever. Because the input is a frame batch, there's no framerate metadata, so the node defines one: duration = frame_count / fps. If your clip was generated at 16 fps and you leave this at 25, your subtitles and audio will drift off the action. Match it to your generation rate.
  • subtitle_style - six baked-in presets (classic_white, short_video_yellow, cinematic_box, news_blue, minimal_clean, karaoke_glow). Pick one, don't expect to fine-tune it.

Worth touching in optional land: font_name defaults to Microsoft YaHei, a Windows font - on Linux or macOS change it or subtitles may fall back to a boxy default. font_size of 0 means auto (about 4.6% of frame height). The codec fields (video_codec, crf, encoder_preset, audio_bitrate_k) are there if you care; the defaults are fine.

The outputs are output_video_path (a STRING with the full path to the new mp4) and a VHS_FILENAMES pair for chaining with VideoHelperSuite nodes. Since this is an output node, you'll see the result in the UI preview.

Installing it

No model downloads, no heavy deps - the real requirements are ffmpeg and torchaudio. Install via ComfyUI Manager (search "comfyui_merge_video") or:

cd ComfyUI/custom_nodes
git clone https://github.com/DEMOUSL/comfyui_merge_video
# restart ComfyUI

Then make sure ffmpeg is on your PATH with subtitle filter support (libass). The code checks COMFYUI_FFMPEG/FFMPEG env vars, falls back to an imageio-ffmpeg binary, then PATH - but that imageio fallback build often lacks libass, so don't rely on it for subtitles.

Where people get burned

The two real failure modes, both grounded in the source: the node doesn't show up at all because torchaudio isn't in your ComfyUI environment (it's imported at module load - pip install torchaudio matching your torch version fixes it), and subtitles fail or vanish because ffmpeg was built without libass (grab a full build - gyan.dev on Windows, brew install ffmpeg on macOS - and put it on PATH). Everything else is the usual: out-of-sync subs means your fps doesn't match the generation rate, and missing glyphs mean your font_name isn't installed. For a zero-impression node this is solidly useful - it just wants a proper ffmpeg and a matching fps.

Categoryvideo/audio

Inputs (16)

NameTypeDefaultDescription
video_framesIMAGE
voice_audioAUDIO
background_audioAUDIO
srt_textSTRING1 00:00:00,000 --> 00:00:02,000 示例字幕
fpsFLOAT25.01–120
subtitle_styleCOMBOclassic_white6 options: classic_white, short_video_yellow, cinematic_box, news_blue, minimal_clean, karaoke_glow
filename_prefixoptSTRINGMergeVideo
font_nameoptSTRINGMicrosoft YaHei
font_sizeoptINT00–200
voice_volumeoptFLOAT1.000–4
bgm_volumeoptFLOAT0.350–4
video_codecoptSTRINGlibx264
audio_codecoptSTRINGaac
encoder_presetoptSTRINGveryfast
audio_bitrate_koptINT19264–512
crfoptINT180–51

Outputs (2)

NameTypeDescription
output_video_pathSTRING
FilenamesVHS_FILENAMES