> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withperf.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Video Generation

> Generate videos with Veo, Runway, Luma, and Pika

# Video Generation API

Generate videos from text prompts using cutting-edge AI models including Google's Veo 3, Runway Gen-3, Luma Dream Machine, and Pika. Video generation is **asynchronous** - you submit a job and poll for completion.

## Create Video Generation

Submit a video generation job.

### Endpoint

```
POST https://api.withperf.pro/v1/video/generations
```

### Request Body

| Parameter          | Type   | Required | Default       | Description                           |
| ------------------ | ------ | -------- | ------------- | ------------------------------------- |
| `prompt`           | string | Yes      | -             | Description of the video to generate  |
| `model`            | string | No       | `runway-gen3` | Video generation model                |
| `duration_seconds` | number | No       | `4`           | Video duration (model-dependent max)  |
| `resolution`       | string | No       | `1080p`       | Output resolution (`720p` or `1080p`) |
| `aspect_ratio`     | string | No       | `16:9`        | Video aspect ratio                    |

### Supported Models

| Model                | Provider  | Max Duration | Resolution | Price          |
| -------------------- | --------- | ------------ | ---------- | -------------- |
| `veo-3`              | Google    | 60s          | 1080p      | \$0.35/second  |
| `runway-gen3`        | Runway    | 16s          | 1080p      | \$0.10/second  |
| `luma-dream-machine` | Luma AI   | 10s          | 1080p      | \$0.06/second  |
| `pika`               | Pika Labs | 4s           | 1080p      | \$0.067/second |

### Aspect Ratios

| Ratio  | Description | Best For                  |
| ------ | ----------- | ------------------------- |
| `16:9` | Widescreen  | YouTube, presentations    |
| `9:16` | Vertical    | TikTok, Instagram Reels   |
| `1:1`  | Square      | Instagram, profile videos |
| `4:3`  | Standard    | Classic video format      |

### Request Examples

#### cURL

```bash theme={null}
curl -X POST https://api.withperf.pro/v1/video/generations \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A serene mountain landscape with flowing water and dramatic clouds, cinematic quality",
    "model": "runway-gen3",
    "duration_seconds": 8,
    "resolution": "1080p",
    "aspect_ratio": "16:9"
  }'
```

#### JavaScript

```javascript theme={null}
const response = await fetch('https://api.withperf.pro/v1/video/generations', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer pk_live_abc123',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'A serene mountain landscape with flowing water and dramatic clouds, cinematic quality',
    model: 'runway-gen3',
    duration_seconds: 8
  })
});

const job = await response.json();
console.log('Job ID:', job.id);
// Poll for completion using the job ID
```

#### Python

```python theme={null}
import requests
import time

# Submit job
response = requests.post(
    'https://api.withperf.pro/v1/video/generations',
    headers={
        'Authorization': 'Bearer pk_live_abc123',
        'Content-Type': 'application/json'
    },
    json={
        'prompt': 'A serene mountain landscape with flowing water and dramatic clouds',
        'model': 'runway-gen3',
        'duration_seconds': 8
    }
)

job = response.json()
job_id = job['id']
print(f'Job submitted: {job_id}')
```

### Response (202 Accepted)

```json theme={null}
{
  "id": "job_vid_abc123",
  "status": "pending",
  "model": "runway-gen3",
  "prompt": "A serene mountain landscape with flowing water and dramatic clouds, cinematic quality",
  "duration_seconds": 8,
  "resolution": "1080p",
  "aspect_ratio": "16:9",
  "estimated_cost_usd": 0.80,
  "perf": {
    "request_id": "req_vid_abc123",
    "model_used": "runway-gen3",
    "latency_ms": 234
  }
}
```

***

## Check Video Generation Status

Poll for the status of a video generation job.

### Endpoint

```
GET https://api.withperf.pro/v1/video/generations/:id
```

### Path Parameters

| Parameter | Type   | Description                                   |
| --------- | ------ | --------------------------------------------- |
| `id`      | string | The job ID returned from the creation request |

### Request Example

```bash theme={null}
curl -X GET https://api.withperf.pro/v1/video/generations/job_vid_abc123 \
  -H "Authorization: Bearer pk_live_abc123"
```

### Status Values

| Status       | Description                               |
| ------------ | ----------------------------------------- |
| `pending`    | Job queued, waiting to start              |
| `processing` | Video is being generated                  |
| `complete`   | Video ready for download                  |
| `failed`     | Generation failed (check `error_message`) |

### Response (Processing)

```json theme={null}
{
  "id": "job_vid_abc123",
  "status": "processing",
  "model": "runway-gen3",
  "prompt": "A serene mountain landscape...",
  "progress_percent": 45,
  "estimated_remaining_seconds": 30
}
```

### Response (Complete)

