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

# Scenes

> Create multi-scene videos combining avatars, video clips, and AI-generated transitions

<Note>
  **Try it out!** Use the API playground on the right to test the Scenes endpoint directly.
</Note>

## Overview

Scenes allows you to create complex, multi-scene videos by combining different content types in a storyboard format. Each scene can be one of four types:

* **Avatar**: A talking avatar scene with script and voice
* **Video**: A video or image clip with optional voiceover
* **Picture in Picture**: An avatar overlaid on a video/image background
* **Start/End Frame**: AI-generated video transition between two images

This format is ideal for:

* Long-form content with multiple segments
* Tutorials with avatar explanations and demo clips
* Marketing videos with varied visual styles
* Storytelling with scene transitions
* Educational content mixing talking heads and visuals

<Info>
  Scenes automatically handles transitions between different scene types and maintains consistent captions throughout the video.
</Info>

***

## Endpoint

```
POST /v1/project/create/scenes
```

***

## Required Fields

<ParamField body="scenes" type="array" required>
  Array of scene objects (1-50 scenes). Each scene defines a segment of your video.

  <Expandable title="Scene Object">
    <ParamField body="type" type="string" required>
      The type of scene:

      * `avatar`: Talking avatar scene
      * `video`: Video/image clip scene
      * `picture_in_picture`: Avatar overlaid on video/image
      * `start_end_frame`: AI-generated video from start/end images
    </ParamField>

    <ParamField body="script" type="string">
      The script for the avatar to speak (max 5,000 characters). Required for `avatar` and `picture_in_picture` types.
    </ParamField>

    <ParamField body="avatarId" type="string">
      Avatar ID from `/v1/avatar/list`. Required for `avatar` and `picture_in_picture` types.
    </ParamField>

    <ParamField body="voiceId" type="string">
      Voice ID from `/v1/voice/list`. Required for `avatar` and `picture_in_picture` types.
    </ParamField>

    <ParamField body="mediaId" type="string">
      Media ID for video/image content. Required for `video` and `picture_in_picture` types.
    </ParamField>

    <ParamField body="startFrameMediaId" type="string">
      Media ID for the starting frame image. Required for `start_end_frame` type.
    </ParamField>

    <ParamField body="endFrameMediaId" type="string">
      Media ID for the ending frame image. Required for `start_end_frame` type.
    </ParamField>

    <ParamField body="frameModel" type="string">
      AI model for generating the transition video:

      * `kling_2_5`: Kling 2.5 model
      * `veo_3_1`: Google Veo 3.1 model
    </ParamField>

    <ParamField body="framePrompt" type="string">
      Prompt describing the transition between start and end frames (max 2,000 characters).
    </ParamField>

    <ParamField body="frameDuration" type="number">
      Duration of the AI-generated transition video in seconds. Must be between 1 and 300. Default: 5.
    </ParamField>
  </Expandable>
</ParamField>

***

## Optional Fields

<ParamField body="name" type="string">
  Video name (max 100 characters). If not provided, a name will be auto-generated from the scene scripts.
</ParamField>

<ParamField body="musicId" type="string">
  Background music ID from `/v1/music/list`.
</ParamField>

<ParamField body="caption" type="object">
  Caption settings for the video

  <Expandable title="Caption Object">
    <ParamField body="preset" type="string" default="classic">
      Caption preset style. Available presets: `default`, `beast`, `umi`, `tiktok`, `wrap1`, `wrap2`, `ariel`, `hooked`, `classic`, `active`, `bubble`, `glass`, `comic`, `glow`, `pastel`, `neon`, `retroTV`, `red`, `marker`, `modern`, `blue`, `vivid`.
    </ParamField>

    <ParamField body="alignment" type="string" default="bottom">
      Caption position on the video: `top`, `middle`, or `bottom`
    </ParamField>

    <ParamField body="disabled" type="boolean" default="true">
      Set to `false` to show captions on the video
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="aspectRatio" type="string" default="ratio_9_16">
  Video aspect ratio:

  * `ratio_9_16`: Vertical (TikTok, Reels, Shorts) - **Recommended**
  * `ratio_16_9`: Horizontal (YouTube)
  * `ratio_1_1`: Square (Instagram)
