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

# Custom Subtitle Styling

> Create videos with fully customized inline subtitle styles without saving presets

This guide shows you how to create videos with completely custom subtitle styles defined directly in your API request. Instead of using saved presets, you can specify all styling properties inline for maximum flexibility.

## What You'll Learn

<CardGroup cols={2}>
  <Card title="Inline Styles" icon="font">
    Define custom styles directly in API requests
  </Card>

  <Card title="Full Control" icon="palette">
    Customize fonts, colors, positions, and effects
  </Card>

  <Card title="No Presets Needed" icon="wand-magic-sparkles">
    Style without saving configurations
  </Card>

  <Card title="Animation Options" icon="sparkles">
    Add entry and exit animations
  </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
* Basic understanding of colors (RGBA format)
* Familiarity with subtitle positioning

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

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

## How Custom Subtitle Styling Works

When you define subtitle styles inline:

1. **Style Definition** - You specify all subtitle properties in your request
2. **Property Application** - Font, colors, position, and effects are configured
3. **Animation Setup** - Entry and exit animations are applied (optional)
4. **No Saving Required** - Style exists only for this video (not saved to account)
5. **Video Rendering** - Subtitles render with your exact specifications

<Note>
  Inline subtitle styles give you complete control without creating saved presets. This is perfect for one-time custom styling or testing different subtitle configurations.
</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 SAMPLE_TEXT = "AI is poised to significantly impact educators and course creators on social media.";

  async function createVideoWithCustomSubtitleStyle() {
    try {
      console.log("Creating video with custom subtitle style...");

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

          // Custom inline subtitle style
          subtitleStyle: {
            // Font settings
            fontFamily: "Poppins",
            fontSize: 48,

            // Colors (RGBA format)
            color: "rgba(255, 255, 255, 1)",              // White text
            backgroundColor: "rgba(0, 0, 0, 0.7)",        // Semi-transparent black background
            keywordColor: "rgba(255, 215, 0, 1)",         // Gold for keywords
            shadowColor: "rgba(0, 0, 0, 0.8)",            // Dark shadow
            shadowWidth: "2%",

            // Position and layout
            position: "bottom-center",
            alignment: "center",
            paragraphWidth: "80%",

            // Text styling
            decorations: ["bold"],
            case: "capitalize",

            // Animations
            animations: [
              {
                name: "fade",
                type: "entry",
                speed: "medium",
              },
              {
                name: "fade",
                type: "exit",
                speed: "fast",
              },
            ],
          },

          scenes: [
            {
              story: SAMPLE_TEXT,
              createSceneOnNewLine: false,
              createSceneOnEndOfSentence: false,
            },
          ],
        },
        {
          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 custom subtitle style 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;
    }
  }

  createVideoWithCustomSubtitleStyle();
  ```

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

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

  SAMPLE_TEXT = "AI is poised to significantly impact educators and course creators on social media."

  def create_video_with_custom_subtitle_style():
      try:
          print("Creating video with custom subtitle style...")

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

                  # Custom inline subtitle style
                  'subtitleStyle': {
                      # Font settings
                      'fontFamily': 'Poppins',
                      'fontSize': 48,

                      # Colors (RGBA format)
                      'color': 'rgba(255, 255, 255, 1)',              # White text
                      'backgroundColor': 'rgba(0, 0, 0, 0.7)',        # Semi-transparent black background
                      'keywordColor': 'rgba(255, 215, 0, 1)',         # Gold for keywords
                      'shadowColor': 'rgba(0, 0, 0, 0.8)',            # Dark shadow
                      'shadowWidth': '2%',

                      # Position and layout
                      'position': 'bottom-center',
                      'alignment': 'center',
                      'paragraphWidth': '80%',

                      # Text styling
                      'decorations': ['bold'],
                      'case': 'capitalize',

                      # Animations
                      'animations': [
                          {'name': 'fade', 'type': 'entry', 'speed': 'medium'},
                          {'name': 'fade', 'type': 'exit', 'speed': 'fast'}
                      ]
                  },

                  'scenes': [
                      {
                          'story': SAMPLE_TEXT,
                          'createSceneOnNewLine': False,
                          'createSceneOnEndOfSentence': False
                      }
                  ]
              },
              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 custom subtitle style 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_video_with_custom_subtitle_style()
  ```
