lipsync-2-pro
Make the mouth match the audio, without a local model
- video
Lip sync is one of those jobs that's miserable to do well locally - the open-weights options are fiddly, VRAM-hungry, and produce that "mouth moves but face is dead" effect. lipsync-2-pro, from Sync, is the hosted, polished version: give it a video and an audio track (each as a UUID or URL), and it returns the same video with the mouth re-synced to the new audio. The "pro" in the name isn't marketing - it's the higher-fidelity tier of Sync's lipsync line.
Where this differs from the other Sync node in the pack (react-1): react-1 re-animates the whole facial performance - emotion, head motion, expression - to drive a character. This node's scope is narrower and safer: it just fixes the lips. If you have footage where the dialogue track changed (ADR, dubbing, a new voiceover) and you only need the mouth to track, this is the node, and it's the one with fewer ways to go wrong.
Inputs that matter
video and audio are both required, as UUIDs or URLs - stage them through Runware's upload nodes first, because there's no file-picker socket here. Then:
providerSettings.sync.temperature- expressiveness of the lip and facial movement, 0–1, default 0.5. Low is stiff, high is lively. For natural results most people land in the 0.6–0.8 range; the default is the safe start, not the best end.providerSettings.sync.syncMode- how to reconcile audio/video length mismatches:bounce(default, ping-pongs the video),loop,cut_off,silence,remap(stretch to fit).providerSettings.sync.activeSpeakerDetection.autoDetect- find and target the talking person automatically when the shot has multiple faces. Off by default; turn it on for group shots.providerSettings.sync.occlusionDetectionEnabled- handles faces briefly covered (hands, objects). On if your subject gestures while talking; costs a little latency.advanced_json- the escape hatch, specifically forproviderSettings.sync.segments. If you need per-segment control (different audio mapped to different parts of the clip), that's where it goes.
numberResults (up to 4), outputFormat (MP4/WEBM/MOV), outputQuality, and safety.mode (none/fast/full) round out the tail.
How it works
The node sends sync:lipsync-2-pro@1 as a videoInference task through the Runware SDK. The result comes back as a native VIDEO socket, ready for SaveVideo or any video consumer. It's fully server-side - no weights on your disk, no local inference - and the title bar prints the per-run cost and content-check verdict.
Install and gotchas
cd ComfyUI/custom_nodes
git clone https://github.com/Runware/ComfyUI-Runware
pip install -r ComfyUI-Runware/requirements.txt
Restart; API key via Settings → "Runware API key", RUNWARE_API_KEY, or runware auth login. Paid per run, minimum top-up.
The realistic warnings: it's slow - hosted performance-transfer jobs take a while, so don't build a real-time loop around it. The two STRING inputs (UUID/URL) are the number-one source of confusion; people try to wire VIDEO/AUDIO sockets straight in and get nothing. And keep expectations calibrated: "lipsync-2-pro" fixes mouth timing and basic facial motion - it won't re-stage a performance the way react-1 does. If your footage has heavy head motion or the actor's face is partially occluded, flip on occlusionDetectionEnabled before you blame the model.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| video | STRING | Video input (UUID or URL). | |
| audio | STRING | Audio input (UUID or URL). | |
| numberResultsopt | INT | 11–4 | Number of results to generate. Each result uses a different seed, producing variations of the same parameters. |
| providerSettings.sync.activeSpeakerDetection.autoDetectopt | BOOLEAN | false | Automatically detect and target the active speaker. |
| providerSettings.sync.occlusionDetectionEnabledopt | BOOLEAN | false | Enable occlusion handling for obstructed faces. |
| safetyopt | BOOLEAN | false | Enable to set safety. Off uses the model's default. |
| safety.checkContentopt | BOOLEAN | false | Enable or disable content safety checking. |
| safety.modeopt | COMBO | fast | Safety checking mode for video generation. |
| providerSettings.sync.syncModeopt | COMBO | bounce | Synchronization strategy when audio and video durations don't match. |
| providerSettings.sync.temperatureopt | FLOAT | 0.500–1 | Expressiveness of lip sync and facial movements. |
| ttlopt | BOOLEAN | false | Enable to set ttl. Off uses the model's default. |
| ttl_valueopt | INT | 60 | Time-to-live (TTL) in seconds for generated content. Only applies when `outputType` is `URL`. |
| outputFormatopt | COMBO | MP4 | File format for the generated video. |
| outputQualityopt | INT | 9520–99 | Compression quality of the output. Higher values preserve quality but increase file size. |
| advanced_jsonopt | STRING | Optional JSON merged into the request. For: providerSettings.sync.segments |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |