Video generation
Generate video clips from a text prompt and optional start and end frames with the asynchronous video task API.
This page explains how to generate video with Engy. It is intended for developers who create video clips from text prompts or images.
How video generation works
Video generation is asynchronous. It uses a task API on the same host and with the same API key as the other endpoints:
- You submit a task with a prompt.
- You poll the task until it succeeds or fails.
- You download the finished MP4 file.
| Endpoint | Description |
|---|---|
POST /v2/video_generation | Submits a task. |
GET /v2/query/video_generation/{task_id} | Returns the status of a task. |
GET /v2/query/video_generation | Lists your tasks from the last 7 days. |
DELETE /v2/video_generation/{task_id} | Cancels a queued task, or deletes a finished task. |
GET /v2/video_generation/{task_id}/content | Downloads the video. |
The available video model is MiniMax-H3. For details, see Models and pricing.
Every response contains a base_resp object. Its status_code is 0 on success. Error responses also contain the standard error object.
Generate a video
Submit a task
curl https://api.engy.ai/v2/video_generation \
-H "Authorization: Bearer $ENGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMax-H3",
"content": [{"type": "text", "text": "A red fox trots across fresh snow at dawn"}],
"duration": 6,
"ratio": "16:9"
}'The response contains the task ID:
{
"task_id": "9f1c2b7e4d6a4f0b8e3c5a7d9b1f2e4c",
"status": "queued",
"base_resp": {"status_code": 0, "status_msg": "success"}
}Poll the task
curl https://api.engy.ai/v2/query/video_generation/$TASK_ID \
-H "Authorization: Bearer $ENGY_API_KEY"A task moves from queued to running, and then to succeeded or failed. A clip usually takes a few minutes after it starts running. Poll every 10 to 30 seconds.
When the task succeeds, task.content.url contains the download link:
{
"task": {
"task_id": "9f1c2b7e4d6a4f0b8e3c5a7d9b1f2e4c",
"status": "succeeded",
"model": "MiniMax-H3",
"duration": 6,
"ratio": "16:9",
"resolution": "768P",
"usage": {"video_seconds": 6.0},
"content": {
"url": "https://api.engy.ai/v2/video_generation/9f1c2b7e4d6a4f0b8e3c5a7d9b1f2e4c/content?token=...",
"content_type": "video/mp4",
"bytes": 4194304,
"expires_at": 1792368000
},
"error": null
},
"base_resp": {"status_code": 0, "status_msg": "success"}
}Download the video
curl -L -o clip.mp4 "$CONTENT_URL"The link is signed and does not require an API key. It is valid for 24 hours, until expires_at. Poll the task again to get a new link.
You can also download the video at any time from GET /v2/video_generation/{task_id}/content with your API key. Both methods return a redirect to a short-lived storage link, so let your client follow redirects.
Complete example
import os
import time
import httpx
BASE_URL = "https://api.engy.ai"
headers = {"Authorization": f"Bearer {os.environ['ENGY_API_KEY']}"}
submit = httpx.post(
f"{BASE_URL}/v2/video_generation",
headers=headers,
json={
"model": "MiniMax-H3",
"content": [{"type": "text", "text": "A red fox trots across fresh snow at dawn"}],
"duration": 6,
"ratio": "16:9",
},
)
submit.raise_for_status()
task_id = submit.json()["task_id"]
while True:
time.sleep(15)
task = httpx.get(
f"{BASE_URL}/v2/query/video_generation/{task_id}", headers=headers
).json()["task"]
if task["status"] in ("succeeded", "failed"):
break
if task["status"] == "failed":
raise RuntimeError(task["error"]["message"])
video = httpx.get(task["content"]["url"], follow_redirects=True)
video.raise_for_status()
with open("clip.mp4", "wb") as f:
f.write(video.content)Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | String | Yes | The video model ID, such as MiniMax-H3. |
content | Array | Yes | Text items, which form the prompt, and optional image items for the start and end frames. |
duration | Integer | No | The length of the clip, in whole seconds, from 4 to 15. Defaults to 5. |
ratio | String | No | adaptive, 21:9, 16:9, 4:3, 1:1, 3:4, or 9:16. Defaults to adaptive. |
resolution | String | No | 768P, which is the only supported value. |
seed | Integer | No | A seed for generation. |
Engy joins the text items in content into one prompt. The prompt can contain at most 7,000 characters.
Set start and end frames
Add an image item with role set to first_frame to fix the opening shot. Add a second image with role set to last_frame to fix the closing shot. An image without a role is used as the first frame.
FIRST="data:image/jpeg;base64,$(base64 -w0 start.jpg)"
curl https://api.engy.ai/v2/video_generation \
-H "Authorization: Bearer $ENGY_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"model": "MiniMax-H3",
"duration": 6,
"content": [
{"type": "text", "text": "The camera pulls back to reveal the whole valley"},
{"type": "image_url", "image_url": {"url": "$FIRST"}, "role": "first_frame"}
]
}
JSONOn macOS, use base64 -i start.jpg instead of base64 -w0 start.jpg.
Frames have the following requirements:
- Each frame is a Base64 data URI. Engy does not download images from URLs.
- The format is JPEG, PNG, or WebP.
- Each side is from 256 to 5,760 pixels.
- The aspect ratio is from 0.4 to 2.5.
- Each frame is at most 30 MB.
Reference images, reference video, and reference audio are not supported.
Limits
| Limit | Value | Status if exceeded |
|---|---|---|
| Prompt length | 7,000 characters | 400 |
| Duration | 4 to 15 seconds, in whole seconds | 400 |
| Resolution | 768P | 400 |
| Frames | One first frame and one last frame | 400 |
| Frame size | 30 MB each | 413 |
| Open tasks | 20 queued or running tasks per account | 429 |
Notifications through callback_url are not supported. Poll the task for its status instead.
Manage tasks
List tasks
GET /v2/query/video_generation lists your tasks from the last 7 days, newest first. It accepts the following query parameters:
| Parameter | Description |
|---|---|
page_num | The page number. Defaults to 1. |
page_size | The number of tasks per page, from 1 to 100. Defaults to 10. |
status | Returns only tasks with this status: queued, running, succeeded, failed, or cancelled. |
model | Returns only tasks for this model. |
task_ids | Returns only the tasks with these IDs, separated by commas. |
Cancel or delete a task
curl -X DELETE https://api.engy.ai/v2/video_generation/$TASK_ID \
-H "Authorization: Bearer $ENGY_API_KEY"| Task status | Result |
|---|---|
queued | The task is cancelled at no charge. |
succeeded or failed | The task and its video file are deleted. |
running | The request fails with status 400. Wait for the task to finish. |
Billing
Video is billed per second of video produced. For the rate, see the pricing page.
- When Engy accepts a task, it reserves credit for the full requested duration. If your balance is insufficient, the request fails with status
402. - When the task succeeds, you are charged for the seconds produced, which
task.usage.video_secondsreports. - A failed or cancelled task is not charged.
If the worker that runs a task stops responding, Engy queues the task again and retries it once before it fails.
Data handling
Zero data retention does not apply to video generation. The prompt and the finished video are stored with the task until you delete it. Frame images are discarded when the task finishes.