</CodeGroup>

## Subtitle Style Parameters

### Font Properties

| Property     | Type   | Description                | Example                                                            |
| ------------ | ------ | -------------------------- | ------------------------------------------------------------------ |
| `fontFamily` | string | Font name                  | "Poppins", "Arial", "Roboto"                                       |
| `fontUrl`    | string | Custom font URL (optional) | "[https://example.com/font.woff2](https://example.com/font.woff2)" |
| `fontSize`   | number | Font size in pixels        | 48, 36, 60                                                         |

### Color Properties

All colors use **RGBA format**: `rgba(R, G, B, A)` where R/G/B are 0-255 and A is 0-1

| Property          | Description                    | Example                                       |
| ----------------- | ------------------------------ | --------------------------------------------- |
| `color`           | Main text color                | `rgba(255, 255, 255, 1)` (white)              |
| `backgroundColor` | Background behind text         | `rgba(0, 0, 0, 0.7)` (semi-transparent black) |
| `keywordColor`    | Color for highlighted keywords | `rgba(255, 215, 0, 1)` (gold)                 |
| `shadowColor`     | Text shadow color              | `rgba(0, 0, 0, 0.8)` (dark gray)              |

### Position and Layout

| Property         | Type   | Options/Description                                                                                                                   |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `position`       | string | `top-left`, `top-center`, `top-right`, `center-left`, `center-center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right` |
| `alignment`      | string | `left`, `center`, `right`                                                                                                             |
| `paragraphWidth` | string | Percentage of screen width (e.g., "80%", "100%")                                                                                      |
| `shadowWidth`    | string | Shadow size as percentage (e.g., "2%", "5%")                                                                                          |

### Text Styling

| Property      | Type   | Options                                                                              |
| ------------- | ------ | ------------------------------------------------------------------------------------ |
| `decorations` | array  | `["bold"]`, `["underline"]`, `["italics"]`, `["linethrough"]` (can combine multiple) |
| `case`        | string | `uppercase`, `lowercase`, `capitalize`, `smallcapitalize`                            |

## Animation Options

You can add up to 2 animations per subtitle style (one entry, one exit).

### Available Animations

| Animation Name | Type       | Description                         |
| -------------- | ---------- | ----------------------------------- |
| `none`         | Entry/Exit | No animation                        |
| `fade`         | Entry/Exit | Gradual fade in or out              |
| `drift`        | Entry/Exit | Drift motion with fade              |
| `wipe`         | Entry/Exit | Wipe across screen                  |
| `text reveal`  | Entry      | Text reveals character by character |
| `elastic`      | Entry      | Elastic bounce effect               |
| `typewriter`   | Entry      | Typewriter effect                   |
| `blur`         | Entry/Exit | Blur transition                     |
| `bulletin`     | Entry      | Bulletin board style                |

### Animation Configuration

| Property    | Options | Description                                                |
| ----------- | ------- | ---------------------------------------------------------- |
| `name`      | string  | Animation name from table above                            |
| `type`      | string  | `entry` (appearing) or `exit` (disappearing)               |
| `speed`     | string  | `slow`, `medium`, `fast`, `custom`                         |
| `direction` | string  | `up`, `down`, `left`, `right` (for directional animations) |

## RGBA Color Format

```
rgba(R, G, B, A)
```

| Component     | Range | Description                                |
| ------------- | ----- | ------------------------------------------ |
| **R** (Red)   | 0-255 | Red intensity                              |
| **G** (Green) | 0-255 | Green intensity                            |
| **B** (Blue)  | 0-255 | Blue intensity                             |
| **A** (Alpha) | 0-1   | Transparency (0 = transparent, 1 = opaque) |

