Customize your input with more control.
Customize your input with more control.
Type # to reference inputs.
Hint: Drag and drop files from your computer, images from web pages, paste from clipboard (Ctrl/Cmd+V), or provide a URL.
Customize your input with more control.
For every second of 720p video you generated, you will be charged $0.14/second. For 1080p video you will be charged $0.28/second.
For every second of 720p video you generated, you will be charged $0.14/second. For 1080p video you will be charged $0.28/second.
Generate a 1080p video with synchronized native audio from a text prompt and 1–9 reference images. Subject consistency is maintained across the clip using character tokens in your prompt.
Model ID:
Provider: fal.ai
Commercial rights: Full commercial rights on all outputs
Supply between 1 and 9 reference images via . In your prompt, refer to each subject as , , ... — the order matches the order of your array.
For example, two reference images of people could be prompted as:
| Property | Value |
|---|---|
| Resolution | 720p, 1080p |
| Duration | 3–15 seconds |
| Aspect ratios | 16:9, 9:16, 1:1, 4:3, 3:4 |
| Reference images | 1–9 images |
| Input image min size | 400px on shortest side (720p+ recommended) |
| Input image max size | 10 MB each |
| Input formats | JPEG, JPG, PNG, WEBP |
| Prompt length | Up to 2,500 characters |
| Resolution | Price |
|---|---|
| 720p | $0.14 / second |
| 1080p | $0.28 / second |
A 10-second clip at 1080p costs $2.80.
JavaScript:
Python:
JavaScript:
Python:
Note: Reference images must be publicly accessible URLs. Use the storage helpers below if you need to upload local files first.
| Parameter | Type | Default | Description |
|---|---|---|---|
| string | required | Text description of the video. Reference subjects as – matching the order of . Max 2,500 characters. | |
| list<string> | required | 1–9 reference images. Min 400px shortest side, max 10 MB each. JPEG, JPG, PNG, or WEBP. | |
| | | | | | Output video aspect ratio. | ||
| | | Output video resolution. | ||
| integer (3–15) | Clip length in seconds. | ||
| integer (0–2,147,483,647) | — | Set for reproducible outputs. | |
| boolean | Content moderation on input and output. |
For clips longer than a few seconds, use the queue API to avoid blocking.
JavaScript:
Python:
If your reference images aren't already hosted, upload them before submitting.
JavaScript:
Python:
Security: Never expose your in browser or mobile code. Route requests through a server-side proxy: set as a server environment variable and have your frontend call your own backend endpoint, which forwards the request to fal.
alibaba/happy-horse/reference-to-videoimage_urlscharacter1character2character9image_urls"A dance battle between character1 and character2, cinematic lighting, smooth camera movement."bashnpm install @fal-ai/clientbashpip install fal-clientbashexport FAL_KEY="YOUR_API_KEY"jsimport { fal } from "@fal-ai/client";
const result = await fal.subscribe("alibaba/happy-horse/reference-to-video", {
input: {
prompt: "A dance battle between character1 and character2, cinematic lighting, smooth camera movement.",
image_urls: [
"https://example.com/person-a.jpg",
"https://example.com/person-b.jpg",
],
aspect_ratio: "16:9",
resolution: "1080p",
duration: 5,
},
logs: true,
onQueueUpdate: (update) => {
if (update.status === "IN_PROGRESS") {
update.logs.map((log) => log.message).forEach(console.log);
}
},
});
console.log(result.data.video.url);pythonimport fal_client
def on_queue_update(update):
if isinstance(update, fal_client.InProgress):
for log in update.logs:
print(log["message"])
result = fal_client.subscribe(
"alibaba/happy-horse/reference-to-video",
arguments={
"prompt": "A dance battle between character1 and character2, cinematic lighting, smooth camera movement.",
"image_urls": [
"https://example.com/person-a.jpg",
"https://example.com/person-b.jpg",
],
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5,
},
with_logs=True,
on_queue_update=on_queue_update,
)
print(result["video"]["url"])promptcharacter1character9image_urlsimage_urlsaspect_ratio"16:9""9:16""1:1""4:3""3:4""16:9"resolution"720p""1080p""1080p"duration5seedenable_safety_checkertruejson{
"video": {
"url": "https://...",
"content_type": "video/mp4",
"file_name": "output.mp4",
"file_size": 4404019,
"width": 1920,
"height": 1080,
"fps": 24,
"duration": 5.0,
"num_frames": 120
},
"seed": 1234567
}jsimport { fal } from "@fal-ai/client";
// Submit
const { request_id } = await fal.queue.submit("alibaba/happy-horse/reference-to-video", {
input: {
prompt: "character1 walks through a sunlit forest, cinematic.",
image_urls: ["https://example.com/person-a.jpg"],
duration: 15,
resolution: "1080p",
},
webhookUrl: "https://your-server.com/webhook",
});
// Poll status
const status = await fal.queue.status("alibaba/happy-horse/reference-to-video", {
requestId: request_id,
logs: true,
});
// Fetch result once complete
const result = await fal.queue.result("alibaba/happy-horse/reference-to-video", {
requestId: request_id,
});
console.log(result.data.video.url);pythonimport fal_client
# Submit
handler = fal_client.submit(
"alibaba/happy-horse/reference-to-video",
arguments={
"prompt": "character1 walks through a sunlit forest, cinematic.",
"image_urls": ["https://example.com/person-a.jpg"],
"duration": 15,
"resolution": "1080p",
},
webhook_url="https://your-server.com/webhook",
)
request_id = handler.request_id
# Poll status
status = fal_client.status("alibaba/happy-horse/reference-to-video", request_id, with_logs=True)
# Fetch result once complete
result = fal_client.result("alibaba/happy-horse/reference-to-video", request_id)
print(result["video"]["url"])jsimport { fal } from "@fal-ai/client";
const file = new File([imageBuffer], "reference.jpg", { type: "image/jpeg" });
const url = await fal.storage.upload(file);
// Use `url` in your image_urls arraypythonimport fal_client
url = fal_client.upload_file("path/to/your/reference.jpg")
# Use `url` in your image_urls listFAL_KEYFAL_KEY