Skip to main content
POST
https://api.pictory.ai
/
pictoryapis
/
v2
/
transcription
/
highlights
Video Summary
curl --request POST \
  --url https://api.pictory.ai/pictoryapis/v2/transcription/highlights \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: <content-type>' \
  --data '
{
  "transcript": [
    {}
  ],
  "highlight_duration": 123,
  "duration": 123,
  "language": "<string>",
  "webhook": "<string>"
}
'
{
  "success": true,
  "data": {
    "jobId": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0"
  }
}

Overview

Generate concise video summaries from video transcripts using AI-powered highlight extraction. This endpoint analyzes your transcript and identifies the most important segments to create a summary of your desired duration. What you’ll accomplish:
  • Extract key highlights from video transcripts
  • Generate summaries of specific durations
  • Receive webhook notifications when processing completes
  • Create engaging short-form content from long videos
You need a valid API key to use this endpoint. Get your API key from the API Access page in your Pictory dashboard.

API Endpoint

POST https://api.pictory.ai/pictoryapis/v2/transcription/highlights

Request Parameters

Headers

Authorization
string
required
API key for authentication (starts with pictai_)
Authorization: YOUR_API_KEY
Content-Type
string
required
Must be application/json

Body Parameters

transcript
object[]
required
Array of transcript segments with text and timing information.Each object in the array must contain:
  • text (string, required): The spoken text for this segment
  • start (number, required): Start time in seconds (supports integers and decimals, e.g., 0, 2.5, 10.75)
  • end (number, required): End time in seconds (supports integers and decimals, e.g., 3, 5.2, 15.5)
The “Try it now” form has limited support for array inputs. For testing, we recommend using cURL, Postman, or copying one of the code examples below.
Example format:
[
  {
    "text": "Welcome to our product demo.",
    "start": 0,
    "end": 3.5
  },
  {
    "text": "Today we'll show you the key features.",
    "start": 3.5,
    "end": 7.2
  }
]
highlight_duration
integer
required
Target duration for the video summary in seconds. The AI will select highlights that fit within this duration.Example: 30 for a 30-second summary, 60 for a 1-minute summary
duration
integer
required
Total duration of the source video in seconds. This helps the AI understand the full context when generating highlights.Example: 120 for a 2-minute video, 300 for a 5-minute video
language
string
required
Language code for the transcript content. Must be one of the supported languages.Supported values: en (English), es (Spanish), fr (French), de (German), it (Italian), pt (Portuguese), ja (Japanese), ko (Korean), zh (Chinese), ar (Arabic), hi (Hindi), ru (Russian), and more.Example: en for English, es for Spanish
webhook
string
Optional webhook URL where the summary results will be posted when processing completes. The webhook will receive a POST request with the summary data.Example: https://your-domain.com/api/webhooks/video-summary

Response

success
boolean
Indicates whether the request was successfully queued for processing
data
object
Contains the job information

Response Examples

{
  "success": true,
  "data": {
    "jobId": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0"
  }
}

Code Examples

Replace YOUR_API_KEY with your actual API key that starts with pictai_
curl --request POST \
  --url https://api.pictory.ai/pictoryapis/v2/transcription/highlights \
  --header 'Authorization: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header 'accept: application/json' \
  --data '{
    "transcript": [
      {
        "text": "Welcome to our comprehensive product demonstration.",
        "start": 0,
        "end": 5
      },
      {
        "text": "Today we will explore the key features and benefits.",
        "start": 5,
        "end": 10
      },
      {
        "text": "Our platform helps you create engaging videos quickly.",
        "start": 10,
        "end": 15
      }
    ],
    "highlight_duration": 30,
    "duration": 120,
    "language": "en",
    "webhook": "https://your-domain.com/api/webhooks/summary"
  }' | python -m json.tool

Usage Notes

Async Processing: This endpoint processes summaries asynchronously. You’ll receive a jobId immediately, and the actual summary will be generated in the background.
Webhook Notifications: If you provide a webhook URL, Pictory will POST the completed summary to that URL when processing finishes. This is the recommended way to receive results rather than polling.
Transcript Format: Ensure your transcript segments are in chronological order with accurate start and end times. The AI uses timing information to create seamless highlight clips.
Duration Limits: The highlight_duration should be shorter than your total transcript duration. The AI will select the most important segments that fit within the target duration.

Common Use Cases

1. Generate Short Social Media Clips

Create 30-second highlights for social media from longer videos:
import requests