</ParamField>

<ParamField body="language" type="string" default="en">
  Language code for the video (2 characters). Example: `en`, `es`
</ParamField>

<ParamField body="webhook" type="string">
  HTTPS URL to receive completion notification (max 500 characters). **Highly recommended** for production use.
</ParamField>

<ParamField body="metadata" type="object">
  Custom metadata object (max 5KB). Store any additional data you need to associate with this video.

  ```json theme={null}
  {
    "courseId": "course_123",
    "lessonNumber": 5
  }
  ```
</ParamField>

***

## Scene Types

### Avatar Scene

A talking avatar presents content with synchronized lip movements.

```json theme={null}
{
  "type": "avatar",
  "script": "Welcome to our tutorial! Today we'll learn about...",
  "avatarId": "professional_avatar_id",
  "voiceId": "confident_voice_id"
}
```

**Required fields**: `script`, `avatarId`, `voiceId`

### Video Scene

A video or image clip plays, optionally with voiceover.

```json theme={null}
{
  "type": "video",
  "mediaId": "demo_video_id",
  "script": "As you can see in this demo...",
  "voiceId": "professional_voice_id"
}
```

**Required fields**: `mediaId`

### Picture in Picture Scene

An avatar appears overlaid on a video/image background.

```json theme={null}
{
  "type": "picture_in_picture",
  "script": "As you can see in this demo...",
  "avatarId": "presenter_avatar_id",
  "voiceId": "professional_voice_id",
  "mediaId": "background_video_id"
}
```

**Required fields**: `script`, `avatarId`, `voiceId`, `mediaId`

### Start/End Frame Scene

AI generates a video transition between two images.

```json theme={null}
{
  "type": "start_end_frame",
  "startFrameMediaId": "start_image_id",
  "endFrameMediaId": "end_image_id",
  "frameModel": "veo_3_1",
  "framePrompt": "Smooth camera zoom out revealing the full scene",
  "frameDuration": 5
}
```

**Required fields**: `startFrameMediaId`, `endFrameMediaId`, `framePrompt`

***

## Request Examples

## Basic Multi-Scene Video

```javascript theme={null}
const response = await fetch('https://api.hooked.so/v1/project/create/scenes', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.HOOKED_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    scenes: [
      {
        type: 'avatar',
        script: 'Welcome to our product demo! Let me show you how it works.',
        avatarId: 'professional_avatar_id',
        voiceId: 'confident_voice_id'
      },
      {
        type: 'video',
        mediaId: 'product_demo_video_id'
      },
      {
        type: 'avatar',
        script: 'As you can see, it is incredibly easy to use. Try it today!',
        avatarId: 'professional_avatar_id',
        voiceId: 'confident_voice_id'
      }
    ]
  })
});

const data = await response.json();
console.log('Project ID:', data.projectId);
```

## Tutorial with Picture in Picture

```javascript theme={null}
const createTutorial = async () => {
  const response = await fetch('https://api.hooked.so/v1/project/create/scenes', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.HOOKED_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'Getting Started Tutorial',
      scenes: [
        {
          type: 'avatar',
          script: 'Hi there! In this tutorial, I will walk you through the setup process step by step.',
          avatarId: 'friendly_avatar_id',
          voiceId: 'warm_voice_id'
        },
        {
          type: 'picture_in_picture',
          script: 'First, click on the settings icon in the top right corner.',
          avatarId: 'friendly_avatar_id',
          voiceId: 'warm_voice_id',
          mediaId: 'settings_screenshot_id'
        },
        {
          type: 'picture_in_picture',
          script: 'Then, navigate to the integrations tab and enable the API access.',
          avatarId: 'friendly_avatar_id',
          voiceId: 'warm_voice_id',
          mediaId: 'integrations_screenshot_id'
        },
        {
          type: 'avatar',
          script: 'And that is it! You are all set up and ready to go.',
          avatarId: 'friendly_avatar_id',
          voiceId: 'warm_voice_id'
        }
      ],
      musicId: 'upbeat_background_id',
      aspectRatio: 'ratio_16_9',
      caption: {
        preset: 'modern',
        alignment: 'bottom',
        disabled: false
      },
      language: 'en',
      webhook: 'https://yoursite.com/webhook',
      metadata: {
        tutorialId: 'getting-started',
        version: '1.0'
      }
    })
  });

  return await response.json();
};
```

