Nodes/Bjornulf_custom_nodes/๐Ÿ”Š๐Ÿ“น Audio Video Sync
ComfyUI Node

๐Ÿ”Š๐Ÿ“น Audio Video Sync

Stretch a looping video to match your audio's length

By justUmenยทCreated 2 years agoยทUpdated about a year agoยท 545
๐Ÿ”Š๐Ÿ“น Audio Video Sync
  • IMAGES
  • AUDIO
  • sync_IMAGES
  • sync_AUDIO
  • sync_audio_path
  • sync_video_path
  • input_video_duration
  • sync_video_duration
  • input_audio_duration
  • sync_audio_duration
  • sync_video_frame_count
โ—„max_speedup1.5โ–บ
โ—„max_slowdown0.5โ–บ
โ—„audio_pathโ–บ
โ—„audio_duration0.000โ–บ
โ—„video_pathโ–บ
โ—„output_fps30.0โ–บ

The author calls this one "overengineered" in his own README, and honestly that's a fair and useful warning - it's solving a genuinely fiddly problem. You've got a video (ideally a loop - a talking-head clip, an idle animation) and an audio track (a TTS line, a voiceover), and they're not the same length. This node reconciles them, and it's specifically built with lip-sync pipelines like MuseTalk in mind, where the animation loop needs to stretch or compress to exactly match a generated voice line.

How it decides what to do

There's real logic here, not just a naive speed-match. If the video is slightly too long, it pads the audio with silence instead of touching the video at all. If the video is way too long, it slows the video down (up to your configured max_slowdown, default 0.5x) and still pads the remaining gap with silence. If the audio is slightly too long, it speeds the video up (up to max_speedup, default 1.5x). If the audio is way too long, same speed-up plus silence padding on top. The goal in every case is a clean loop point - the video's last frame matching its first frame - so if you chain several of these clips together, the cuts transition smoothly instead of jumping.

The inputs and outputs that matter

max_speedup and max_slowdown are the two required knobs - they cap how aggressively the node is allowed to distort your video's timing before it just leans on silence instead. Everything else is optional and flexible about format: you can feed video as a list of IMAGES or as a video_path string, and audio as either an AUDIO type or an audio_path string. audio_duration is optional too - leave it disconnected and the node reads the duration straight off the audio itself. output_fps (default 30) sets the frame rate of the result.

On the output side you get the synced video as both sync_IMAGES and sync_video_path, the synced audio as both sync_AUDIO and sync_audio_path, plus a handful of duration/frame-count numbers (input_video_duration, sync_video_duration, input_audio_duration, sync_audio_duration, sync_video_frame_count) that are genuinely useful to wire into downstream nodes rather than just for display - recovering the video's original FPS this way, for instance, is exactly the kind of thing the README's own example workflow does.

Installing it

ComfyUI Manager: search Bjornulf_custom_nodes, install, restart. By hand:

cd ComfyUI/custom_nodes
git clone https://github.com/justUmen/Bjornulf_custom_nodes

Then install the shared dependencies from requirements.txt inside that folder - this node leans on the pack's ffmpeg/opencv stack (ffmpeg-python, opencv-python) to actually manipulate the video and audio streams, so you need the real ffmpeg binary reachable on your system PATH too. Installing the ffmpeg-python pip package alone does not install ffmpeg itself - that trips people up more than anything else in this pack's video tooling.

Where people get burned

Beyond the missing-ffmpeg trap: give it a video that isn't actually a loop and the "clean transition" logic is fighting a losing battle - the seam will still be visible no matter how well the durations line up, because it's matching length, not content. Pair it with the pack's own Video Ping Pong node if you don't already have a proper loop to feed in. And this pack's video/audio tooling was, in the author's own words on release, tested mainly on Linux - if you're on Windows and something in the ffmpeg chain silently fails, that history is worth remembering before you assume your setup is wrong.

CategoryBjornulf

Inputs (8)

NameTypeDefaultDescription
max_speedupFLOAT1.51โ€“10โ€”
max_slowdownFLOAT0.50.1โ€“1โ€”
IMAGESoptIMAGEโ€”
AUDIOoptAUDIOโ€”
audio_pathoptSTRINGโ€”
audio_durationoptFLOAT0.0000โ€“3600โ€”
video_pathoptSTRINGโ€”
output_fpsoptFLOAT30.01โ€“120โ€”

Outputs (9)

NameTypeDescription
sync_IMAGESIMAGEโ€”
sync_AUDIOAUDIOโ€”
sync_audio_pathSTRINGโ€”
sync_video_pathSTRINGโ€”
input_video_durationFLOATโ€”
sync_video_durationFLOATโ€”
input_audio_durationFLOATโ€”
sync_audio_durationFLOATโ€”
sync_video_frame_countINTโ€”