def create_social_media_summary(full_transcript, api_key):
    """
    Generate a 30-second highlight reel for social media
    """
    url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
    headers = {
        "Authorization": api_key,
        "Content-Type": "application/json"
    }

    payload = {
        "transcript": full_transcript,
        "highlight_duration": 30,  # Perfect for Instagram/TikTok
        "webhook": "https://your-domain.com/webhooks/social-summary"
    }

    response = requests.post(url, json=payload, headers=headers)
    data = response.json()

    if data.get("success"):
        print(f"Social media summary job created: {data['data']['jobId']}")
        return data['data']['jobId']
    else:
        print(f"Failed to create summary: {data.get('message')}")
        return None

# Example usage
transcript = [
    {"text": "In today's video, we're diving deep into AI technology.", "start": 0, "end": 5},
    {"text": "This breakthrough will change everything.", "start": 5, "end": 9},
    {"text": "Let me show you the three key features.", "start": 9, "end": 13},
    # ... more segments
]

job_id = create_social_media_summary(transcript, "YOUR_API_KEY")

2. Batch Process Multiple Videos

Process multiple video transcripts in parallel:
async function batchProcessSummaries(videos, apiKey, targetDuration) {
  const results = [];

  for (const video of videos) {
    try {
      const response = await fetch(
        'https://api.pictory.ai/pictoryapis/v2/transcription/highlights',
        {
          method: 'POST',
          headers: {
            'Authorization': `${apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            transcript: video.transcript,
            highlight_duration: targetDuration,
            webhook: `https://your-domain.com/webhooks/${video.id}`
          })
        }
      );

      const data = await response.json();

      if (data.success) {
        results.push({
          videoId: video.id,
          jobId: data.data.jobId,
          status: 'submitted'
        });
        console.log(`✓ ${video.title}: Job ${data.data.jobId}`);
      } else {
        results.push({
          videoId: video.id,
          status: 'failed',
          error: data.message
        });
        console.log(`✗ ${video.title}: Failed`);
      }
    } catch (error) {
      console.error(`Error processing ${video.title}:`, error.message);
      results.push({
        videoId: video.id,
        status: 'error',
        error: error.message
      });
    }

    // Add small delay to avoid rate limiting
    await new Promise(resolve => setTimeout(resolve, 100));
  }

  console.log(`\nProcessed ${results.length} videos`);
  console.log(`Successful: ${results.filter(r => r.status === 'submitted').length}`);
  console.log(`Failed: ${results.filter(r => r.status !== 'submitted').length}`);

  return results;
}

// Example usage
const videos = [
  {
    id: 'video-1',
    title: 'Product Demo',
    transcript: [/* transcript data */]
  },
  {
    id: 'video-2',
    title: 'Tutorial',
    transcript: [/* transcript data */]
  }
];

const results = await batchProcessSummaries(videos, 'YOUR_API_KEY', 60);

3. Handle Webhook Results

Set up a webhook endpoint to receive completed summaries:
from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/webhooks/video-summary', methods=['POST'])
def handle_summary_webhook():
    """
    Receive and process completed video summary
    """
    try:
        summary_data = request.json

        # Log the received data
        print(f"Received summary for job: {summary_data.get('jobId')}")

        # Process the summary
        # (The exact structure depends on what Pictory sends)
        job_id = summary_data.get('jobId')
        highlights = summary_data.get('highlights', [])

        # Save to database, trigger next step, etc.
        save_summary_to_database(job_id, highlights)

        # Optionally trigger video creation with the highlights
        create_video_from_highlights(highlights)

        return jsonify({"status": "success"}), 200

    except Exception as e:
        print(f"Error processing webhook: {str(e)}")
        return jsonify({"status": "error", "message": str(e)}), 500

def save_summary_to_database(job_id, highlights):
    # Your database logic here
    pass

def create_video_from_highlights(highlights):
    # Create a video project using the highlights
    pass

if __name__ == '__main__':
    app.run(port=3000)

4. Create Multiple Duration Variants

Generate summaries of different lengths from the same transcript:
def create_multi_duration_summaries(transcript, api_key):
    """
    Create summaries of different durations for various platforms
    """
    durations = {
        'tiktok': 15,      # TikTok/Reels
        'instagram': 30,   # Instagram feed
        'twitter': 45,     # Twitter/X
        'youtube': 60      # YouTube Shorts
    }

    jobs = {}

    for platform, duration in durations.items():
        response = requests.post(
            "https://api.pictory.ai/pictoryapis/v2/transcription/highlights",
            json={
                "transcript": transcript,
                "highlight_duration": duration,
                "webhook": f"https://your-domain.com/webhooks/{platform}"
            },
            headers={
                "Authorization": api_key,
                "Content-Type": "application/json"
            }
        )

        data = response.json()

        if data.get("success"):
            jobs[platform] = {
                'job_id': data['data']['jobId'],
                'duration': duration,
                'status': 'processing'
            }
            print(f"✓ {platform.title()}: {duration}s summary (Job: {data['data']['jobId']})")
        else:
            print(f"✗ {platform.title()}: Failed")

    return jobs