## AI Transition Video

```javascript theme={null}
const createTransitionVideo = async () => {
  const response = await fetch('https://api.hooked.so/v1/project/create/scenes', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.HOOKED_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      scenes: [
        {
          type: 'avatar',
          script: 'Watch this amazing transformation!',
          avatarId: 'energetic_avatar_id',
          voiceId: 'excited_voice_id'
        },
        {
          type: 'start_end_frame',
          startFrameMediaId: 'before_image_id',
          endFrameMediaId: 'after_image_id',
          frameModel: 'veo_3_1',
          framePrompt: 'Smooth morphing transition from the before state to the after state with elegant camera movement'
        },
        {
          type: 'avatar',
          script: 'Incredible, right? This is the power of our solution.',
          avatarId: 'energetic_avatar_id',
          voiceId: 'excited_voice_id'
        }
      ],
      aspectRatio: 'ratio_9_16'
    })
  });

  return await response.json();
};
```

## Response

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "projectId": "proj_scenes_abc123xyz",
    "message": "Scenes project successfully created"
  }
  ```

  ```json Error Response - No Scenes theme={null}
  {
    "success": false,
    "message": "At least one scene is required"
  }
  ```

  ```json Error Response - Invalid Scene theme={null}
  {
    "success": false,
    "message": "scenes.0.script: Script is required for avatar scenes"
  }
  ```

  ```json Error Response - Not Enough Credits theme={null}
  {
    "success": false,
    "message": "Not enough credits for scenes video. Estimated: 50, Available: 25"
  }
  ```
</ResponseExample>

***

## Webhook Notification

When your video is ready, we'll POST to your webhook URL:

```json Webhook Payload theme={null}
{
  "status": "COMPLETED",
  "data": {
    "videoId": "vid_scenes_abc123xyz",
    "status": "COMPLETED",
    "url": "https://cdn.hooked.so/videos/abc123xyz.mp4",
    "shareUrl": "https://cdn.hooked.so/shared/abc123xyz.mp4",
    "metadata": {
      "projectId": "proj_scenes_abc123xyz",
      "tutorialId": "getting-started"
    }
  },
  "message": "Video completed"
}
```

<Note>
  Your webhook endpoint must return a `200` status code. We'll retry up to 3 times if the request fails.
</Note>

***

## Scene Type Requirements

| Scene Type           | Required Fields                                       | Optional Fields               |
| -------------------- | ----------------------------------------------------- | ----------------------------- |
| `avatar`             | `script`, `avatarId`, `voiceId`                       |                               |
| `video`              | `mediaId`                                             | `script`, `voiceId`,          |
| `picture_in_picture` | `script`, `avatarId`, `voiceId`, `mediaId`            |                               |
| `start_end_frame`    | `startFrameMediaId`, `endFrameMediaId`, `framePrompt` | `frameModel`, `frameDuration` |

***

## AI Models for Start/End Frame

| Model       | Description     | Best For                               |
| ----------- | --------------- | -------------------------------------- |
| `kling_2_5` | Kling 2.5 model | Fast generation, general transitions   |
| `veo_3_1`   | Google Veo 3.1  | High quality, complex camera movements |

***

## Caption Presets

Available caption presets for the `caption.preset` field:

| Preset    | Description                                              |
| --------- | -------------------------------------------------------- |
| `default` | Default caption style with bold text and shadow effects  |
| `beast`   | Bold uppercase style with Komika font                    |
| `umi`     | Yellow glowing text style                                |
| `tiktok`  | Viral & trendy style, perfect for social media           |
| `wrap1`   | Wrapped style with red background highlight              |
| `wrap2`   | Wrapped style with blue background highlight (uppercase) |
| `ariel`   | Bold uppercase style with purple highlight               |
| `hooked`  | Brand style with purple background                       |
| `classic` | Clean, simple captions with black background             |
| `active`  | Green background with bold text                          |
| `bubble`  | White background bubble style                            |
| `glass`   | Glassmorphic transparency effect                         |
| `comic`   | Comic Sans font with colorful style                      |
| `glow`    | Pink and orange glow effects                             |
| `pastel`  | Soft pastel pink background                              |
| `neon`    | Green neon glow effect                                   |
| `retroTV` | Retro TV style with cyan glow                            |
| `red`     | Red glow effect with white text                          |
| `marker`  | Yellow marker/highlighter style                          |
| `modern`  | Contemporary white background style                      |
| `blue`    | Blue background style                                    |
| `vivid`   | Vibrant pink background with uppercase text              |

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Plan Your Storyboard" icon="list">
    Outline your scenes before creating. Each scene should serve a clear purpose in the narrative.
  </Card>

  <Card title="Consistent Avatar" icon="user">
    Use the same avatar across scenes for continuity, unless intentionally switching perspectives.
  </Card>

  <Card title="Vary Scene Types" icon="shuffle">
    Mix avatar, video, and PiP scenes to keep viewers engaged and add visual variety.
  </Card>

  <Card title="Smooth Transitions" icon="arrows-left-right">
    Write scripts that flow naturally between scenes. End one scene leading into the next.
  </Card>

  <Card title="Optimize Duration" icon="clock">
    Keep individual scenes focused. Split long content into multiple shorter scenes.
  </Card>

  <Card title="Use Start/End Frames" icon="wand-magic-sparkles">
    Leverage AI transitions for impressive visual effects between static images.
  </Card>
</CardGroup>

***

## Error Handling

| Error                                     | Description                    | Solution                                      |
| ----------------------------------------- | ------------------------------ | --------------------------------------------- |
| `At least one scene is required`          | Empty scenes array             | Add at least one scene to the array           |
| `Cannot have more than 50 scenes`         | Too many scenes                | Reduce the number of scenes to 50 or fewer    |
| `Script is required for avatar scenes`    | Missing script in avatar scene | Add the `script` field                        |
| `Avatar ID is required for avatar scenes` | Missing avatarId               | Add a valid `avatarId` from `/v1/avatar/list` |
| `Voice ID is required for avatar scenes`  | Missing voiceId                | Add a valid `voiceId` from `/v1/voice/list`   |
| `Media ID is required for video scenes`   | Missing mediaId in video scene | Add a valid `mediaId`                         |
| `Not enough credits`                      | Insufficient credits           | Top up your account credits                   |

***

## Credits

Scenes videos use a credit model based on:

* **Base credits**: Fixed cost per video
* **Avatar scene credits**: Charged based on script duration (similar to UGC Video)
* **Video scenes**: Included in base credits (no additional charge)
* **Start/End Frame**: Additional credits for AI generation

***

## Next Steps

<CardGroup cols={2}>
  <Card title="List Avatars" icon="user" href="/api-reference/avatar/list">
    Browse available avatars for your scenes
  </Card>

  <Card title="List Voices" icon="microphone" href="/api-reference/voice/list">
    Find the perfect voice for your avatars
  </Card>

  <Card title="List Music" icon="music" href="/api-reference/music/list">
    Add background music to your video
  </Card>

  <Card title="Webhooks Guide" icon="webhook" href="/guides/webhooks">
    Learn how to handle webhook notifications
  </Card>
</CardGroup>


## OpenAPI

````yaml POST /v1/project/create/scenes
openapi: 3.0.0
info:
  title: Hooked API
  version: 1.0.0
  description: AI Video Generation API
servers:
  - url: https://api.hooked.so
security:
  - ApiKeyAuth: []
paths:
  /v1/project/create/scenes:
    post:
      tags:
        - Videos
      summary: Create Scenes Video
      description: >-
        Create multi-scene videos combining avatars, video clips, and
        AI-generated transitions
      operationId: createScenes
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - scenes
              properties:
                name:
                  type: string
                  description: Video name (max 100 characters)
                  maxLength: 100
                scenes:
                  type: array
                  description: Array of scene objects (1-50 scenes)
                  minItems: 1
                  maxItems: 50
                  items:
                    type: object
                    required:
                      - type
                    properties:
                      type:
                        type: string
                        enum:
                          - avatar
                          - video
                          - picture_in_picture
                          - start_end_frame
                        description: Type of scene
                      script:
                        type: string
                        description: Script for avatar to speak (max 5000 characters)
                        maxLength: 5000
                      avatarId:
                        type: string
                        description: Avatar ID from /v1/avatar/list
                        maxLength: 30
                      voiceId:
                        type: string
                        description: Voice ID from /v1/voice/list
                        maxLength: 30
                      mediaId:
                        type: string
                        description: Media ID for video/image content
                        maxLength: 30
                      startFrameMediaId:
                        type: string
                        description: >-
                          Media ID for starting frame image (start_end_frame
                          type)
                        maxLength: 30
                      endFrameMediaId:
                        type: string
                        description: Media ID for ending frame image (start_end_frame type)
                        maxLength: 30
                      frameModel:
                        type: string
                        enum:
                          - kling_2_5
                          - veo_3_1
                          - seedance_1_5
                        description: AI model for generating transition video
                      framePrompt:
                        type: string
                        description: >-
                          Prompt for AI transition generation (max 2000
                          characters)
                        maxLength: 2000
                      frameDuration:
                        type: number
                        description: Duration of the transition video in seconds
                        minimum: 1
                        maximum: 300
                        default: 5
                musicId:
                  type: string
                  description: Background music ID from /v1/music/list
                  maxLength: 30
                aspectRatio:
                  type: string
                  enum:
                    - ratio_9_16
                    - ratio_16_9
                    - ratio_1_1
                  description: Video aspect ratio
                  default: ratio_9_16
                caption:
                  type: object
                  properties:
                    preset:
                      type: string
                      enum:
                        - default
                        - beast
                        - umi
                        - tiktok
                        - wrap1
                        - wrap2
                        - ariel
                        - hooked
                        - classic
                        - active
                        - bubble
                        - glass
                        - comic
                        - glow
                        - pastel
                        - neon
                        - retroTV
                        - red
                        - marker
                        - modern
                        - blue
                        - vivid
                      description: Caption preset style
                      default: classic
                    alignment:
                      type: string
                      enum:
                        - top
                        - middle
                        - bottom
                      description: Caption position on video
                      default: bottom
                    disabled:
                      type: boolean
                      description: Set to true to hide captions
                      default: true
                addStickers:
                  type: boolean
                  description: Add AI-generated stickers to enhance video engagement
                  default: false
                language:
                  type: string
                  description: Language code (2 characters)
                  minLength: 2
                  maxLength: 2
                  default: en
                webhook:
                  type: string
                  description: HTTPS URL to receive completion notification
                  maxLength: 500
                metadata:
                  type: object
                  description: Custom metadata object (max 5KB)
            example:
              name: Product Tutorial
              scenes:
                - type: avatar
                  script: Welcome to our product demo! Let me show you how it works.
                  avatarId: professional_avatar_id
                  voiceId: confident_voice_id
                - type: video
                  mediaId: product_demo_video_id
                - type: start_end_frame
                  startFrameMediaId: start_image_id
                  endFrameMediaId: end_image_id
                  frameModel: veo_3_1
                  framePrompt: Smooth camera zoom out revealing the full scene
                  frameDuration: 5
                - type: picture_in_picture
                  script: >-
                    As you can see here, the interface is intuitive and easy to
                    use.
                  avatarId: professional_avatar_id
                  voiceId: confident_voice_id
                  mediaId: screenshot_id
                - type: avatar
                  script: Try it today and see the difference!
                  avatarId: professional_avatar_id
                  voiceId: confident_voice_id
              musicId: upbeat_background_id
              aspectRatio: ratio_9_16
              caption:
                preset: modern
                alignment: bottom
                disabled: false
              addStickers: false
              audio:
                speed: 1
                stability: 0.5
                similarityBoost: 0.75
                style: 0
                useSpeakerBoost: true
              language: en
              webhook: https://yoursite.com/webhook
              metadata:
                tutorialId: getting-started
                version: '1.0'
      responses:
        '200':
          description: Scenes project created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  projectId:
                    type: string
                  message:
                    type: string
              example:
                success: true
                projectId: proj_scenes_abc123xyz
                message: Scenes project successfully created
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
              example:
                success: false
                message: At least one scene is required
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
              example:
                success: false
                message: Invalid API key
      security:
        - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````