Vidu Q4 Reference To Video API Documentation

Vidu Q4 Reference To Video API Documentation

Playground

Try it on WaveSpeedAI!

Vidu Q4 Reference-to-Video generates subject-consistent AI videos from text prompts, 1-15 reference images, and up to 3 reference audio clips, supporting character consistency, product videos, social content, brand assets, and reference-guided storytelling workflows. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.

Features

Vidu Q4 Reference-to-Video generates a video of 3 to 16 seconds, up to 4K, from a text prompt and up to 15 reference images, so people, products and scenes stay consistent. Add up to 3 voice clips to give characters their own voice.


Why Choose This?

  • Consistent subjects — Characters, products and settings from your references stay recognizable across shots.
  • Up to 15 reference images — Cover several subjects and an environment in a single request.
  • Voice references — Up to 3 MP3 clips guide how the speakers sound.
  • Sound included — Dialogue, effects and ambience are generated with the picture, and can be switched off.
  • Five aspect ratios and five resolutions — From 540p to 4K for widescreen, vertical or square layouts.

Parameters

ParameterRequiredDescription
promptYesThe scene: who does what, the camera movement and the mood.
imagesYes1 to 15 reference images, as an array of public URLs (PNG, JPEG or WebP) or Base64-encoded images.
audiosNoUp to 3 voice reference clips, as an array of MP3 URLs. Each clip lasts 3 to 12 seconds and is at most 50 MB.
aspect_ratioNo16:9, 9:16, 1:1, 3:4 or 4:3. Default: 16:9.
resolutionNo540p, 720p, 1080p, 2k or 4k. Default: 720p.
durationNoLength in whole seconds, from 3 to 16. Default: 5.
generate_audioNoGenerate sound with the video. Default: true.
seedNoFix the seed to compare variations. Omit it, or use -1, for a random seed.

images and audios are arrays even when you send a single item.


How to Use

  1. Collect references — Choose clear images of the characters, products or places that belong in the scene.
  2. Write the prompt — Say what each subject does. Refer to the images by their order in the array: @1 is the first image, @2 the second, and so on.
  3. Add voices (optional) — Provide up to 3 short MP3 clips in audios.
  4. Choose the format — Set the aspect ratio, resolution and duration.
  5. Run — Submit the request and download the video when it finishes.

Pricing

Pricing is based on the selected resolution and video duration.

ResolutionPrice per Second5-Second Video
540p$0.045$0.225
720p$0.095$0.475
1080p$0.12$0.60
2K$0.19$0.95
4K$0.39$1.95

The total is the per-second rate for the selected resolution multiplied by duration (whole seconds, 3 to 16). The default of 720p and 5 seconds costs $0.475. Audio generation and the other settings do not change the price.


Best Use Cases

  • Character-led content — Keep a recurring character or mascot consistent across clips.
  • Product videos — Place a product from several angles into a promotional scene.
  • Brand storytelling — Combine a brand’s visual assets with a written script.
  • Multi-subject scenes — Bring several people and a location together in one shot.
  • Social content — Render the same idea as widescreen, vertical or square.

Pro Tips

  • Use clear references that belong in the scene, and avoid contradictory ones unless the contrast is intended.
  • Say how each important subject should look and behave, and tie it to its image with @1, @2.
  • Keep the action small enough to finish within the chosen duration.
  • Treat the two audio controls separately: audios gives the model voices to follow, and generate_audio decides whether the video has sound at all.
  • Explore at 540p or 720p, then render the final clip at a higher resolution.
  • A fixed seed makes variations easier to compare, but identical output is not guaranteed.

Authentication

For authentication details, please refer to the Authentication Guide.

API Endpoints

Submit Task & Query Result

set -euo pipefail

export WAVESPEED_API_KEY="your-api-key"

REQUEST_BODY=$(cat <<'JSON'
{
  "prompt": "A cinematic ocean wave at sunrise, highly detailed",
  "images": [
    "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg"
  ],
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 5,
  "generate_audio": true
}
JSON
)

