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

# Video Studio API Overview

> Transform static images into animated videos with AI-powered motion

## Overview

The Video Studio API enables you to convert static avatar images into dynamic video clips with natural motion, facial animations, and optional audio synchronization. Perfect for creating engaging content, animated presentations, and character-driven media.

## Base URL

```
https://api.percify.io/v1
```

## Core Endpoints

| Method | Endpoint                      | Description                      |
| ------ | ----------------------------- | -------------------------------- |
| POST   | `/videos/from-image`          | Generate video from avatar image |
| GET    | `/videos/{videoId}`           | Get video generation status      |
| GET    | `/videos`                     | List your videos                 |
| POST   | `/videos/{videoId}/add-audio` | Add audio track with lip-sync    |
| PATCH  | `/videos/{videoId}`           | Update video metadata            |
| DELETE | `/videos/{videoId}`           | Delete video                     |

## Video Object

```json theme={null}
{
  "id": "video_xyz789",
  "userId": "user_abc123",
  "avatarId": "avatar_def456",
  "status": "completed",
  "videoUrl": "https://cdn.percify.io/videos/video_xyz789.mp4",
  "thumbnailUrl": "https://cdn.percify.io/videos/video_xyz789_thumb.jpg",
  "durationSeconds": 8,
  "resolution": "720p",
  "fps": 30,
  "fileSize": 3456789,
  "format": "mp4",
  "studioTier": "basic",
  "motionStyle": "moderate",
  "creditCost": 48,
  "hasAudio": false,
  "audioId": null,
  "metadata": {
    "processingTime": 45.2,
    "renderEngine": "video-studio-v3"
  },
  "createdAt": "2025-11-25T06:15:00Z",
  "completedAt": "2025-11-25T06:15:45Z"
}
```

## Pricing

### Basic Video Studio

* **Base:** 30 credits (includes first 5 seconds)
* **Additional:** +6 credits per second after 5s
* **Quality:** 720p, 30fps
* **Max Duration:** 10 seconds

### Reality Lab

* **Base:** 20 credits (includes first 5 seconds)
* **Additional:** +4 credits per second after 5s
* **Quality:** 1080p, 30/60fps
* **Max Duration:** 30 seconds

## Quick Start

<CodeGroup>
  ```javascript Node.js theme={null}
  const response = await fetch('https://api.percify.io/v1/videos/from-image', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      imageId: 'avatar_abc123',
      durationSeconds: 5,
      studioTier: 'basic',
      motionStyle: 'moderate'
    })
  });

  const video = await response.json();
  console.log(`Video ID: ${video.id}, Status: ${video.status}`);
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.post(
      'https://api.percify.io/v1/videos/from-image',
      headers={
          'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
          'Content-Type': 'application/json'
      },
      json={
          'imageId': 'avatar_abc123',
          'durationSeconds': 5,
          'studioTier': 'basic',
          'motionStyle': 'moderate'
      }
  )

  video = response.json()
  print(f"Video ID: {video['id']}, Status: {video['status']}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.percify.io/v1/videos/from-image \
    -H "Authorization: Bearer $PERCIFY_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "imageId": "avatar_abc123",
      "durationSeconds": 5,
      "studioTier": "basic",
      "motionStyle": "moderate"
    }'
  ```
</CodeGroup>

## Processing Times

| Duration | Tier        | Typical Processing |
| -------- | ----------- | ------------------ |
| 3-5s     | Basic       | 20-35 seconds      |
| 6-10s    | Basic       | 40-75 seconds      |
| 3-5s     | Reality Lab | 35-60 seconds      |
| 10-15s   | Reality Lab | 90-150 seconds     |
| 15-30s   | Reality Lab | 3-5 minutes        |

## Motion Styles

| Style      | Description                             | Best For                            |
| ---------- | --------------------------------------- | ----------------------------------- |
| `subtle`   | Gentle breathing, soft blinks           | Professional portraits, calm scenes |
| `moderate` | Natural head movements, expressions     | Conversations, introductions        |
| `dynamic`  | Full range motion, dramatic expressions | Action content, music videos        |

## Video Formats

