Recast a video
Put your own person and your own product into a video that you own.
Recast is the identity/product replacement path for Preserve video. It edits footage your workspace owns and requests that the original camera, motion, cuts and timing remain. Review the result for fidelity; matching frames or output length is not guaranteed. For a new script and storyboard, choose Rebuild ad.
Recast runs on seedance-2.5-edit by default. A request that sends elements and no model runs on kling-4, because only Kling accepts identity elements. model chooses the model: seedance-2.5-edit or kling-4. The quote, the idempotency key, the job envelope, the webhook and the refund are the same as for POST /v1/video-edit/kling-4.
1. Choose the source video
Send exactly one source.
| Field | Use it for |
|---|---|
source_video_url | A video on https://cdn.roasos.com that your workspace owns |
source_generation_id | The id of a completed video job in your workspace |
source_generation_id resolves to the output URL of that job. Use it to recast a clip that roasOS made for you, without copying the URL.
On kling-4, the source must be 3 to 30 seconds long, at most 100 MiB, at least 700 px per side, and video/mp4. On seedance-2.5-edit, the source must be 4 to 30 seconds long and at most 100 MiB.
roasOS measures the source and refuses a longer clip with 400 recast_source_too_long, before it prices anything. No credits move on that refusal. Refer to The source length for what to do with a longer ad.
2. Choose the target
Send at least one of these three fields. Without one of them the call is a plain video edit, so roasOS refuses it with 400 recast_target_required.
| Field | What it does |
|---|---|
avatar_id | Uses a saved avatar as one identity element |
product_id | Adds the images of a saved product as style references |
elements | kling-4 only. Locks an identity yourself: 1 to 7 items of { frontal_image_url, reference_image_urls } (1 to 3 views each) |
Add optional references for a look, such as a season or a location. On seedance-2.5-edit, your references, the product images and the avatar share 9 image slots. On the Kling tiers, explicit elements, a saved avatar and all reference images share four slots. The avatar counts as one identity element, and each image resolved from product_id counts as one appearance reference.
Make an avatar over the API with POST /v1/avatar/nano-banana-pro. The MCP tool is roasos_avatar_nano_banana_pro. Send the new id in avatar_id, or send a roasOS gallery avatar. The legacy path POST /v1/avatars answers 503 avatar_generation_unavailable. Its list, get and delete paths work.
A body that carries elements needs a consent record. Send media_rights with it, or roasOS answers 400 media_rights_required. A recast that casts only avatar_id or product_id needs none. Refer to Recast an actor.
Name each identity in the prompt
The provider needs every identity element named one time in the prompt.
On seedance-2.5-edit (the default):
@Image1to@Image9are the images, in this order: yourreferences, the product images, then the avatar.- Write the tags yourself.
On kling-4:
@Video1is the source clip.@Element1to@Element7are theelements, in order.@Image1to@Image9are thereferences, in order.- roasOS appends the tag for
avatar_idwhen your prompt does not carry it. Write the other tags yourself.
Name the requested change, then ask to preserve the remaining motion, camera, cuts, timing and existing captions. Keep generation-only no-text suffixes off an edit.
3. Quote
This example names kling-4, so the avatar binds as @Element1.
curl -X POST https://api.roasos.com/v1/workflows/recast \
-H "Authorization: Bearer roasos_sk_..." \
-H "Idempotency-Key: recast-kitchen-cut-001" \
-H "Content-Type: application/json" \
-d '{
"source_generation_id": "3d2f7b90-6c11-4a8d-9b02-77e5a1c4d380",
"prompt": "Replace the woman with @Element1. Keep the product, the hands and the lighting the same.",
"avatar_id": "9c17ab42-0b53-4d1e-8f7a-2c9b6e40a115",
"product_id": "5e6b3311-7a2c-4f19-b3d8-0c41e7f92a63",
"model": "kling-4",
"quote_only": true
}'{
"data": {
"kind": "quote",
"quote_id": "c4a0e918-...",
"credits": 17,
"expires_at": "2026-08-21T11:12:19.000Z",
"pricing_version": "customer-pricing@2026-10-30.v14",
"confirmation": {
"model": "kling-4",
"mode": "edit",
"duration_seconds": 5,
"reference_count": 2
}
}
}Read confirmation. It states what roasOS understood. Credits are reserved from the measured source duration. Completion refunds credits proportionally for shorter output and caps longer output at the approved quote; the source is not billed again as an input-video offset.
4. Confirm
Send the same body with the quote_id. Use the same idempotency key. Add webhook_url when you do not want to poll.
curl -X POST https://api.roasos.com/v1/workflows/recast \
-H "Authorization: Bearer roasos_sk_..." \
-H "Idempotency-Key: recast-kitchen-cut-001" \
-H "Content-Type: application/json" \
-d '{
"source_generation_id": "3d2f7b90-6c11-4a8d-9b02-77e5a1c4d380",
"prompt": "Replace the woman with @Element1. Keep the product, the hands and the lighting the same.",
"avatar_id": "9c17ab42-0b53-4d1e-8f7a-2c9b6e40a115",
"product_id": "5e6b3311-7a2c-4f19-b3d8-0c41e7f92a63",
"model": "kling-4",
"quote_id": "c4a0e918-..."
}'The answer is 201 with the standard job envelope.
{
"data": {
"id": "7b52d0c4-...",
"kind": "video",
"model": "kling-4",
"status": "queued",
"credits_reserved": 17,
"created_at": "2026-08-21T11:02:31Z",
"links": {
"self": "/v1/jobs/7b52d0c4-...",
"status": "/v1/jobs/7b52d0c4-.../status",
"result": "/v1/jobs/7b52d0c4-.../result",
"events": "/v1/jobs/7b52d0c4-.../events"
}
}
}5. Poll the job
curl https://api.roasos.com/v1/jobs/7b52d0c4-.../status \
-H "Authorization: Bearer roasos_sk_..."A recast is an ordinary job, so it carries the five job statuses. Poll every few seconds until the status is completed, failed or canceled. Refer to Jobs and to Webhooks.
6. Read the result
curl https://api.roasos.com/v1/jobs/7b52d0c4-.../result \
-H "Authorization: Bearer roasos_sk_..."{
"data": { "url": "https://cdn.roasos.com/workspaces/.../recast.mp4" }
}The URL is immutable. Send it as the media input of your next call.
Rights
You may recast only a video that your workspace owns.
roasOS checks the source against the workspace media rules before it prices anything. An immutable object under workspaces/… or uploads/… on https://cdn.roasos.com passes. Every other URL fails with 400 reference_media_not_workspace_owned.
A Discover creative is a competitor's ad. Recast accepts it as the source video. You are responsible for the rights to the footage you recast. Refer to Media rights.
Price
The quote reserves credits from the measured source length.
Choose the tier
model chooses the model. The default is seedance-2.5-edit, the preserve-video role in roasos_get_catalog. A request with elements and no model uses kling-4.
model | Reserved credits for 5 s | Reserved credits for 15 s |
|---|---|---|
seedance-2.5-edit (default) | 18 | 54 |
kling-4 (default with elements) | 17 | 51 |
Both models bill the source seconds and the output seconds. The Kling 4.0 values are at 1080p, its default tier. A longer output cannot exceed the approved quote. The full tables are on the model pages: Kling 4.0 Edit.
seedance-2.5-edit takes a source up to 30 seconds and up to 9 reference images. On it, references alone is a valid target, and elements is refused. The model page states its price: Seedance 2.5 Edit.
Limits
- The source must be 3 to 30 seconds on
kling-4and 4 to 30 seconds onseedance-2.5-edit. A longer clip is400 recast_source_too_long. - Keep the prompt at 2,500 characters or fewer. Every recast model holds the same limit.
- On
kling-4, the edit has no audio control. Do not promise the original sound. - The source length sets the reservation. Review output duration: shorter output receives a proportional refund, and longer output cannot exceed the approved quote.
Errors
| Code | Cause |
|---|---|
recast_target_required | No avatar_id, no product_id and no elements |
recast_source_too_long | The measured source is longer than the model takes: 30 seconds |
media_rights_required | The body carries elements and no media_rights block |
reference_media_not_workspace_owned | The source video or a reference is not workspace-owned media |
invalid_request | Two sources, no source, or more images than the model takes |
insufficient_credits | The balance does not cover the quote |
quote_expired | The quote is older than 10 minutes; quote again under a new idempotency key |
Refer to Errors.
From an agent
The MCP tool is roasos_recast_video. The quote rule is the same. Refer to Connect an AI agent (MCP).