### Common Colors

| Color                  | RGBA Value               |
| ---------------------- | ------------------------ |
| White                  | `rgba(255, 255, 255, 1)` |
| Black                  | `rgba(0, 0, 0, 1)`       |
| Semi-transparent black | `rgba(0, 0, 0, 0.7)`     |
| Gold                   | `rgba(255, 215, 0, 1)`   |
| Red                    | `rgba(255, 0, 0, 1)`     |
| Blue                   | `rgba(0, 120, 255, 1)`   |
| Green                  | `rgba(34, 197, 94, 1)`   |

<Tip>
  Use online RGBA color pickers to easily create color values for your custom styles.
</Tip>

## Common Use Cases

### Professional Business Subtitles

```javascript theme={null}
{
  subtitleStyle: {
    fontFamily: "Roboto",
    fontSize: 42,
    color: "rgba(255, 255, 255, 1)",
    backgroundColor: "rgba(0, 0, 0, 0.8)",
    position: "bottom-center",
    decorations: ["bold"]
  }
}
```

**Result:** Clean, professional subtitles with strong readability.

### Social Media Style

```javascript theme={null}
{
  subtitleStyle: {
    fontFamily: "Poppins",
    fontSize: 56,
    color: "rgba(255, 255, 255, 1)",
    keywordColor: "rgba(255, 215, 0, 1)",
    backgroundColor: "rgba(0, 0, 0, 0)",
    shadowColor: "rgba(0, 0, 0, 1)",
    shadowWidth: "3%",
    position: "center-center",
    case: "uppercase",
    decorations: ["bold"]
  }
}
```

**Result:** Eye-catching subtitles perfect for TikTok, Instagram Reels.

### Educational Content

```javascript theme={null}
{
  subtitleStyle: {
    fontFamily: "Arial",
    fontSize: 40,
    color: "rgba(0, 0, 0, 1)",
    backgroundColor: "rgba(255, 255, 255, 0.9)",
    position: "bottom-center",
    alignment: "center",
    paragraphWidth: "90%",
    decorations: []
  }
}
```

**Result:** High-contrast, easy-to-read subtitles for learning materials.

### Animated Dynamic Subtitles

```javascript theme={null}
{
  subtitleStyle: {
    fontFamily: "Montserrat",
    fontSize: 48,
    color: "rgba(255, 255, 255, 1)",
    backgroundColor: "rgba(0, 0, 0, 0.6)",
    position: "bottom-center",
    animations: [
      { name: "typewriter", type: "entry", speed: "fast" },
      { name: "fade", type: "exit", speed: "medium" }
    ]
  }
}
```

**Result:** Engaging subtitles with typewriter entry and fade exit.

## Best Practices

