> ## 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.

# Text to Video with Captions

> Create videos with custom captions in different languages, separate from the story text

This guide shows you how to create videos with custom captions that are separate from your story text. Perfect for creating multilingual content where the visuals are selected based on one language while displaying subtitles in another.

## What You'll Learn

<CardGroup cols={2}>
  <Card title="Custom Captions" icon="closed-captioning">
    Add subtitles separate from story text
  </Card>

  <Card title="Multi-Language Support" icon="language">
    Display captions in different languages
  </Card>

  <Card title="Dual Text System" icon="text">
    Story for visuals, captions for display
  </Card>

  <Card title="Translation Ready" icon="globe">
    Perfect for international audiences
  </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
* Your content text and translated captions prepared
* Language codes for your target language

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

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

## How Caption System Works

Pictory's caption system uses a dual-text approach:

1. **Story Text** - The main content used by AI to understand context and select appropriate visuals
2. **Caption Text** - The text displayed as subtitles in your final video
3. **Language Code** - Specifies the caption language for proper formatting
4. **Automatic Sync** - Captions are automatically synchronized with video timing

<Note>
  This separation allows you to create videos in one language (for visual selection) while displaying subtitles in another language, making your content accessible to global audiences.
</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";

  // Story text - used for AI visual selection and content understanding
  const STORY_TEXT = "AI is poised to significantly impact educators and course creators on social media.";

  // Caption text - displayed as subtitles (Spanish translation)
  const CAPTION_TEXT = "La IA está destinada a impactar significativamente a los educadores y creadores de cursos en las redes sociales.";

  async function createTextToVideoWithCaption() {
    try {
      console.log("Creating video with custom captions...");

      const response = await axios.post(
        `${API_BASE_URL}/v2/video/storyboard/render`,
        {
          videoName: "text_to_video_with_caption",
          scenes: [
            {
              story: STORY_TEXT,              // English for visual selection
              caption: CAPTION_TEXT,          // Spanish for subtitles
              captionLanguage: "es",          // Spanish language code
              createSceneOnNewLine: false,    // Required when using captions
              createSceneOnEndOfSentence: false, // Required when using captions
            },
          ],
        },
        {
          headers: {
            "Content-Type": "application/json",
            Authorization: API_KEY,
          },
        }
      );

      const jobId = response.data.data.jobId;
      console.log("✓ Video creation started!");
      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 captions 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;
    }
  }

  createTextToVideoWithCaption();
  ```

  ```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 - used for AI visual selection and content understanding
  STORY_TEXT = "AI is poised to significantly impact educators and course creators on social media."

  # Caption text - displayed as subtitles (Spanish translation)
  CAPTION_TEXT = "La IA está destinada a impactar significativamente a los educadores y creadores de cursos en las redes sociales."

  def create_text_to_video_with_caption():
      try:
          print("Creating video with custom captions...")

          response = requests.post(
              f'{API_BASE_URL}/v2/video/storyboard/render',
              json={
                  'videoName': 'text_to_video_with_caption',
                  'scenes': [
                      {
                          'story': STORY_TEXT,              # English for visual selection
                          'caption': CAPTION_TEXT,          # Spanish for subtitles
                          'captionLanguage': 'es',          # Spanish language code
                          'createSceneOnNewLine': False,    # Required when using captions
                          'createSceneOnEndOfSentence': False  # Required when using captions
                      }
                  ]
              },
              headers={
                  'Content-Type': 'application/json',
                  'Authorization': API_KEY
              }
          )
          response.raise_for_status()

          job_id = response.json()['data']['jobId']
          print("✓ Video creation started!")
          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 captions 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}")
          raise

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

## Caption Configuration Parameters

### Scene Configuration

