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

# Video Intro and Outro

> Add video-based intro and outro sequences with automatic duration detection

This guide shows you how to add professional video-based intro and outro sequences to your videos. Video backgrounds automatically detect duration, making it easy to add branded sequences without manual timing configuration.

## What You'll Learn

<CardGroup cols={2}>
  <Card title="Video Intro/Outro" icon="clapperboard">
    Add video-based branded intro and outro sequences
  </Card>

  <Card title="Auto Duration Detection" icon="clock">
    Automatically use video's actual duration without manual configuration
  </Card>

  <Card title="Duration Override" icon="hourglass">
    Optionally override duration to trim or loop videos
  </Card>

  <Card title="Audio Control" icon="volume">
    Control audio playback with mute and loop settings
  </Card>
</CardGroup>

## Before You Begin

Make sure you have:

* A [Pictory API key](https://app.pictory.ai/api-access)
* Node.js or Python installed on your machine
* Intro and outro video URLs (MP4 format recommended)
* Videos are high quality (1920x1080 or higher recommended)

<CodeGroup>
  ```bash npm theme={null}
  npm install axios
  ```

  ```bash pip theme={null}
  pip install requests
  ```
</CodeGroup>

## How Video Intro/Outro Works

When you add video intro/outro sequences:

1. **Intro Scene Definition** - Create first scene with video background pointing to intro URL
2. **Duration Detection** - System automatically detects video duration from file
3. **Duration Override (Optional)** - Add `minimumDuration` to trim or loop to specific length
4. **Main Content Addition** - Include your main content scenes after intro
5. **Outro Scene Definition** - Create last scene with video background pointing to outro URL
6. **Audio Settings Application** - Mute and loop settings are applied to intro/outro videos
7. **Video Rendering** - Final video rendered with intro, content, and outro

<Note>
  For intro and outro videos, omit `minimumDuration` to use the video's actual duration. This ensures your branded sequences play completely without trimming.
</Note>

## Complete Example

<CodeGroup>
  ```javascript Node.js theme={null}
  import axios from "axios";

  const API_BASE_URL = "https://api.pictory.ai/pictoryapis";
  const API_KEY = "YOUR_API_KEY";

  const STORY_TEXT = "AI is poised to significantly impact educators and course creators.";
  const INTRO_VIDEO_URL = "https://pictory-static.pictorycontent.com/PictoryLogoINTRO.mp4";
  const OUTRO_VIDEO_URL = "https://pictory-static.pictorycontent.com/PictoryLogoOUTRO.mp4";

  async function createTextToVideoWithIntroOutro() {
    try {
      console.log("Creating video with intro and outro...");

      const response = await axios.post(
        `${API_BASE_URL}/v2/video/storyboard/render`,
        {
          videoName: "text_to_video_intro_outro",

          scenes: [
            // Intro scene - with optional minimumDuration
            {
              background: {
                type: "video",
                visualUrl: INTRO_VIDEO_URL,
              },
              minimumDuration: 2, // Optional: override video duration
            },

            // Main content
            {
              story: STORY_TEXT,
              createSceneOnNewLine: true,
              createSceneOnEndOfSentence: true,
            },

            // Outro scene - without minimumDuration (auto-detect)
            {
              background: {
                type: "video",
                visualUrl: OUTRO_VIDEO_URL,
              },
              // minimumDuration omitted - uses actual video duration
            },
          ],
        },
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: API_KEY,
          },
        }
      );

      const jobId = response.data.data.jobId;
      console.log("✓ Video with intro and outro render job created!");
      console.log("Job ID:", jobId);

      // Monitor progress
      console.log("\nMonitoring video creation...");
      let jobCompleted = false;
      let jobResult = null;

      while (!jobCompleted) {
        const statusResponse = await axios.get(
          `${API_BASE_URL}/v1/jobs/${jobId}`,
          {
            headers: { Authorization: API_KEY }
          }
        );

        const status = statusResponse.data.data.status;
        console.log("Status:", status);

        if (status === "completed") {
          jobCompleted = true;
          jobResult = statusResponse.data;
          console.log("\n✓ Video with intro and outro is ready!");
          console.log("Video URL:", jobResult.data.videoURL);
        } else if (status === "failed") {
          throw new Error("Video creation failed: " + JSON.stringify(statusResponse.data));
        }

        await new Promise(resolve => setTimeout(resolve, 5000));
      }

      return jobResult;
    } catch (error) {
      console.error("Error:", error.response?.data || error.message);
      throw error;
    }
  }

  createTextToVideoWithIntroOutro();
  ```

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

  API_BASE_URL = 'https://api.pictory.ai/pictoryapis'
  API_KEY = 'YOUR_API_KEY'

  STORY_TEXT = "AI is poised to significantly impact educators and course creators."
  INTRO_VIDEO_URL = "https://pictory-static.pictorycontent.com/PictoryLogoINTRO.mp4"
  OUTRO_VIDEO_URL = "https://pictory-static.pictorycontent.com/PictoryLogoOUTRO.mp4"

  def create_text_to_video_with_intro_outro():
      try:
          print("Creating video with intro and outro...")

          response = requests.post(
              f'{API_BASE_URL}/v2/video/storyboard/render',
              json={
                  'videoName': 'text_to_video_intro_outro',

                  'scenes': [
                      # Intro scene - with optional minimumDuration
                      {
                          'background': {
                              'type': 'video',
                              'visualUrl': INTRO_VIDEO_URL
                          },
                          'minimumDuration': 2  # Optional: override video duration
                      },

                      # Main content
                      {
                          'story': STORY_TEXT,
                          'createSceneOnNewLine': True,
                          'createSceneOnEndOfSentence': True
                      },

                      # Outro scene - without minimumDuration (auto-detect)
                      {
                          'background': {
                              'type': 'video',
                              'visualUrl': OUTRO_VIDEO_URL
                          }
                          # minimumDuration omitted - uses actual video duration
                      }
                  ]
              },
              headers={
                  'Content-Type': 'application/json',
                  'Authorization': API_KEY
              }
          )
          response.raise_for_status()

          job_id = response.json()['data']['jobId']
          print("✓ Video with intro and outro render job created!")
          print(f"Job ID: {job_id}")

          # Monitor progress
          print("\nMonitoring video creation...")
          job_completed = False
          job_result = None

          while not job_completed:
              status_response = requests.get(
                  f'{API_BASE_URL}/v1/jobs/{job_id}',
                  headers={'Authorization': API_KEY}
              )
              status_response.raise_for_status()

              status = status_response.json()['data']['status']
              print(f"Status: {status}")

              if status == 'completed':
                  job_completed = True
                  job_result = status_response.json()
                  print("\n✓ Video with intro and outro is ready!")
                  print(f"Video URL: {job_result['data']['videoURL']}")
              elif status == 'failed':
                  raise Exception(f"Video creation failed: {status_response.json()}")

              time.sleep(5)

          return job_result

      except requests.exceptions.RequestException as error:
          print(f"Error: {error}")
          if hasattr(error, 'response') and error.response is not None:
              print(f"Response: {error.response.text}")
          raise

  if __name__ == '__main__':
      create_text_to_video_with_intro_outro()
  ```
</CodeGroup>

## Understanding the Parameters

### Video Background Parameters

| Parameter                  | Type    | Default | Description                                                                                               |
| -------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `background.type`          | string  | -       | Must be `"video"` for video backgrounds                                                                   |
| `background.visualUrl`     | string  | -       | URL to the video file (MP4 recommended)                                                                   |
| `background.settings.mute` | boolean | `true`  | When `true`, mutes video audio. When `false`, includes video's original audio.                            |
| `background.settings.loop` | boolean | `true`  | When `true`, loops video if shorter than scene. When `false`, video plays once and freezes on last frame. |
| `minimumDuration`          | number  | -       | Optional. Scene duration in seconds. If omitted for videos, uses actual video duration.                   |

### Duration Behavior by Scenario

| Scenario            | minimumDuration    | Behavior                                                                 |
| ------------------- | ------------------ | ------------------------------------------------------------------------ |
| Custom video URL    | Not provided       | Uses actual video duration (auto-detected) ✅ Recommended for intro/outro |
| Custom video URL    | Provided (e.g., 3) | Video is trimmed or looped to match 3 seconds                            |
| Stock library video | Provided           | Video is trimmed or looped to match duration                             |
| Image background    | Required           | Must specify duration (images have no inherent duration)                 |

<Warning>
  **Important:** For intro and outro videos, omit `minimumDuration` to use the video's full duration. This ensures your branded sequences play completely without trimming.
</Warning>

## Intro Duration Explained

### Without minimumDuration (Recommended)

```javascript theme={null}
{
  background: {
    type: "video",
    visualUrl: INTRO_VIDEO_URL
  }
  // minimumDuration omitted - uses actual video duration
}
```

**When to use:**

* Want full branded intro sequence to play
* Video duration is already optimal length
* Don't want to trim or loop the video
* Most common use case for intro/outro

**Result:** Video plays for its full duration automatically.

### With minimumDuration Override

```javascript theme={null}
{
  background: {
    type: "video",
    visualUrl: INTRO_VIDEO_URL
  },
  minimumDuration: 3   // Override to 3 seconds
}
```

**When to use:**

* Need to trim long intro to specific duration
* Want consistent timing across multiple videos
* Need to loop short video to fill time

**Result:** Video is trimmed or looped to match 3 seconds.

**Example:** 5-second intro with `minimumDuration: 3` plays only first 3 seconds.

## Outro Duration Explained

### Without minimumDuration (Recommended)

```javascript theme={null}
{
  background: {
    type: "video",
    visualUrl: OUTRO_VIDEO_URL
  }
  // minimumDuration omitted - uses actual video duration
}
```

**When to use:**

* Want full branded outro sequence to play
* Outro contains important info (CTAs, contact info)
* Video duration is already optimal length
* Most common use case for outro

**Result:** Video plays for its full duration automatically.

### With minimumDuration Override

```javascript theme={null}
{
  background: {
    type: "video",
    visualUrl: OUTRO_VIDEO_URL
  },
  minimumDuration: 8   // Override to 8 seconds
}
```

**When to use:**

* Need to trim long outro to specific duration
* Want consistent timing across multiple videos
* Social media platforms have time constraints

**Result:** Video is trimmed or looped to match 8 seconds.

<Tip>
  **Best Practice:** Keep intro videos short (2-5 seconds) to maintain viewer attention. Outro videos can be longer (5-10 seconds) to include calls-to-action and contact information.
</Tip>

## Duration Best Practices

### Recommended Intro Durations

| Duration    | Use Case                   | Platform            | Example                   |
| ----------- | -------------------------- | ------------------- | ------------------------- |
| 2-3 seconds | Quick logo reveal          | Social media        | Brand logo animation      |
| 3-5 seconds | Branded intro with tagline | Corporate videos    | Company name + slogan     |
| 5-8 seconds | Full branded sequence      | Educational content | Logo + tagline + music    |
| 8+ seconds  | ⚠️ Too long                | Not recommended     | May lose viewer attention |

### Recommended Outro Durations

| Duration      | Use Case     | Platform              | Example                             |
| ------------- | ------------ | --------------------- | ----------------------------------- |
| 5-8 seconds   | Simple CTA   | Social media          | "Subscribe" message with logo       |
| 8-12 seconds  | Detailed CTA | Corporate/Educational | Subscribe + social links + website  |
| 12-15 seconds | Extended CTA | Long-form content     | Full contact info + multiple CTAs   |
| 15+ seconds   | ⚠️ Too long  | Not recommended       | Viewers may leave before completion |

## Video Background with Audio Settings

Control audio playback in your intro and outro videos:

```javascript theme={null}
{
  background: {
    type: "video",
    visualUrl: OUTRO_VIDEO_URL,
    settings: {
      mute: true,        // Mute outro video audio (allows voiceover to be heard)
      loop: false        // Don't loop the video (play once and freeze on last frame)
    }
  }
}
```

**When to use mute:**

* `mute: true` - When you have voiceover narration or want silent branded sequences
* `mute: false` - When intro/outro has important music or sound effects

**When to use loop:**

* `loop: false` - For branded sequences that should play once (recommended for intro/outro)
* `loop: true` - For background ambient videos in main content scenes

## Common Use Cases

### Corporate Video with Branded Intro/Outro

```javascript theme={null}
{
  scenes: [
    // Corporate intro with company branding
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/corporate-intro.mp4",
        settings: {
          mute: false,      // Include intro music
          loop: false       // Play once only
        }
      }
      // minimumDuration omitted - uses actual video duration
    },

    // Main content scenes
    {
      story: "Our quarterly results show significant growth..."
    },

    // Corporate outro with contact information
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/corporate-outro.mp4",
        settings: {
          mute: false,      // Include outro music
          loop: false       // Play once only
        }
      }
    }
  ]
}
```

**Result:** Professional corporate video with branded intro/outro and company music.

### Educational Video with Quick Branding

```javascript theme={null}
{
  scenes: [
    // Short 2-second logo reveal
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/edu-logo-intro.mp4"
      },
      minimumDuration: 2    // Trim to exactly 2 seconds for quick intro
    },

    // Educational content with voiceover
    {
      story: "Today we'll learn about photosynthesis...",
      voiceOver: {
        speaker: "Matthew"
      }
    },

    // Outro with call-to-action
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/edu-cta-outro.mp4"
      }
      // Uses full 8-second outro duration
    }
  ]
}
```

**Result:** Quick branded intro, educational content with voice, full CTA outro.

### Social Media Video with Attention-Grabbing Intro

```javascript theme={null}
{
  scenes: [
    // Eye-catching 3-second intro
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/social-hook-intro.mp4",
        settings: {
          mute: false,      // Include energetic music
          loop: false
        }
      },
      minimumDuration: 3    // Keep it short for social media
    },

    // Main content
    {
      story: "5 tips to boost your productivity..."
    },

    // Call-to-action outro
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/social-cta-outro.mp4"
      },
      minimumDuration: 5    // Short CTA for social media
    }
  ]
}
```

**Result:** Fast-paced social media video with short intro/outro for platform best practices.

### Product Demo with Professional Bookends

```javascript theme={null}
{
  scenes: [
    // Professional intro with product branding
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/product-intro.mp4",
        settings: {
          mute: false,
          loop: false
        }
      }
    },

    // Product demonstration scenes
    {
      story: "Our new software streamlines your workflow..."
    },

    // Outro with purchase information and discount code
    {
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/product-outro-with-discount.mp4",
        settings: {
          mute: false,
          loop: false
        }
      }
      // Uses full outro duration to show all purchase info
    }
  ]
}
```

**Result:** Product demo with professional branded intro and detailed purchase outro.

## Best Practices

<AccordionGroup>
  <Accordion title="Keep Intros Short for Engagement">
    Maintain viewer attention with brief intros:

    * **Social Media**: 2-3 seconds maximum
    * **Corporate Videos**: 3-5 seconds
    * **Educational Content**: 3-4 seconds
    * **Long Intros**: Increase drop-off rates significantly
    * **First Impression**: Viewers decide quickly whether to continue
    * **Test Variations**: A/B test different intro lengths
  </Accordion>

  <Accordion title="Use High-Quality Video Files">
    Ensure professional appearance with quality files:

    * **Resolution**: 1920x1080 minimum for HD quality
    * **Format**: MP4 with H.264 codec for best compatibility
    * **Bitrate**: 5-10 Mbps for optimal quality/size balance
    * **Frame Rate**: 30fps or 60fps for smooth playback
    * **Aspect Ratio**: 16:9 for standard video players
    * **Brand Reflection**: Low-quality intro/outro reflects poorly on brand
  </Accordion>

  <Accordion title="Omit minimumDuration for Full Playback">
    Ensure complete branded sequences:

    * **Branded Sequences**: Omit for full animation playback
    * **Outro with Info**: Ensure all contact info is visible
    * **CTA Videos**: Let complete CTA message play
    * **When to Include**: Only for trimming long videos
    * **Auto-Detection**: Let system use actual video duration
    * **Professional Finish**: Full sequences look more polished
  </Accordion>

  <Accordion title="Consider Audio Carefully">
    Manage audio layers for clear sound:

    * **With Voiceover**: Set `mute: true` on intro/outro
    * **Without Voiceover**: Set `mute: false` to include music
    * **Background Music**: Keep volume lower than voiceover
    * **Audio Conflicts**: Don't mix multiple audio sources
    * **Professional Mix**: Fewer audio layers = cleaner sound
    * **Test Output**: Preview to ensure audio balance
  </Accordion>

  <Accordion title="Test Video Compatibility Before Production">
    Verify videos work correctly:

    * **URL Accessibility**: Video URL must be publicly accessible
    * **Browser Playback**: Video plays in browser without download
    * **Format Check**: Video is in MP4 format
    * **Aspect Ratio**: 16:9 recommended for standard players
    * **Audio Levels**: Audio is appropriate volume
    * **Test Render**: Create test video before bulk production
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Intro/outro video not appearing in final video">
    **Problem:** Video intro or outro does not show in rendered video.

    **Solution:**

    * Verify video URL is publicly accessible (test in browser)
    * Ensure video format is supported (use MP4 with H.264)
    * Check video file is not corrupted or incomplete
    * Verify URL uses HTTPS (not HTTP)
    * Test with known working video URL to isolate issue
    * Review API response for validation errors
  </Accordion>

  <Accordion title="Intro/outro video is cut off or truncated">
    **Problem:** Video is trimmed and does not play fully.

    **Solution:**

    * Remove `minimumDuration` parameter to use full video duration
    * If duration must be specified, ensure it matches or exceeds video length
    * Check video's actual duration (right-click → Properties → Details)
    * Do not guess duration - let system auto-detect
    * Test without `minimumDuration` first
    * Only add `minimumDuration` when intentionally trimming
  </Accordion>

  <Accordion title="Intro/outro video is looping unexpectedly">
    **Problem:** Video repeats instead of playing once.

    **Solution:**

    * Set `settings.loop: false` explicitly in background configuration
    * Default is `loop: true`, must override for one-time playback
    * Remove `minimumDuration` to use actual video duration
    * If `minimumDuration` > video length and `loop: true`, video will loop
    * Verify loop setting is within scene's background configuration
    * Preview output to confirm loop behavior
  </Accordion>

  <Accordion title="Audio from intro/outro conflicts with voiceover">
    **Problem:** Intro/outro audio plays simultaneously with narration.

    **Solution:**

    * Set `settings.mute: true` to silence intro/outro audio
    * Use intro/outro videos without audio tracks
    * Adjust audio levels in source video files before upload
    * Do not mix background video audio + voiceover
    * Plan audio strategy before configuring settings
    * Test audio balance with actual voiceover
  </Accordion>

  <Accordion title="Video Duration Does Not Match Expected Length">
    **Problem:** Scene duration differs from what you expected.

    **Solution:**

    * Check actual video duration using media player
    * Re-encode video with standard settings (30fps, constant frame rate)
    * Use `minimumDuration` to explicitly set desired length
    * Verify video does not have variable frame rate (VFR)
    * Convert to constant frame rate (CFR) for predictable duration
    * Test with explicitly set `minimumDuration`
  </Accordion>

  <Accordion title="Low video quality in final render">
    **Problem:** Intro/outro appears pixelated or low quality.

    **Solution:**

    * Use 1920x1080 minimum resolution for source videos
    * Export videos at high bitrate (5-10 Mbps)
    * Use MP4 format with H.264 codec
    * Avoid re-compressing videos multiple times
    * Ensure aspect ratio matches project settings (16:9)
    * Test with high-quality source video to isolate issue
  </Accordion>
</AccordionGroup>

## Supported Video Formats

Best practices for intro/outro video formats:

| Format | Extension | Recommended | Notes                              |
| ------ | --------- | ----------- | ---------------------------------- |
| MP4    | `.mp4`    | ✅ Yes       | Best compatibility and compression |
| WebM   | `.webm`   | ⚠️ Limited  | May have compatibility issues      |
| MOV    | `.mov`    | ⚠️ Limited  | Larger file sizes, use H.264 codec |
| AVI    | `.avi`    | ❌ No        | Not recommended, poor compression  |

<Tip>
  **Recommended Format:** MP4 with H.264 codec at 1920x1080 resolution for best compatibility and quality across all platforms.
</Tip>

## Advanced Configuration

### Combining Intro/Outro with Other Features

```javascript theme={null}
{
  scenes: [
    // Intro with transition
    {
      background: {
        type: "video",
        visualUrl: INTRO_VIDEO_URL
      },
      transition: {
        type: "fade",
        duration: 0.5
      }
    },

    // Main content with custom background and audio
    {
      story: "Your content here...",
      background: {
        type: "video",
        visualUrl: "https://your-cdn.com/background.mp4",
        settings: {
          mute: true,       // Mute background to hear voiceover
          loop: true        // Loop background video
        }
      },
      voiceOver: {
        speaker: "Matthew"
      }
    },

    // Outro with music and no transition
    {
      background: {
        type: "video",
        visualUrl: OUTRO_VIDEO_URL,
        settings: {
          mute: false,      // Include outro music
          loop: false
        }
      }
    }
  ]
}
```

**Result:** Smooth intro transition, looping background with voiceover, and musical outro.

## Next Steps

Enhance your video intro/outro with these complementary features:

<CardGroup cols={2}>
  <Card title="Background Video Settings" icon="sliders" href="/guides/advanced-features/background-video-settings">
    Control mute and loop behavior for background videos
  </Card>

  <Card title="Scene Transitions" icon="arrow-right-arrow-left" href="/guides/advanced-features/transitions">
    Add smooth transitions between intro, content, and outro scenes
  </Card>

  <Card title="AI Voiceover" icon="microphone" href="/guides/text-to-video/ai-voiceover">
    Add professional voiceover to your videos
  </Card>

  <Card title="Text-to-Video" icon="text" href="/guides/text-to-video/text-to-video-basic">
    Learn how to create main content scenes from text
  </Card>
</CardGroup>

## API Reference

For complete technical details, see:

* [Render Storyboard Video](/api-reference/videos/render-storyboard-video) - Full API specification including intro/outro configuration
* [Get Job Status](/api-reference/jobs/get-video-render-job-by-id) - Monitor job status and get video URLs
