Nodes/ComfyUI-Easy-Media/Easy Bernini S2V Conditioning
ComfyUI Node

Easy Bernini S2V Conditioning

Bernini, Now With Mouths That Move

By yolain·Created 3 months ago·Updated about 15 hours ago· 158
Easy Bernini S2V Conditioning
  • positive
  • negative
  • vae
  • audio_0
  • mask_0
  • audio_1
  • mask_1
  • source_video
  • reference_video
  • reference_images
  • positive
  • negative
  • latent
width832
height480
length81
batch_size1
second_speaker_start_frame-1
mask_crossfade_frames4
audio_inject_scale1.00
ref_max_size848

The king was mute. This node gives it a voice.

Bernini - ByteDance's Wan 2.2 fine-tune that took over local video editing - has a famous weakness. The community put it bluntly: "the king is mute." It edits video beautifully, but it has no audio, no lipsync, nothing. If you wanted a talking character you had to generate in Bernini, then Frankenstein audio onto it elsewhere.

Easy Bernini S2V Conditioning is this pack's answer to that. S2V means speech-to-video: it takes the Bernini in-context conditioning (source video, reference images) and merges it with the Wan S2V audio pipeline so the model generates video where the mouth actually matches the audio track. The README credits rzgar/Bernini-R-S2V as the reference - this node is the ComfyUI wrapper around that recipe. It even handles the two-speaker case, so you can dub a conversation between two characters into one clip.

How it works

The node does two independent jobs and combines them into the conditioning:

  1. Bernini context - it VAE-encodes your source_video (the edit base / canvas), reference_video, and reference_images, and attaches them to both positive and negative conditioning as context_latents. Task is inferred from what you connect, same as core Bernini Conditioning: source video alone = v2v, plus refs = rv2v, refs only = r2v.

  2. S2V audio - if audio_0 is connected, it builds an audio_embed from the audio and adds it to the positive conditioning (and zeroed to the negative). In the simplest case - one audio, no mask - you get the original full-frame single-speaker mode: everyone in frame lip-syncs. Connect mask_0 (a mask where white marks speaker 0's mouth region) and it switches to spatially masked injection, so only that region is driven by the audio. Add audio_1 + mask_1 and you get a second speaker.

The latent output is just an empty zeroed latent at your width/height/length - the template the sampler denoises from.

The inputs that matter

  • positive / negative - your CLIP-encoded conditioning. This is the node you feed text into the pipeline with.
  • vae, width / height / length / batch_size - standard video latent geometry. Defaults are 832x480x81, Bernini-ish.
  • audio_0 + mask_0 - the core S2V pair. Audio alone = global single-speaker. Add the mask for spatial control.
  • audio_1 + mask_1 - second speaker. Both masks are required when you go two-speaker.
  • second_speaker_start_frame - -1 (default) starts speaker 1 right after speaker 0's audio ends; set an explicit frame to overlap or delay.
  • mask_crossfade_frames (4) - how many frames the spatial mask fades at the speaker boundary. Higher = softer handoff, less obvious mask edge.
  • audio_inject_scale (1.0) - how hard the audio drives the mouth. Crank it if lips are barely moving, drop it if they're flapping.

Outputs are positive, negative, latent - straight into your sampler.

Setup and the traps

Install comes with the pack (clone Easy-Media or use Manager, restart). You'll want the Bernini Model Patch from the same pack on your Wan 2.2 model, and the S2V model files per the pack's examples - the README points at the Bernini-R-S2V repo and the example workflows under Templates → ComfyUI-Easy-Media (look for "Bernini S2V 1voice" / "2voice").

Where people trip:

  • The validation errors are the spec. audio_0 is required when audio_1 is connected, mask_0 is required..., mask_1 is required... - the node hard-fails on every half-wired combination, on purpose. If you connect audio_1, you must wire mask_0, mask_1, and audio_0 too. There's no partial state.
  • Mask orientation. Remember: white marks the speaker's lips region. A black-on-white mask (background white) inverts everything and you'll get a character who stops syncing exactly where they should be syncing.
  • Forgetting the audio encoder. audio_0/audio_1 take AUDIO_ENCODER_OUTPUT, not raw AUDIO - the Wan S2V audio encoder output. Raw audio from a load node won't slot in directly.

Once it's wired, it's the closest thing to a talking-head Bernini pipeline you'll get locally, and for dialogue or dubbing scenes it beats generating audio separately and hoping the mouth looks fine.

Categoryconditioning/video_models

Inputs (18)

NameTypeDefaultDescription
positiveCONDITIONING
negativeCONDITIONING
vaeVAE
widthINT83216–8192
heightINT48016–8192
lengthINT811–8192
batch_sizeINT11–4096
second_speaker_start_frameINT-1-1–8192-1 starts speaker 1 after speaker 0 ends; otherwise uses this explicit output-video frame.
mask_crossfade_framesINT40–64
audio_inject_scaleFLOAT1.000–10
audio_0optAUDIO_ENCODER_OUTPUTOptional primary speaker audio. Without mask_0 it uses the original full-frame single-speaker mode.
mask_0optMASKWhite marks speaker 0's lip-sync region. Connecting it enables spatially masked audio injection.
audio_1optAUDIO_ENCODER_OUTPUTOptional second speaker audio.
mask_1optMASKRequired when audio_1 is connected.
source_videooptIMAGE
reference_videooptIMAGE
reference_imagesoptCOMFY_AUTOGROW_V3
ref_max_sizeoptINT84816–8192

Outputs (3)

NameTypeDescription
positiveCONDITIONING
negativeCONDITIONING
latentLATENT