| Parameter                    | Type    | Required | Description                                                          |
| ---------------------------- | ------- | -------- | -------------------------------------------------------------------- |
| `story`                      | string  | Yes      | The main text used for AI visual selection and content understanding |
| `caption`                    | string  | Yes      | The text that will be displayed as subtitles in the video            |
| `captionLanguage`            | string  | Yes      | ISO 639-1 language code for the caption (e.g., "es" for Spanish)     |
| `createSceneOnNewLine`       | boolean | Yes      | Must be `false` when using captions                                  |
| `createSceneOnEndOfSentence` | boolean | Yes      | Must be `false` when using captions                                  |

<Warning>
  **Important Limitation:** When using custom captions, both `createSceneOnNewLine` and `createSceneOnEndOfSentence` must be set to `false`. This means you need to manually create multiple scenes if you want scene breaks with captions.
</Warning>

## Supported Caption Languages

| Language | Code | Language   | Code |
| -------- | ---- | ---------- | ---- |
| Chinese  | `zh` | Portuguese | `pt` |
| Dutch    | `nl` | Russian    | `ru` |
| English  | `en` | Spanish    | `es` |
| French   | `fr` | Hindi      | `hi` |
| German   | `de` | Japanese   | `ja` |
| Italian  | `it` | Korean     | `ko` |

## Story vs Caption: Understanding the Difference

<AccordionGroup>
  <Accordion title="When to Use Story Text">
    **Story text** is the content the AI uses to:

    * Understand the context and meaning of your video
    * Select appropriate stock visuals and images
    * Determine the overall theme and mood
    * Generate relevant background content

    Use story text in the language that best describes your visual needs, even if your audience speaks a different language.
  </Accordion>

  <Accordion title="When to Use Caption Text">
    **Caption text** is what your viewers will see:

    * Displayed as subtitles throughout the video
    * Can be a translation of the story text
    * Can be simplified or adapted for your audience
    * Should match your target audience's language

    Use caption text in the language your viewers will understand.
  </Accordion>

  <Accordion title="Example Use Case">
    **Scenario:** Creating a video for Spanish-speaking students about AI in education.

    ```javascript theme={null}
    {
      story: "AI is transforming education through personalized learning",
      caption: "La IA está transformando la educación mediante el aprendizaje personalizado",
      captionLanguage: "es"
    }
    ```

    The AI understands the English concept to select educational visuals, but Spanish subtitles appear for your audience.
  </Accordion>
</AccordionGroup>

## Common Use Cases

### Creating Multilingual Marketing Videos

```javascript theme={null}
{
  story: "Our product saves you time and increases productivity",
  caption: "Notre produit vous fait gagner du temps et augmente la productivité",
  captionLanguage: "fr"
}
```

**Result:** Professional marketing video with French subtitles, using English-sourced visuals.

### Educational Content for International Students

```javascript theme={null}
{
  story: "Learn programming fundamentals step by step",
  caption: "プログラミングの基礎を段階的に学ぶ",
  captionLanguage: "ja"
}
```

**Result:** Programming tutorial with Japanese subtitles, maintaining clear technical visuals.

### Accessibility and Localization

```javascript theme={null}
{
  story: "Welcome to our company presentation",
  caption: "Willkommen zu unserer Unternehmenspräsentation",
  captionLanguage: "de"
}
```

**Result:** Corporate presentation accessible to German-speaking audiences.

## Working with Multiple Scenes

Since automatic scene breaks are disabled when using captions, you need to manually create scenes:

```javascript theme={null}
scenes: [
  {
    story: "First concept in English",
    caption: "Primer concepto en español",
    captionLanguage: "es",
    createSceneOnNewLine: false,
    createSceneOnEndOfSentence: false
  },
  {
    story: "Second concept in English",
    caption: "Segundo concepto en español",
    captionLanguage: "es",
    createSceneOnNewLine: false,
    createSceneOnEndOfSentence: false
  }
]
```

## Best Practices

