Video Generation with Sora
The Sora model provides advanced text-to-video generation capabilities. Generate high-quality videos from text descriptions with customizable dimensions and duration.
API Endpoint
POST https://llm.kloud.team/v1/video/generations
Authentication
All API requests require authentication using your Access Key from the dashboard:
Authorization: Bearer YOUR_ACCESS_KEY
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model identifier (e.g., "sora") |
prompt | string | Yes | Text description of the video to generate |
height | string | Yes | Video height in pixels (e.g., "1080") |
width | string | Yes | Video width in pixels (e.g., "1080") |
n_seconds | string | Yes | Video duration in seconds (e.g., "5") |
n_variants | string | Yes | Number of video variants to generate (e.g., "1") |
Basic Usage
Creating a Video Generation Job
curl -X POST "https://llm.kloud.team/v1/video/generations" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_KEY" \
-d '{
"model": "sora",
"prompt" : "A video of a cat",
"height" : "1080",
"width" : "1080",
"n_seconds" : "5",
"n_variants" : "1"
}'
Initial Response
The API returns a JSON response with the video generation job information:
{
"object": "video.generation.job",
"id": "task_01kba05srhfvhar2f6nzna2jb4",
"status": "preprocessing",
"created_at": 1764493551,
"finished_at": null,
"expires_at": null,
"generations": [],
"prompt": "A video of a cat",
"model": "sora",
"n_variants": 1,
"n_seconds": 5,
"height": 1080,
"width": 1080,
"inpaint_items": null,
"failure_reason": null
}
Response Fields
| Field | Type | Description |
|---|---|---|
object | string | Object type identifier: "video.generation.job" |
id | string | Unique job identifier for tracking generation status |
status | string | Current job status: "preprocessing", "processing", "completed", or "failed" |
created_at | integer | Unix timestamp when the job was created |
finished_at | integer | Unix timestamp when the job completed (null if still processing) |
expires_at | integer | Unix timestamp when the generated video expires (null until completed) |
generations | array | Array of generated video URLs (empty until completed) |
prompt | string | The text prompt used to generate the video |
model | string | The model used for generation |
n_variants | integer | Number of video variants requested |
n_seconds | integer | Video duration in seconds |
height | integer | Video height in pixels |
width | integer | Video width in pixels |
inpaint_items | array | Inpainting parameters (null if not used) |
failure_reason | string | Error description if status is "failed" (null otherwise) |
Checking Job Status
Since video generation is asynchronous, you'll need to poll the job status using the returned job ID:
curl -X GET "https://llm.kloud.team/v1/video/generations/jobs/{job_id}" \
-H "Authorization: Bearer YOUR_ACCESS_KEY"
Replace {job_id} with the id from the initial response (e.g., task_01kba05srhfvhar2f6nzna2jb4).
Response While Processing
{
"object": "video.generation.job",
"id": "task_01kba05srhfvhar2f6nzna2jb4",
"status": "running",
"created_at": 1764493551,
"finished_at": null,
"expires_at": null,
"generations": [],
"prompt": "A video of a cat",
"model": "sora",
"n_variants": 1,
"n_seconds": 5,
"height": 1080,
"width": 1080,
"inpaint_items": null,
"failure_reason": null
}
Job Status Values
"preprocessing"- Job is being prepared"running"- Video is being generated"succeeded"- Generation finished successfully"failed"- Generation failed (checkfailure_reason)
Completed Response
When the video generation is complete, the response will include the generated video information:
{
"object": "video.generation.job",
"id": "task_01kba05srhfvhar2f6nzna2jb4",
"status": "succeeded",
"created_at": 1764493551,
"finished_at": 1764493593,
"expires_at": 1764579951,
"generations": [
{
"object": "video.generation",
"id": "gen_01kba06rpmedhtx9r0279w53n7",
"job_id": "task_01kba05srhfvhar2f6nzna2jb4",
"created_at": 1764493593,
"width": 1080,
"height": 1080,
"n_seconds": 5,
"prompt": "A video of a cat"
}
],
"prompt": "A video of a cat",
"model": "sora",
"n_variants": 1,
"n_seconds": 5,
"height": 1080,
"width": 1080,
"inpaint_items": null,
"failure_reason": null
}
Generation Object Fields
object- Object type:"video.generation"id- Unique generation IDjob_id- Reference to the parent jobcreated_at- Unix timestamp when generation completedwidth,height,n_seconds- Video specificationsprompt- The prompt used for this generation
Common Video Dimensions
| Preset | Width | Height | Aspect Ratio | Use Case |
|---|---|---|---|---|
| Square | 1080 | 1080 | 1:1 | Social media posts |
| HD | 1920 | 1080 | 16:9 | Standard video |
| Vertical | 1080 | 1920 | 9:16 | Mobile/Stories |
Code Examples
Python
import requests
import time
import json
# Create video generation job
url = "https://llm.kloud.team/v1/video/generations"
headers = {
"Authorization": "Bearer YOUR_ACCESS_KEY",
"Content-Type": "application/json"
}
data = {
"model": "sora",
"prompt": "A cinematic shot of ocean waves at sunset",
"height": "1080",
"width": "1920",
"n_seconds": "5",
"n_variants": "1"
}
response = requests.post(url, headers=headers, json=data)
job = response.json()
job_id = job['id']
print(f"Job created: {job_id}")
# Poll for completion
status_url = f"https://llm.kloud.team/v1/video/generations/jobs/{job_id}"
while True:
status_response = requests.get(status_url, headers=headers)
job_status = status_response.json()
status = job_status['status']
print(f"Status: {status}")
if status == 'succeeded':
print("Video generation complete!")
print(json.dumps(job_status['generations'], indent=2))
break
elif status == 'failed':
print(f"Generation failed: {job_status['failure_reason']}")
break
time.sleep(10) # Wait 10 seconds before checking again
Node.js
const axios = require('axios');
const API_KEY = 'YOUR_ACCESS_KEY';
const BASE_URL = 'https://llm.kloud.team';
async function generateVideo() {
// Create video generation job
const response = await axios.post(
`${BASE_URL}/v1/video/generations`,
{
model: 'sora',
prompt: 'A cinematic shot of ocean waves at sunset',
height: '1080',
width: '1920',
n_seconds: '5',
n_variants: '1'
},
{
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
const jobId = response.data.id;
console.log(`Job created: ${jobId}`);
// Poll for completion
while (true) {
const statusResponse = await axios.get(
`${BASE_URL}/v1/video/generations/jobs/${jobId}`,
{
headers: { 'Authorization': `Bearer ${API_KEY}` }
}
);
const status = statusResponse.data.status;
console.log(`Status: ${status}`);
if (status === 'succeeded') {
console.log('Video generation complete!');
console.log(JSON.stringify(statusResponse.data.generations, null, 2));
break;
} else if (status === 'failed') {
console.log(`Generation failed: ${statusResponse.data.failure_reason}`);
break;
}
await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds
}
}
generateVideo();
Best Practices
Writing Effective Prompts
- Be specific and descriptive
- Include details about motion, lighting, and style
- Specify camera angles and movements
- Mention mood and atmosphere
Example Prompts
"A cinematic shot of ocean waves crashing on rocks at sunset, slow motion"
"A cat playing with a ball of yarn in soft morning light, top-down view"
"Aerial drone footage of a forest with fog, moving forward slowly"
Duration Guidelines
- Start with shorter videos (5-10 seconds) for testing
- Longer videos consume more resources and take longer to generate
- Consider splitting long scenes into multiple shorter clips
Resource Management
- Higher resolutions increase generation time and cost
- Generate multiple variants to choose the best result
- Monitor your token usage in the dashboard
Generation Time:
Video generation typically takes 1-3 minutes depending on duration and resolution. The API will return immediately with a job ID that you can use to check generation status.
Error Handling
Common Errors
| Error | Description | Solution |
|---|---|---|
| Invalid dimensions | Unsupported width/height combination | Use standard dimensions (see table above) |
| Duration too long | Requested duration exceeds limits | Reduce n_seconds parameter |
| Invalid prompt | Prompt violates content policy | Revise prompt to comply with guidelines |
Retry Logic
Implement exponential backoff for failed requests:
import time
max_retries = 3
retry_delay = 1
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
break
except requests.exceptions.RequestException as e:
if attempt < max_retries - 1:
time.sleep(retry_delay * (2 ** attempt))
else:
raise
Support
For video generation questions or issues:
- Check the Models Deployment guide
- Review Best Practices
- Contact Support