Turning a portrait and a voice recording into a short talking video sounds like a “demo day” feature, but the production details matter: public asset URLs, audio length limits, async job handling, and error traces.
This guide walks through the Dreamina Video Generation API on Ace Data Cloud from a builder’s point of view. We will send a portrait image plus a driving audio file, receive a synchronized speaking video, and decide when to use callbacks or polling instead of waiting on one long HTTP request.
What you can do
The Dreamina Video Generation API is designed for audio-driven talking-photo generation. You provide a portrait image via image_url, a driving audio file via audio_url, and optional steering text via prompt. The endpoint generates a video where the person speaks with synchronized lips. The model defaults to omnihuman-1.5.
The core API shape is compact:
Endpoint: POST https://api.acedata.cloud/dreamina/videos
Authorization: Bearer <your API key>
Content-Type: application/json
The required request parameters are image_url and audio_url. Optional fields include model, prompt, mask_url, callback_url, and async.
The smallest useful request
Here is a minimal JSON request body:
{
"model": "omnihuman-1.5",
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voice.wav",
"prompt": "Natural speaking expression, stable face, calm presenter style"
}
And here is the same call as cURL:
curl -X POST 'https://api.acedata.cloud/dreamina/videos' \
-H 'Authorization: Bearer <your API key>' \
-H 'Content-Type: application/json' \
-d '{
"model": "omnihuman-1.5",
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voice.wav",
"prompt": "Natural speaking expression, stable face, calm presenter style"
}'
The guide’s response example returns a platform-level task_id, a trace_id, and a nested data object with the upstream task and media URLs:
{
"success": true,
"task_id": "0c0b4d3a-2f1e-4a6b-9c2d-2b3c4d5e6f70",
"trace_id": "a9063166-26ed-4451-85b5-54e896817c69",
"data": {
"task_id": "362b4fed67bd11f1ad1100163e57d510",
"status": "done",
"video_url": "https://cdn.acedata.cloud/634d760216.mp4",
"image_url": "https://cdn.acedata.cloud/4hfydw.jpg",
"audio_url": "https://cdn.acedata.cloud/6f7d62b18b.wav"
}
}
For an app, data.video_url is the artifact you show to the user. Keep trace_id in logs because it is useful when debugging failed or slow jobs.
Preparing the image and audio
The API is only as good as the assets you send it. For the image, use a clear, well-lit, front-facing portrait. The face should be unobstructed and reasonably large in the frame. This is the kind of constraint you should enforce in your UI copy before users upload anything.
For the audio, use a public mp3 or wav URL. The guide says to keep audio under 60 seconds, with 30 seconds or less recommended for 1080p and 60 seconds or less for 720p. Both image_url and audio_url must be reachable from the public internet.
That last point is easy to miss. A signed URL that expires too quickly, a private S3 object, or a localhost link will fail. In a production flow, upload the portrait and audio to durable public URLs before calling the API.
Synchronous, callback, or polling?
By default, the endpoint runs synchronously and returns the finished video. That is convenient for short tests, but video generation can take long enough that you may not want to keep a web request open.
The guide documents two async patterns. First, you can pass callback_url:
{
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voice.mp3",
"callback_url": "https://example.com/webhooks/dreamina-result"
}
With this pattern, the endpoint returns a task_id immediately and POSTs the result to your URL when ready.
Second, you can pass async: true:
{
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voice.mp3",
"async": true
}
With async: true, the endpoint returns a task_id immediately, and you poll the result with POST /dreamina/tasks using either task_id or trace_id.
A simple production pattern is: create a local job row with status pending, submit /dreamina/videos, store task_id and trace_id, show a pending state, and mark the job done when the webhook or polling result contains data.video_url.
Handling common failures
The documented errors are straightforward, but you should map them to actionable product states:
-
400 bad_request: missing or invalid parameters such asimage_urloraudio_url -
401 authorization_missingorinvalid_token: missing or invalid token -
403 forbidden: insufficient balance or quota, or upstream not authorized -
429 too_many_requests: rate limit exceeded -
500 api_error: internal server error
The error response includes trace_id:
{
"error": {
"code": "bad_request",
"message": "image_url is required (a public URL of a portrait image)"
},
"trace_id": "2efa9340-b21b-4e26-9e14-4aac95f343ab"
}
In your client, branch on error.code, show a human-readable message, and always log trace_id.
A practical checklist
Before you ship a talking-photo feature, I would add these checks:
- require a clear frontal portrait before upload
- validate that audio is mp3 or wav and under the duration limit
- upload both files to public URLs before calling the API
- keep
Authorization: Bearer <your API key>server-side - store
task_id,trace_id, input URLs, anddata.video_url - prefer
callback_urlorasync: truefor user-facing workflows
That gives you a small but reliable pipeline: portrait plus voice in, video_url out, and enough task metadata to debug what happened.
The maintained reference for fields, async behavior, and errors is here: https://platform.acedata.cloud/documents/dreamina-videos-integration

Top comments (0)