```json theme={null}
{
  "id": "job_vid_abc123",
  "status": "complete",
  "model": "runway-gen3",
  "prompt": "A serene mountain landscape with flowing water and dramatic clouds, cinematic quality",
  "video_url": "https://storage.withperf.pro/videos/job_vid_abc123.mp4",
  "duration_seconds": 8,
  "resolution": "1080p",
  "aspect_ratio": "16:9",
  "perf": {
    "request_id": "req_vid_abc123",
    "model_used": "runway-gen3",
    "generation_time_ms": 45234,
    "cost_usd": 0.80
  }
}
```

### Response (Failed)

```json theme={null}
{
  "id": "job_vid_abc123",
  "status": "failed",
  "model": "runway-gen3",
  "prompt": "...",
  "error_message": "Content policy violation: prompt contains prohibited content",
  "perf": {
    "request_id": "req_vid_abc123",
    "model_used": "runway-gen3"
  }
}
```

***

## Complete Polling Example

### JavaScript

```javascript theme={null}
async function generateVideo(prompt, options = {}) {
  // Submit job
  const submitResponse = await fetch('https://api.withperf.pro/v1/video/generations', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer pk_live_abc123',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ prompt, ...options })
  });

  const job = await submitResponse.json();
  console.log('Job submitted:', job.id);

  // Poll for completion
  while (true) {
    const statusResponse = await fetch(
      `https://api.withperf.pro/v1/video/generations/${job.id}`,
      { headers: { 'Authorization': 'Bearer pk_live_abc123' } }
    );

    const status = await statusResponse.json();
    console.log('Status:', status.status);

    if (status.status === 'complete') {
      return status.video_url;
    }

    if (status.status === 'failed') {
      throw new Error(status.error_message);
    }

    // Wait 5 seconds before next poll
    await new Promise(resolve => setTimeout(resolve, 5000));
  }
}

// Usage
const videoUrl = await generateVideo(
  'A cat playing piano in a jazz club, cinematic lighting',
  { model: 'runway-gen3', duration_seconds: 8 }
);
console.log('Video ready:', videoUrl);
```

### Python

```python theme={null}
import requests
import time

def generate_video(prompt, model='runway-gen3', duration_seconds=4):
    headers = {'Authorization': 'Bearer pk_live_abc123'}

    # Submit job
    response = requests.post(
        'https://api.withperf.pro/v1/video/generations',
        headers={**headers, 'Content-Type': 'application/json'},
        json={
            'prompt': prompt,
            'model': model,
            'duration_seconds': duration_seconds
        }
    )
    job = response.json()
    job_id = job['id']
    print(f'Job submitted: {job_id}')

    # Poll for completion
    while True:
        status_response = requests.get(
            f'https://api.withperf.pro/v1/video/generations/{job_id}',
            headers=headers
        )
        status = status_response.json()
        print(f'Status: {status["status"]}')

        if status['status'] == 'complete':
            return status['video_url']

        if status['status'] == 'failed':
            raise Exception(status.get('error_message', 'Video generation failed'))

        time.sleep(5)

# Usage
video_url = generate_video(
    'A cat playing piano in a jazz club, cinematic lighting',
    model='runway-gen3',
    duration_seconds=8
)
print(f'Video ready: {video_url}')
```

## Prompt Best Practices

### Be Descriptive

```json theme={null}
{
  "prompt": "Slow motion shot of coffee being poured into a white ceramic cup, steam rising, warm morning light through window, shallow depth of field"
}
```

### Specify Camera Movement

```json theme={null}
{
  "prompt": "Drone shot flying over a mountain range at sunrise, slowly revealing a valley with a river below, cinematic quality"
}
```

### Include Lighting and Mood

```json theme={null}
{
  "prompt": "A lone astronaut walking on Mars surface, dramatic sunset lighting casting long shadows, dust particles in the air, sci-fi atmosphere"
}
```

## Error Responses

### 400 Bad Request

```json theme={null}
{
  "error": {
    "type": "invalid_request",
    "message": "prompt is required"
  }
}
```

### 400 Duration Exceeded

```json theme={null}
{
  "error": {
    "type": "invalid_request",
    "message": "duration_seconds exceeds maximum of 16 for runway-gen3 model"
  }
}
```

### 404 Job Not Found

```json theme={null}
{
  "error": {
    "type": "not_found",
    "message": "Video generation job not found"
  }
}
```

## Rate Limits

| Tier       | Concurrent Jobs | Jobs/Day |
| ---------- | --------------- | -------- |
| Free       | 1               | 5        |
| Pro        | 5               | 100      |
| Enterprise | Custom          | Custom   |

## Related Endpoints

* [Image Generation](./images) - Generate still images
* [Audio Generation](./audio) - Text-to-speech
* [Chat API](./chat) - Text generation
