Text to Video with Subtitle Style Name/ID

This example demonstrates how to create a video using saved subtitle styles from your Pictory account. You can apply pre-configured subtitle styles at both video level and scene level using either the style name or style ID.

Overview

This example covers:

  • Getting an access token
  • Using saved subtitle styles with subtitleStyleName or subtitleStyleId
  • Applying styles at video level (all scenes)
  • Overriding video-level styles at scene level
  • Understanding the difference between styleName and styleId
  • Monitoring job status and retrieving the final video

Node.js Example

Prerequisites

npm install axios

Complete Code

import axios from "axios";

const API_BASE_URL = "https://api.pictory.ai/pictoryapis";
const CLIENT_ID = "YOUR_CLIENT_ID";
const CLIENT_SECRET = "YOUR_CLIENT_SECRET";

const STORY_TEXT_1 = "AI is poised to significantly impact educators and course creators on social media.";
const STORY_TEXT_2 =
  "By automating tasks like content generation, visual design, and video editing, AI will save time and enhance consistency.";

async function createTextToVideoWithSubtitleStyleNameId() {
  try {
    // Step 1: Get Access Token
    console.log("Step 1: Getting access token...");
    const tokenResponse = await axios.post(
      `${API_BASE_URL}/v1/oauth2/token`,
      {
        client_id: CLIENT_ID,
        client_secret: CLIENT_SECRET,
      },
      {
        headers: {
          "Content-Type": "application/json",
        },
      }
    );

    const accessToken = tokenResponse.data.access_token;
    console.log("Access token obtained successfully");
    console.log("Token expires in:", tokenResponse.data.expires_in, "seconds\n");

    // Step 2: Create Video with Subtitle Style
    console.log("Step 2: Creating video with subtitle styles...");
    const storyboardResponse = await axios.post(
      `${API_BASE_URL}/v2/video/storyboard/render`,
      {
        videoName: "text_to_video_subtitle_style",
        // Video-level subtitle style (applies to all scenes by default)
        subtitleStyleName: "{YOUR_STYLE_NAME}", // Use either subtitleStyleName OR subtitleStyleId
        // subtitleStyleId: "{YOUR_STYLE_ID}",  // Alternative: use styleId instead
        scenes: [
          {
            story: STORY_TEXT_1,
            createSceneOnNewLine: false,
            createSceneOnEndOfSentence: false,
            // This scene uses the video-level subtitle style
          },
          {
            story: STORY_TEXT_2,
            createSceneOnNewLine: false,
            createSceneOnEndOfSentence: false,
            // Scene-level override with different style
            subtitleStyleName: "{DIFFERENT_STYLE_NAME}", // Overrides video-level style for this scene
            // subtitleStyleId: "{DIFFERENT_STYLE_ID}"    // Alternative: use styleId instead
          },
        ],
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: accessToken,
        },
      }
    );

    const renderJobId = storyboardResponse.data.data.jobId;
    console.log("Video with subtitle styles render job created");
    console.log("Job ID:", renderJobId, "\n");

    // Step 3: Monitor Job Status
    console.log("Step 3: Monitoring job status...");
    let jobCompleted = false;
    let jobResult = null;

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

      const status = jobStatusResponse.data.data.status;
      console.log("Current status:", status);

      if (status === "completed") {
        jobCompleted = true;
        jobResult = jobStatusResponse.data;
        console.log("\nVideo with subtitle styles created successfully!");
        console.log("Video URL:", jobResult.data.videoURL);
      } else if (status === "failed") {
        throw new Error("Job failed: " + JSON.stringify(jobStatusResponse.data));
      } else {
        // Wait 5 seconds before checking again
        await new Promise(resolve => setTimeout(resolve, 5000));
      }
    }

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

// Run the function
createTextToVideoWithSubtitleStyleNameId();

Python Example

Prerequisites

pip install requests

Complete Code

import requests
import time
import json

API_BASE_URL = 'https://api.pictory.ai/pictoryapis'
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'

STORY_TEXT_1 = "AI is poised to significantly impact educators and course creators on social media."
STORY_TEXT_2 = "By automating tasks like content generation, visual design, and video editing, AI will save time and enhance consistency."