<AccordionGroup>
  <Accordion title="Choose Readable Font Combinations">
    Select fonts and sizes for optimal readability:

    * **Font Size:** 36-56 pixels for most videos (1920x1080)
    * **Font Families:** Use web-safe fonts like Poppins, Roboto, Arial, Montserrat
    * **Font Weight:** Bold is generally more readable on video
    * **Custom Fonts:** Test custom fonts thoroughly before production
    * **Consistency:** Use same font family across all scenes for cohesion
  </Accordion>

  <Accordion title="Use High-Contrast Colors">
    Ensure subtitles are easily visible:

    * **Light Text on Dark:** White text on semi-transparent black (most common)
    * **Dark Text on Light:** Black text on white background (high brightness videos)
    * **Shadow for Depth:** Add shadows to text without backgrounds
    * **Keyword Colors:** Use contrasting colors for keyword highlights
    * **Test Backgrounds:** Verify readability on various scene backgrounds
  </Accordion>

  <Accordion title="Position Strategically">
    Place subtitles where they are visible but not intrusive:

    * **Bottom-Center:** Standard position, does not cover main content
    * **Avoid Top:** Unless content is primarily at bottom
    * **Width:** 70-90% paragraph width prevents text from reaching edges
    * **Alignment:** Center alignment works best for most content
    * **Scene-Specific:** Consider different positions for different scene types
  </Accordion>

  <Accordion title="Apply Animations Sparingly">
    Use animations to enhance, not distract:

    * **Entry Animation:** Fade or drift work well for most content
    * **Exit Animation:** Faster exit (fade) than entry feels natural
    * **Speed:** Medium or fast speeds prevent slow pacing
    * **Avoid Overuse:** Too many animations can be distracting
    * **Match Content:** Playful animations for casual, simple for professional
  </Accordion>

  <Accordion title="Test Before Production">
    Always preview your custom styles:

    * **Create Test Video:** Use short sample text first
    * **Multiple Scenes:** Test with different background colors
    * **Device Testing:** View on mobile and desktop
    * **Readability Check:** Ensure text is clear at different video sizes
    * **Adjust Iteratively:** Refine style based on test results
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Subtitles are hard to read">
    **Problem:** Text is not clearly visible in the video.

    **Solution:**

    * Increase background opacity (higher alpha value in backgroundColor)
    * Use higher contrast between text color and background
    * Add or increase shadow (shadowColor and shadowWidth)
    * Increase font size (try 48-56 pixels)
    * Use bold decoration for thicker, more visible text
  </Accordion>

  <Accordion title="Colors Do Not Look as Expected">
    **Problem:** Subtitle colors appear different than intended.

    **Solution:**

    * Verify RGBA format is correct (rgba(R, G, B, A))
    * Check RGB values are 0-255, alpha is 0-1
    * Ensure proper comma separation in RGBA values
    * Test colors with online RGBA picker before using
    * Remember alpha channel affects transparency
    * Check for typos in color values
  </Accordion>

  <Accordion title="Font Does Not Appear or Looks Wrong">
    **Problem:** Specified font is not being used.

    **Solution:**

    * Use standard web fonts (Poppins, Roboto, Arial, Montserrat)
    * Check font name spelling exactly
    * If using custom font URL, verify URL is accessible
    * Ensure fontUrl points directly to font file (.woff2, .woff, .ttf)
    * Test with standard font first, then add custom
  </Accordion>

  <Accordion title="Animations not working">
    **Problem:** Entry or exit animations do not appear.

    **Solution:**

    * Verify animation name is from available options
    * Check type is either "entry" or "exit"
    * Ensure speed is "slow", "medium", "fast", or "custom"
    * Maximum 2 animations allowed (one entry, one exit)
    * Check animations array syntax is correct
    * Try simple "fade" animation first to test
  </Accordion>

  <Accordion title="Subtitles positioned incorrectly">
    **Problem:** Subtitles appear in wrong location on screen.

    **Solution:**

    * Verify position value matches available options
    * Position names are case-sensitive and hyphenated
    * Check for typos: "bottom-center" not "bottom center"
    * Ensure paragraphWidth does not push text off-screen
    * Test with "bottom-center" first as baseline
    * Review final video to verify placement
  </Accordion>
</AccordionGroup>

## Next Steps

Explore more subtitle and branding options:

<CardGroup cols={2}>
  <Card title="Subtitle Styles" icon="closed-captioning" href="/guides/branding-customization/subtitle-styles">
    Use saved subtitle style presets
  </Card>

  <Card title="Highlight Keywords" icon="highlighter" href="/guides/branding-customization/highlight-keywords">
    Automatically emphasize important words
  </Card>

  <Card title="Brand Settings" icon="palette" href="/guides/branding-customization/brand-settings">
    Apply complete brand presets to videos
  </Card>

  <Card title="Custom Captions" icon="closed-captioning" href="/guides/text-to-video/text-to-video-captions">
    Add multilingual captions to videos
  </Card>
</CardGroup>

## API Reference

For complete technical details, see:

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