Kling Talking Photo (Ace Data Cloud)
One portrait plus one audio file
- status
- task_id
- media_urls_json
- first_media_url
- result_json
- trace_id
What it does, and who it's for
Give it a portrait and an audio track, get back a video of that face saying those words. No driving video, no performance reference, no prompt gymnastics - the audio is the direction. That makes it the cleanest expression of an audio-driven avatar in this whole pack: Kling Talking Photo.
Where it fits in the wider stack matters, because this is a solved-ish problem locally now. LTX-2.3 generates video and audio in one pass, and the community's answer to lipsync turned out to be chaining it with Wan Animate. That pipeline is free per run and genuinely good when it behaves - the complaint that never goes away is prompt adherence and identity drift, plus a habit of making background characters start mouthing along. If what you want is one still image, one audio file, and a result without a five-node scaffold, the hosted route is simply less work. This node is that route.
How it works
Two required inputs, and they're both URLs: image_url for the portrait and audio_url for the track. The service conditions the face on the audio and renders the result. model selects one of six IDs ranging from kling-v1 up to kling-v2-6, with (from JSON/default) handing the choice back to the API default. duration is an enum of exactly 5 or 10 seconds - not a free number, so long audio isn't going to be rendered in one job. mode is std or pro. prompt is optional and is not where the performance comes from; it's there for guidance.
Two things the node does for you before any request goes out: the payload is validated against the published API contract with jsonschema, so malformed calls cost nothing, and async: true is forced onto the request. You get a task ID back in about a second and the render happens on Ace's side. Poll it with Kling Retrieve Task, or bump wait_seconds there.
Inputs and outputs
The widgets you'll actually set: image_url, audio_url, model, duration, mode, and optionally prompt. Plus callback_url if you're wiring a webhook, and parameters_json as the advanced escape hatch - a nonempty widget overrides the matching key inside it.
Remember the pack's convention: every widget is a STRING. duration gets typed as 10. A JSON object goes in parameters_json as text.
Outputs: status, task_id, media_urls_json, first_media_url, result_json, trace_id - all STRING. first_media_url → Kling Load Video for a native VIDEO. Note that the output clip can be silent even when the input audio was the whole point; if you need the audio back as a ComfyUI AUDIO, that's Kling Load Audio on the appropriate URL.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/AceDataCloud/KlingComfyUI
cd KlingComfyUI && python -m pip install -r requirements.txt
# restart ComfyUI
Manager: search Kling, confirm publisher acedatacloud and package Kling by Ace Data Cloud (Registry ID kling). Just requests and jsonschema; no local TTS, no avatar model, no weights. The native video loader wants ComfyUI 0.39.0+.
export ACEDATACLOUD_API_KEY=your_key_here # then launch ComfyUI
Common issues
The audio must already exist as a URL. This node takes audio_url, not a file from your disk - so if you generated the voice locally with Kokoro, Chatterbox or F5-TTS, you have to host the result somewhere fetchable first. That's the step people forget, and it's the reason some users end up at Kling Voices instead: create a voice in the service, then push the text through Kling Lip Sync's text2video mode and skip hosting anything.
Portrait choice does most of the work. Front-facing, even lighting, mouth visible, not a screenshot of a screenshot. A full-body shot or a tilted profile produces exactly what you'd expect - the model guessing.
duration is 5 or 10, and that's it. Anything longer needs stitching, which is a workflow problem, not a node setting. There's no "full track" button.
The pack has essentially no community footprint - a literal search for "Ace Data Cloud" in the Reddit corpus comes back empty - so you're not going to find troubleshooting threads for this node. The pack's own error messages are unusually specific ("Task is pending; retrieve the same task ID again"), which helps, and trace_id is your handle if you have to ask the provider.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| parameters_json | STRING | {} | — |
| model | COMBO | (from JSON/default) | 7 options: (from JSON/default), kling-v1, kling-v1-6, kling-v2-master, kling-v2-1-master, kling-v2-5-turbo, +1 |
| image_url | STRING | — | |
| audio_url | STRING | — | |
| prompt | STRING | — | |
| duration | STRING | — | |
| mode | STRING | — | |
| callback_url | STRING | — |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| status | STRING | — |
| task_id | STRING | — |
| media_urls_json | STRING | — |
| first_media_url | STRING | — |
| result_json | STRING | — |
| trace_id | STRING | — |