<AccordionGroup>
  <Accordion title="Keep Translations Accurate">
    Ensure your caption text accurately reflects the story text:

    * Use professional translation services when possible
    * Keep the meaning and tone consistent
    * Avoid direct word-for-word translations that may sound unnatural
    * Test with native speakers before production
  </Accordion>

  <Accordion title="Choose the Right Language Code">
    Always use the correct ISO 639-1 language code:

    * Double-check the code matches your caption language
    * Use region-specific codes when necessary (e.g., `zh-CN` vs `zh-TW`)
    * Verify the language is supported (see table above)
  </Accordion>

  <Accordion title="Match Caption Length to Video Timing">
    Keep captions readable within the scene duration:

    * Shorter captions are easier to read
    * Break long sentences into multiple scenes
    * Aim for 1-2 lines of text per scene
    * Test video playback to ensure captions are comfortable to read
  </Accordion>

  <Accordion title="Plan Your Scene Structure">
    Since automatic scene breaks do not work with captions:

    * Plan scene breaks manually before creating the video
    * Group related content into logical scenes
    * Create separate scene objects for each caption segment
    * Consider the visual flow between scenes
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Error: Cannot use captions with automatic scene breaks">
    **Problem:** You set `createSceneOnNewLine` or `createSceneOnEndOfSentence` to `true` with captions.

    **Solution:**
    Set both parameters to `false`:

    ```javascript theme={null}
    {
      caption: "Your caption text",
      captionLanguage: "es",
      createSceneOnNewLine: false,  // Must be false
      createSceneOnEndOfSentence: false  // Must be false
    }
    ```
  </Accordion>

  <Accordion title="Captions appear in wrong language">
    **Problem:** The caption text displays but formatting is incorrect.

    **Solution:**

    * Verify you are using the correct language code (e.g., "es" not "spanish")
    * Check the supported languages table above
    * Ensure the caption text is properly encoded (UTF-8)
  </Accordion>

  <Accordion title="Visuals Do Not Match Caption Content">
    **Problem:** The selected visuals do not seem relevant to your captions.

    **Solution:**
    Remember that visuals are selected based on `story` text, not `caption` text:

    * Make sure your `story` text clearly describes the visuals you want
    * Keep `story` text in a language the AI handles well (English recommended)
    * The `caption` is only for subtitle display, not visual selection
  </Accordion>

  <Accordion title="Caption text too long for scene">
    **Problem:** Captions are cut off or hard to read.

    **Solution:**

    * Break long text into multiple scenes
    * Keep each caption to 1-2 lines (approximately 60-100 characters)
    * Create separate scene objects for longer content:

    ```javascript theme={null}
    scenes: [
      { story: "Part 1", caption: "Parte 1 del contenido", captionLanguage: "es" },
      { story: "Part 2", caption: "Parte 2 del contenido", captionLanguage: "es" }
    ]
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

Enhance your captioned videos with these features:

<CardGroup cols={2}>
  <Card title="AI Voice-Over" icon="microphone" href="/guides/text-to-video/ai-voiceover">
    Add narration in the caption language
  </Card>

  <Card title="Custom Subtitle Styles" icon="palette" href="/guides/branding-customization/custom-subtitle-style">
    Customize caption appearance and formatting
  </Card>

  <Card title="Multi-Level Voice-Over" icon="layer-group" href="/guides/text-to-video/multi-level-voiceover">
    Use different voices for different scenes
  </Card>

  <Card title="Brand Settings" icon="brush" href="/guides/branding-customization/brand-settings">
    Apply consistent branding across videos
  </Card>
</CardGroup>

## API Reference

For complete technical details, see:

<CardGroup cols={2}>
  <Card title="Render Storyboard Video" icon="video" href="/api-reference/videos/render-storyboard-video">
    Direct video rendering with captions
  </Card>

  <Card title="Get Text Styles" icon="font" href="/api-reference/branding/get-text-styles">
    Customize subtitle appearance
  </Card>

  <Card title="Create Storyboard Preview" icon="eye" href="/api-reference/videos/create-storyboard-preview">
    Create preview before rendering
  </Card>

  <Card title="Get Storyboard Preview Job" icon="clock" href="/api-reference/jobs/get-storyboard-preview-job-by-id">
    Monitor storyboard creation progress
  </Card>
</CardGroup>