# 1. Submit the prediction once. Never retry this request automatically:
# a retry after an unclear failure can create a second, billed task.
CHECK='The task may already exist. Check History or the predictions list before submitting again.'
if ! SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 60 \
  -X POST "https://api.wavespeed.ai/api/v3/vidu/q4/reference-to-video" \
  -H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
  -H "Content-Type: application/json" \
  -d "${REQUEST_BODY}"); then
  printf 'Submit failed. %s\n' "${CHECK}" >&2
  exit 1
fi

TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
  printf 'Submission response did not contain a prediction id. %s\n' "${CHECK}" >&2
  exit 1
fi
RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"

# 2. Poll until the prediction reaches a final status.
BODY_FILE=$(mktemp)
trap 'rm -f "${BODY_FILE}"' EXIT
while true; do
  # Transient errors (429, 5xx) are retried, honoring Retry-After.
  HTTP_CODE=$(curl --silent --show-error --fail-with-body \
    --connect-timeout 10 --max-time 60 --retry 5 --retry-delay 2 \
    --output "${BODY_FILE}" --write-out '%{http_code}' \
    "${RESULT_URL}" \
    -H "Authorization: Bearer ${WAVESPEED_API_KEY}" || true)
  case "${HTTP_CODE}" in
    2??) ;;
    000|429|5??)  # dropped connection or temporary error: keep polling
      printf 'Task %s: HTTP %s, polling again in 10s\n' "${PREDICTION_ID}" "${HTTP_CODE}" >&2
      sleep 10; continue ;;
    *) printf 'Task %s: HTTP %s\n' "${PREDICTION_ID}" "${HTTP_CODE}" >&2
      cat "${BODY_FILE}" >&2; exit 1 ;;
  esac
  RESULT=$(jq 'if type == "object" and has("data") then .data else . end' "${BODY_FILE}")
  STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')

  case "${STATUS}" in
    completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
    failed|cancelled|timeout|deleted)
      printf 'Task %s ended with status %s\n' "${PREDICTION_ID}" "${STATUS}" >&2
      printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
    *) sleep 2 ;;
  esac
done

Retry temporary errors only while polling, never the submit request. Errors, retries and timeouts

Parameters

Task Submission Parameters

Request Parameters

ParameterTypeRequiredDefaultRangeDescription
promptstringYes-The positive prompt for the generation.
imagesarray<string>Yes-1 ~ 15 itemsReference images for video generation. Supports up to 15 image URLs or Base64 encoded images.
audiosarray<string>No-0 ~ 3 itemsOptional reference audio files for generation. Supports up to 3 audio references.
aspect_ratiostringNo16:916:9, 9:16, 1:1, 3:4, 4:3The aspect ratio of the generated media.
resolutionstringNo720p540p, 720p, 1080p, 2k, 4kThe resolution of the generated media.
durationintegerNo53 ~ 16The duration of the generated media in seconds.
generate_audiobooleanNotrue-Whether to generate audio.
seedintegerNo--The random seed to use for the generation. 0 or an omitted value uses a random seed.

Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
data.idstringUnique identifier for the prediction, Task Id
data.modelstringModel ID used for the prediction
data.outputsarrayOutput values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed)
data.urlsobjectObject containing related API endpoints
data.statusstringTask status. completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses.
data.created_atstringISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”)
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds

Result Request Parameters

ParameterTypeRequiredDefaultDescription
idstringYes-Task ID

Result Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
dataobjectThe prediction data object containing all details
data.idstringUnique identifier for the prediction
data.modelstringModel ID used for the prediction
data.outputsarray<string | object>Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model.
data.urlsobjectObject containing related API endpoints
data.statusstringStatus: completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses
data.created_atstringISO timestamp of when the request was created
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds
© 2026 WaveSpeedAI. All rights reserved.