# Example usage
full_transcript = [
    {"text": "Welcome to today's product update.", "start": 0, "end": 3},
    {"text": "We've added three exciting new features.", "start": 3, "end": 7},
    # ... more transcript segments
]

summary_jobs = create_multi_duration_summaries(full_transcript, "YOUR_API_KEY")
print(f"\nCreated {len(summary_jobs)} summary jobs")

5. Validate Transcript Before Submission

Ensure transcript quality before generating summaries:
function validateTranscript(transcript) {
  const errors = [];

  if (!Array.isArray(transcript) || transcript.length === 0) {
    errors.push('Transcript must be a non-empty array');
    return { valid: false, errors };
  }

  // Check each segment
  transcript.forEach((segment, index) => {
    if (!segment.text || segment.text.trim() === '') {
      errors.push(`Segment ${index}: Missing or empty text`);
    }

    if (typeof segment.start !== 'number' || segment.start < 0) {
      errors.push(`Segment ${index}: Invalid start time`);
    }

    if (typeof segment.end !== 'number' || segment.end <= segment.start) {
      errors.push(`Segment ${index}: End time must be greater than start time`);
    }
  });

  // Check chronological order
  for (let i = 1; i < transcript.length; i++) {
    if (transcript[i].start < transcript[i-1].end) {
      errors.push(`Segment ${i}: Overlaps with previous segment`);
    }
  }

  // Calculate total duration
  const totalDuration = transcript[transcript.length - 1].end - transcript[0].start;

  return {
    valid: errors.length === 0,
    errors,
    totalDuration,
    segmentCount: transcript.length
  };
}

async function generateSummaryWithValidation(transcript, duration, apiKey) {
  // Validate transcript
  const validation = validateTranscript(transcript);

  if (!validation.valid) {
    console.error('Transcript validation failed:');
    validation.errors.forEach(error => console.error(`  - ${error}`));
    return null;
  }

  console.log(`Transcript valid:`);
  console.log(`  - ${validation.segmentCount} segments`);
  console.log(`  - ${validation.totalDuration.toFixed(1)}s total duration`);

  // Check if requested duration is reasonable
  if (duration > validation.totalDuration) {
    console.warn(`Warning: Requested duration (${duration}s) exceeds transcript duration (${validation.totalDuration.toFixed(1)}s)`);
  }

  // Generate summary
  const response = await fetch(
    'https://api.pictory.ai/pictoryapis/v2/transcription/highlights',
    {
      method: 'POST',
      headers: {
        'Authorization': `${apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        transcript,
        highlight_duration: duration
      })
    }
  );

  const data = await response.json();

  if (data.success) {
    console.log(`✓ Summary job created: ${data.data.jobId}`);
    return data.data.jobId;
  } else {
    console.error(`✗ Failed to create summary: ${data.message}`);
    return null;
  }
}

// Example usage
const transcript = [
  { text: "Introduction to the topic.", start: 0, end: 5 },
  { text: "Main content section one.", start: 5, end: 15 },
  { text: "Main content section two.", start: 15, end: 25 }
];

const jobId = await generateSummaryWithValidation(transcript, 15, 'YOUR_API_KEY');

Best Practices

Transcript Quality

  1. Accurate Timing: Ensure start and end times are precise for smooth highlight transitions
  2. Complete Sentences: Break transcript at natural sentence boundaries for better context
  3. No Overlaps: Segments should not overlap in time
  4. Chronological Order: Segments must be ordered by time

Duration Selection

  1. Platform Optimization:
    • TikTok/Reels: 15-30 seconds
    • Instagram: 30-60 seconds
    • YouTube Shorts: 60 seconds
    • LinkedIn: 30-90 seconds
  2. Content Type:
    • Product demos: 60-90 seconds
    • Testimonials: 30-45 seconds
    • Educational: 45-60 seconds

Webhook Implementation

  1. Return 200 OK Quickly: Process the webhook payload asynchronously to avoid timeouts
  2. Implement Retry Logic: Webhooks may be retried if they fail
  3. Validate Signatures: Implement webhook signature validation for security
  4. Log All Webhooks: Keep logs for debugging and audit trails