def create_text_to_video_with_subtitle_style_name_id():
    try:
        # Step 1: Get Access Token
        print('Step 1: Getting access token...')
        token_response = requests.post(
            f'{API_BASE_URL}/v1/oauth2/token',
            json={
                'client_id': CLIENT_ID,
                'client_secret': CLIENT_SECRET
            },
            headers={
                'Content-Type': 'application/json'
            }
        )
        token_response.raise_for_status()

        access_token = token_response.json()['access_token']
        print('Access token obtained successfully')
        print(f"Token expires in: {token_response.json()['expires_in']} seconds\n")

        # Step 2: Create Video with Subtitle Style
        print('Step 2: Creating video with subtitle styles...')
        storyboard_response = requests.post(
            f'{API_BASE_URL}/v2/video/storyboard/render',
            json={
                'videoName': 'text_to_video_subtitle_style',
                # Video-level subtitle style (applies to all scenes by default)
                'subtitleStyleName': '{YOUR_STYLE_NAME}',  # Use either subtitleStyleName OR subtitleStyleId
                # 'subtitleStyleId': '{YOUR_STYLE_ID}',  # Alternative: use styleId instead
                'scenes': [
                    {
                        'story': STORY_TEXT_1,
                        'createSceneOnNewLine': False,
                        'createSceneOnEndOfSentence': False
                        # This scene uses the video-level subtitle style
                    },
                    {
                        'story': STORY_TEXT_2,
                        'createSceneOnNewLine': False,
                        'createSceneOnEndOfSentence': False,
                        # Scene-level override with different style
                        'subtitleStyleName': '{DIFFERENT_STYLE_NAME}'  # Overrides video-level style for this scene
                        # 'subtitleStyleId': '{DIFFERENT_STYLE_ID}'    # Alternative: use styleId instead
                    }
                ]
            },
            headers={
                'Content-Type': 'application/json',
                'Authorization': access_token
            }
        )
        storyboard_response.raise_for_status()

        render_job_id = storyboard_response.json()['data']['jobId']
        print('Video with subtitle styles render job created')
        print(f'Job ID: {render_job_id}\n')

        # Step 3: Monitor Job Status
        print('Step 3: Monitoring job status...')
        job_completed = False
        job_result = None

        while not job_completed:
            job_status_response = requests.get(
                f'{API_BASE_URL}/v1/jobs/{render_job_id}',
                headers={
                    'Authorization': access_token
                }
            )
            job_status_response.raise_for_status()

            status = job_status_response.json()['data']['status']
            print(f'Current status: {status}')

            if status == 'completed':
                job_completed = True
                job_result = job_status_response.json()
                print('\nVideo with subtitle styles created successfully!')
                print(f"Video URL: {job_result['data']['videoURL']}")
            elif status == 'failed':
                raise Exception(f"Job failed: {json.dumps(job_status_response.json())}")
            else:
                # Wait 5 seconds before checking again
                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

# Run the function
if __name__ == '__main__':
    create_text_to_video_with_subtitle_style_name_id()

Key Parameters

Video-Level Subtitle Style

  • subtitleStyleName: The name of a saved subtitle style (use this OR subtitleStyleId, not both)
  • subtitleStyleId: The ID of a saved subtitle style (use this OR subtitleStyleName, not both)

Scene-Level Subtitle Style

  • scenes[].subtitleStyleName: Override video-level style for a specific scene
  • scenes[].subtitleStyleId: Override video-level style using style ID

Important Rules

  1. Mutual Exclusivity at Video Level: Cannot provide both subtitleStyleId and subtitleStyleName at video level
  2. Mutual Exclusivity at Scene Level: Cannot provide both subtitleStyleId and subtitleStyleName at scene level
  3. Scene Override: Scene-level styles take precedence over video-level styles
  4. Account Ownership: The style must exist in your Pictory account

Style Name vs Style ID

Use Style Name When:

  • You know the human-readable name of the style
  • Easier to remember and maintain in code
  • More readable in configuration

Use Style ID When:

  • You need to ensure exact style reference
  • Working with programmatically generated styles
  • Style names might change but IDs remain constant

Creating Subtitle Styles

Before using this API, create subtitle styles in your Pictory account:

  1. Log in to your Pictory account
  2. Navigate to Subtitle Styles or Settings
  3. Create and save custom subtitle styles
  4. Note the style name or ID for API use

What Subtitle Styles Include

Subtitle styles typically include:

  • Font family and size
  • Text color and background color
  • Text position and alignment
  • Text decorations (bold, italic, underline)
  • Animations and effects
  • Shadow and outline settings

Use Cases

  • Maintain consistent branding across videos
  • Apply company-specific subtitle formatting
  • Create different styles for different video types
  • Quickly switch between predefined looks
  • Ensure compliance with brand guidelines

Multi-Scene Style Example

scenes: [
  {
    story: "Introduction text",
    subtitleStyleName: "Bold Intro Style",
  },
  {
    story: "Main content",
    // Uses video-level style
  },
  {
    story: "Call to action",
    subtitleStyleName: "Highlighted CTA Style",
  },
];

Response

The API returns a job ID for monitoring the video creation progress. Once completed, you'll receive a video URL with subtitles styled according to your saved styles.

Notes

  • Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with your actual API credentials
  • Replace {YOUR_STYLE_NAME} and {DIFFERENT_STYLE_NAME} with actual style names from your account
  • Placeholders with curly braces {} indicate user-specific data
  • The style must be created and saved in your account before use
  • If a style is not found, the API will return an error