3D to Video turns a rough 3D viewport animation (a clay render or a blocking playblast from Blender, Unreal or similar) into a finished shot: the camera move and object placement follow your layout, and the look follows a reference image. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.
Idle
$0.04per run·~25 / $1
A cozy log cabin among snow-dusted pine trees, a trodden path in fresh snow, golden winter light, photoreal cinematic shot.
A cozy log cabin among snow-dusted pine trees, a trodden path in fresh snow, golden winter light, photoreal cinematic shot.
3D to Video turns a rough 3D viewport animation into a finished shot. Export a grey clay render or a simple blocking playblast from Blender, Unreal, or any 3D tool, add one image that shows the look you want, and get a video that moves exactly like your layout and looks like your image.
Your camera, your blocking The camera path, the timing, and where objects sit come from your layout and stay aligned through the shot.
Art direction from one image Palette, lighting, and materials follow the look image. No texturing, lighting, or rendering in the 3D tool.
Rough layouts work A blocking animation built from boxes, spheres, and cylinders is enough. A detailed clay render is not required.
Fast look development Try several looks for the same shot by changing only the image and the prompt.
| Parameter | Required | Description |
|---|---|---|
| video | Yes | The layout video: a 3D viewport animation (grey clay render or blocking playblast). It sets the camera move, the motion, and object placement. 24 fps works best. |
| image | Yes | The look image. Take the first frame of the layout video and turn it into the finished look with any image model. Do not use the grey layout frame itself. |
| last_image | No | The look of the shot's last frame, in the same style as image. Recommended for shots longer than about three seconds. |
| prompt | Yes | One or two sentences describing the finished shot, matching the look image. |
| target_resolution | No | Output resolution: 720p or 1080p. Default: 1080p. The layout's aspect ratio is preserved. |
| seed | No | Random seed for reproducible results. |
Pricing is based on the layout video's duration and selected target_resolution.
Billed duration is rounded up to the next whole second, with a minimum billed duration of 3 seconds and a maximum billed duration of 120 seconds.
| Output Resolution | Per 5s | Per second |
|---|---|---|
| 720p | $0.20 | $0.04 |
| 1080p | $0.50 | $0.10 |
last_image: take the layout's last frame and restyle it the same way. Very long layouts still drift in the middle, so keep shots short.120 seconds.Grab a WaveSpeedAI API key, then call POST https://api.wavespeed.ai/api/v3/wavespeed-ai/3d-to-video with your input as JSON. The endpoint returns a prediction id. Start polling the result endpoint around every 2 seconds, increase the interval for long-running tasks, and stop on any terminal status. On completed, read output values from data.outputs. Examples for 3d To Video below.
set -euo pipefail
: "${WAVESPEED_API_KEY:?Set WAVESPEED_API_KEY}"
REQUEST_BODY=$(cat <<'JSON'
{
"video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
"image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
"prompt": "A cinematic shot of a city at sunset, soft golden light",
"target_resolution": "1080p"
}
JSON
)
# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
-X POST "https://api.wavespeed.ai/api/v3/wavespeed-ai/3d-to-video" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $WAVESPEED_API_KEY" \
-d "$REQUEST_BODY")
TASK=$(printf '%s' "$SUBMIT_RESPONSE" | jq 'if has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "$TASK" | jq -r '.id')
if [ -z "$PREDICTION_ID" ] || [ "$PREDICTION_ID" = "null" ]; then
printf 'Submission response did not contain a prediction id
' >&2
exit 1
fi
RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/$PREDICTION_ID/result"
# 2. Poll until the prediction finishes.
while true; do
RESPONSE=$(curl --silent --show-error --fail-with-body "$RESULT_URL" \
-H "Authorization: Bearer $WAVESPEED_API_KEY")
RESULT=$(printf '%s' "$RESPONSE" | jq 'if has("data") then .data else . end')
STATUS=$(printf '%s' "$RESULT" | jq -r '.status')
case "$STATUS" in
completed) printf '%s\n' "$RESULT" | jq '.outputs'; break ;;
failed|cancelled|timeout|deleted) printf '%s\n' "$RESULT" | jq . >&2; exit 1 ;;
*) sleep 2 ;;
esac
doneconst submitUrl = "https://api.wavespeed.ai/api/v3/wavespeed-ai/3d-to-video";
const apiKey = process.env.WAVESPEED_API_KEY;
if (!apiKey) throw new Error('Set WAVESPEED_API_KEY');
async function requestJson(url, options = {}) {
const response = await fetch(url, options);
if (!response.ok) throw new Error(await response.text());
return response.json();
}
// 1. Submit the prediction.
const body = await requestJson(submitUrl, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
"image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
"prompt": "A cinematic shot of a city at sunset, soft golden light",
"target_resolution": "1080p"
}),
});
const task = body.data ?? body;
if (!task.id) throw new Error("Submission response did not contain a prediction id");
const resultUrl = `https://api.wavespeed.ai/api/v3/predictions/${task.id}/result`;
// 2. Poll until the prediction finishes.
while (true) {
const resultBody = await requestJson(resultUrl, {
headers: { "Authorization": `Bearer ${apiKey}` },
});
const result = resultBody.data ?? resultBody;
if (result.status === "completed") {
console.log(result.outputs);
break;
}
if (["failed", "cancelled", "timeout", "deleted"].includes(result.status)) throw new Error(JSON.stringify(result));
await new Promise(resolve => setTimeout(resolve, 2000));
}import json
import os
import time
from urllib.request import Request, urlopen
api_key = os.environ["WAVESPEED_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
payload = {
"video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
"image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
"prompt": "A cinematic shot of a city at sunset, soft golden light",
"target_resolution": "1080p"
}
def request_json(url, data=None):
request = Request(url, data=data, headers=headers, method="POST" if data else "GET")
with urlopen(request) as response:
return json.load(response)
# 1. Submit the prediction.
body = request_json("https://api.wavespeed.ai/api/v3/wavespeed-ai/3d-to-video", json.dumps(payload).encode())
task = body.get("data", body)
if not task.get("id"):
raise RuntimeError("Submission response did not contain a prediction id")
result_url = f"https://api.wavespeed.ai/api/v3/predictions/{task['id']}/result"
# 2. Poll until the prediction finishes.
while True:
result_body = request_json(result_url)
result = result_body.get("data", result_body)
status = result.get("status")
if status == "completed":
print(result.get("outputs", []))
break
if status in {"failed", "cancelled", "timeout", "deleted"}:
raise RuntimeError(result)
time.sleep(2)3d To Video is a WaveSpeedAI model for video editing, exposed as a REST API on WaveSpeedAI. 3D to Video turns a rough 3D viewport animation (a clay render or a blocking playblast from Blender, Unreal or similar) into a finished shot: the camera move and object placement follow your layout, and the look follows a reference image. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing. You can call it programmatically or try it from the playground above.
POST your input parameters to the model's REST endpoint (shown in the API tab of this playground) with your WaveSpeedAI API key in the Authorization header. Submission returns a prediction ID. Poll the result endpoint starting around every 2 seconds, increase the interval for long-running tasks, and stop on any terminal status. The playground generates Python, JavaScript, and cURL examples for submitting requests and polling results. Full request/response shape is documented at https://wavespeed.ai/docs/docs-api/wavespeed-ai/3d-to-video.
3d To Video starts at $0.04 per run or per second. That figure is the base price — the final charge scales with the parameters you set in the form (output size, length, count, references, or whatever knobs this model exposes), so a higher-quality or larger output costs more than a minimal one. The exact cost for your current input is shown live next to the Generate button before you submit, and the actual per-call charge is recorded on the prediction afterwards.
Key inputs: `prompt`, `image`, `video`, `seed`, `last_image`, `target_resolution`. The full JSON schema (types, defaults, allowed values) is rendered above the Generate button and mirrored in the API reference at https://wavespeed.ai/docs/docs-api/wavespeed-ai/3d-to-video.
Sign up for a free WaveSpeedAI account to claim starter credits, copy your API key from /accesskey, then call the endpoint shown in the API tab of the playground. The playground also auto-generates a code sample in Python, JavaScript, or cURL for the parameters you've set.
Commercial usage rights depend on the model's license, set by its provider (WaveSpeedAI). Check the provider's applicable terms and WaveSpeedAI's Terms of Service before commercial use.