<Tabs>
  <Tab title="MP4 (H.264)">
    **Best compatibility** - Recommended for most uses

    * Codec: H.264
    * Container: MP4
    * Compatibility: All browsers, mobile devices
    * File size: Medium
  </Tab>

  <Tab title="WebM (VP9)">
    **Smaller file size** - Good for web embedding

    * Codec: VP9
    * Container: WebM
    * Compatibility: Modern browsers
    * File size: Small (30% smaller than MP4)
  </Tab>

  <Tab title="MOV (ProRes)">
    **Highest quality** - For professional editing

    * Codec: ProRes
    * Container: MOV
    * Compatibility: Professional editing software
    * File size: Large
    * Requires: Reality Lab tier
  </Tab>
</Tabs>

## Error Responses

```json theme={null}
{
  "error": {
    "code": "insufficient_credits",
    "message": "Not enough credits for 8-second video. Required: 48, Available: 30",
    "details": {
      "required": 48,
      "available": 30,
      "calculation": {
        "base": 30,
        "additional": 18,
        "total": 48
      }
    }
  }
}
```

Common error codes:

* `invalid_image` - Avatar image not found or inaccessible
* `invalid_duration` - Duration out of allowed range
* `insufficient_credits` - Not enough credits
* `processing_failed` - Video generation failed
* `avatar_not_completed` - Source avatar still processing

## Polling for Completion

```javascript theme={null}
async function waitForVideo(videoId) {
  const maxAttempts = 120; // 10 minutes max
  const pollInterval = 5000; // 5 seconds
  
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://api.percify.io/v1/videos/${videoId}`,
      {
        headers: {
          'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
        }
      }
    );
    
    const video = await response.json();
    
    if (video.status === 'completed') {
      return video;
    } else if (video.status === 'failed') {
      throw new Error(`Video generation failed: ${video.error}`);
    }
    
    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }
  
  throw new Error('Video generation timed out');
}
```

## Adding Audio with Lip-Sync

```javascript theme={null}
// Generate video
const video = await client.videos.fromImage({
  imageId: 'avatar_abc123',
  durationSeconds: 8
});

// Generate audio
const audio = await client.audio.generate({
  text: 'Welcome to Percify! Create amazing AI content.',
  voiceId: 'voice_default'
});

// Add audio with automatic lip-sync
const syncedVideo = await client.videos.addAudio({
  videoId: video.id,
  audioId: audio.id,
  enableLipSync: true
});

console.log(`Video with audio: ${syncedVideo.videoUrl}`);
```

## Webhooks

Subscribe to video completion events:

```json theme={null}
{
  "event": "video.completed",
  "data": {
    "videoId": "video_xyz789",
    "status": "completed",
    "videoUrl": "https://cdn.percify.io/videos/video_xyz789.mp4",
    "durationSeconds": 8,
    "creditCost": 48
  },
  "timestamp": "2025-11-25T06:15:45Z"
}
```

Available events:

* `video.processing` - Video generation started
* `video.completed` - Video ready for download
* `video.failed` - Generation failed

## Best Practices

<AccordionGroup>
  <Accordion icon="coins" title="Optimize Costs">
    * Keep videos under 5 seconds to avoid per-second charges
    * Use Basic tier for testing, Reality Lab for production
    * Batch similar videos for workflow efficiency
    * Reuse successful configurations
  </Accordion>

  <Accordion icon="image" title="Input Quality">
    * Use high-resolution avatars (1024x1024+)
    * Ensure clean, well-lit images
    * Center subject in frame
    * Avoid heavily cropped faces
  </Accordion>

  <Accordion icon="gauge" title="Performance">
    * Generate during off-peak hours for faster processing
    * Use webhooks instead of polling for long videos
    * Download and cache completed videos
    * Compress for web delivery if needed
  </Accordion>
</AccordionGroup>

## Rate Limits

| Tier       | Concurrent Generations | Daily Limit |
| ---------- | ---------------------- | ----------- |
| Free       | 1                      | 10 videos   |
| Pro        | 3                      | 100 videos  |
| Enterprise | 10                     | Unlimited   |

## Next Steps

<CardGroup cols={3}>
  <Card title="Generate Video" icon="plus" href="/api-reference/video-studio/generate">
    Create video from image
  </Card>

  <Card title="Add Audio" icon="volume" href="/api-reference/video-studio/add-audio">
    Sync audio with video
  </Card>

  <Card title="List Videos" icon="list" href="/api-reference/video-studio/list">
    Manage your videos
  </Card>
</CardGroup>
