Generate Highlights from Custom Transcript
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,
"webhook": "<string>",
"language": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
payload = {
"transcript": [{}],
"highlight_duration": 123,
"duration": 123,
"webhook": "<string>",
"language": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
transcript: [{}],
highlight_duration: 123,
duration: 123,
webhook: '<string>',
language: '<string>'
})
};
fetch('https://api.pictory.ai/pictoryapis/v2/transcription/highlights', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pictory.ai/pictoryapis/v2/transcription/highlights",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'transcript' => [
[
]
],
'highlight_duration' => 123,
'duration' => 123,
'webhook' => '<string>',
'language' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
payload := strings.NewReader("{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pictory.ai/pictoryapis/v2/transcription/highlights")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v2/transcription/highlights")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"name": "transcript",
"errors": "transcript is required"
}
]
}
{
"message": "Unauthorized"
}
Video Summary and Transcription
Generate Highlights from Custom Transcript
Generate AI-powered video highlights from an edited or custom transcript
POST
/
pictoryapis
/
v2
/
transcription
/
highlights
Generate Highlights from Custom Transcript
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,
"webhook": "<string>",
"language": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
payload = {
"transcript": [{}],
"highlight_duration": 123,
"duration": 123,
"webhook": "<string>",
"language": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
transcript: [{}],
highlight_duration: 123,
duration: 123,
webhook: '<string>',
language: '<string>'
})
};
fetch('https://api.pictory.ai/pictoryapis/v2/transcription/highlights', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pictory.ai/pictoryapis/v2/transcription/highlights",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'transcript' => [
[
]
],
'highlight_duration' => 123,
'duration' => 123,
'webhook' => '<string>',
'language' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
payload := strings.NewReader("{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pictory.ai/pictoryapis/v2/transcription/highlights")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v2/transcription/highlights")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"transcript\": [\n {}\n ],\n \"highlight_duration\": 123,\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"language\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"name": "transcript",
"errors": "transcript is required"
}
]
}
{
"message": "Unauthorized"
}
Overview
Generate concise video highlights from your own custom or edited transcript. This endpoint is useful when you have manually edited the transcription output or want to provide your own transcript data directly. The AI analyzes your transcript and identifies the most important segments to create a summary of your desired duration. What you will accomplish:- Generate highlights from manually edited transcripts
- Use custom transcript data that does not come from the transcription API
- Create summaries from transcripts you have corrected or enhanced
- Apply highlights to videos with pre-existing transcript data
You need a valid API key to use this endpoint. Get your API key from the API Access page in your Pictory dashboard.
If you have not edited the transcript and want highlights from a transcription job, use the Generate Highlights from Transcription Job endpoint instead - it is simpler and requires less data.
Request Headers
string
required
API key for authentication
Authorization: YOUR_API_KEY
string
required
Must be set to
application/jsonContent-Type: application/json
Body Parameters
object[]
required
Array of sentence-level transcript segments with word-level timing information.Each sentence object must contain:
The “Try it now” form cannot properly handle nested array inputs. Please use cURL, Postman, or one of the code examples below to test this endpoint.
uid(string, required): Unique identifier for the sentencespeakerId(number, required): Speaker identifier (e.g.,1)words(array, required): Array of word objects
uid(string, required): Unique identifier for the wordword(string, required): The word textstart_time(number, required): Start time in seconds (supports decimals)end_time(number, required): End time in seconds (supports decimals)speakerId(number, required): Speaker identifiersentence_index(number, required): Index of the sentence
[
{
"uid": "sentence-1",
"speakerId": 1,
"words": [
{
"uid": "word-1",
"word": "Important",
"start_time": 0.0,
"end_time": 0.5,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-2",
"word": "content",
"start_time": 0.5,
"end_time": 1.0,
"speakerId": 1,
"sentence_index": 0
}
]
}
]
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 summaryinteger
default:"0"
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 videostring
Webhook URL where the summary results will be posted when processing completes.Example:
https://your-domain.com/api/webhooks/video-summarystring
default:"en"
Language code for the transcript content.Supported values:
en (English), es (Spanish), fr (French), de (German), it (Italian), pt (Portuguese), and more.Example: en for English, es for SpanishResponse
boolean
Indicates whether the request was successfully queued for processing
object
Contains the job information
Show data properties
Show data properties
string
Unique identifier for the highlights generation job. Use this ID to track the job status via the Get Job by ID API.
Response Examples
{
"success": true,
"data": {
"jobId": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"name": "transcript",
"errors": "transcript is required"
}
]
}
{
"message": "Unauthorized"
}
Job Status Response (via Get Job API)
While the highlights job is processing:{
"job_id": "bbd75639-c3cb-4add-bf7b-e4e39cffb3b0",
"success": true,
"data": {
"status": "in-progress"
}
}
Code Examples
Replace
YOUR_API_KEY with your actual API key that starts with pictai_curl --location 'https://api.pictory.ai/pictoryapis/v2/transcription/highlights' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"transcript": [
{
"uid": "sentence-1",
"speakerId": 1,
"words": [
{
"uid": "word-1-1",
"word": "Click",
"start_time": 0.64,
"end_time": 0.96,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-1-2",
"word": "the",
"start_time": 0.96,
"end_time": 1.12,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-1-3",
"word": "play",
"start_time": 1.12,
"end_time": 1.36,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-1-4",
"word": "button.",
"start_time": 1.36,
"end_time": 1.68,
"speakerId": 1,
"sentence_index": 0
}
]
},
{
"uid": "sentence-2",
"speakerId": 1,
"words": [
{
"uid": "word-2-1",
"word": "This",
"start_time": 2.0,
"end_time": 2.3,
"speakerId": 1,
"sentence_index": 1
},
{
"uid": "word-2-2",
"word": "is",
"start_time": 2.3,
"end_time": 2.5,
"speakerId": 1,
"sentence_index": 1
},
{
"uid": "word-2-3",
"word": "important",
"start_time": 2.5,
"end_time": 3.0,
"speakerId": 1,
"sentence_index": 1
},
{
"uid": "word-2-4",
"word": "content.",
"start_time": 3.0,
"end_time": 3.5,
"speakerId": 1,
"sentence_index": 1
}
]
}
],
"highlight_duration": 10,
"duration": 120,
"language": "en"
}'
import requests
url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
headers = {
"Authorization": "YOUR_API_KEY",
"Content-Type": "application/json"
}
# Example edited transcript
transcript = [
{
"uid": "sentence-1",
"speakerId": 1,
"words": [
{
"uid": "word-1-1",
"word": "Click",
"start_time": 0.64,
"end_time": 0.96,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-1-2",
"word": "the",
"start_time": 0.96,
"end_time": 1.12,
"speakerId": 1,
"sentence_index": 0
},
{
"uid": "word-1-3",
"word": "play",
"start_time": 1.12,
"end_time": 1.36,
"speakerId": 1,
"sentence_index": 0
}
]
}
]
payload = {
"transcript": transcript,
"highlight_duration": 10,
"duration": 120,
"language": "en",
"webhook": "https://your-domain.com/api/webhooks/highlights"
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get("success"):
print(f"Highlights Job ID: {data['data']['jobId']}")
print("Highlights generation started successfully")
else:
print(f"Error: {data.get('message', 'Unknown error')}")
const response = await fetch(
'https://api.pictory.ai/pictoryapis/v2/transcription/highlights',
{
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
transcript: [
{
uid: 'sentence-1',
speakerId: 1,
words: [
{
uid: 'word-1-1',
word: 'Click',
start_time: 0.64,
end_time: 0.96,
speakerId: 1,
sentence_index: 0
},
{
uid: 'word-1-2',
word: 'the',
start_time: 0.96,
end_time: 1.12,
speakerId: 1,
sentence_index: 0
}
]
}
],
highlight_duration: 10,
duration: 120,
language: 'en',
webhook: 'https://your-domain.com/api/webhooks/highlights'
})
}
);
const data = await response.json();
if (data.success) {
console.log(`Highlights Job ID: ${data.data.jobId}`);
console.log('Highlights generation started successfully');
} else {
console.log(`Error: ${data.message || 'Unknown error'}`);
}
<?php
$url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights";
$transcript = [
[
'uid' => 'sentence-1',
'speakerId' => 1,
'words' => [
[
'uid' => 'word-1-1',
'word' => 'Click',
'start_time' => 0.64,
'end_time' => 0.96,
'speakerId' => 1,
'sentence_index' => 0
],
[
'uid' => 'word-1-2',
'word' => 'the',
'start_time' => 0.96,
'end_time' => 1.12,
'speakerId' => 1,
'sentence_index' => 0
]
]
]
];
$payload = [
'transcript' => $transcript,
'highlight_duration' => 10,
'duration' => 120,
'language' => 'en',
'webhook' => 'https://your-domain.com/api/webhooks/highlights'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode === 200 && $data['success']) {
echo "Highlights Job ID: " . $data['data']['jobId'] . "\n";
echo "Highlights generation started successfully\n";
} else {
echo "Error: " . ($data['message'] ?? 'Unknown error') . "\n";
}
?>
Common Use Cases
1. Generate Highlights from Edited Transcript
After manually correcting or enhancing a transcript:import requests
def generate_highlights_from_edited_transcript(edited_transcript, duration, api_key):
"""
Generate highlights after editing the transcript for accuracy
"""
url = "https://api.pictory.ai/pictoryapis/v2/transcription/highlights"
headers = {
"Authorization": api_key,
"Content-Type": "application/json"
}
payload = {
"transcript": edited_transcript,
"highlight_duration": 30,
"duration": duration,
"language": "en",
"webhook": "https://your-domain.com/webhooks/highlights"
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get("success"):
print(f"Highlights job created: {data['data']['jobId']}")
return data['data']['jobId']
else:
print(f"Failed: {data.get('message')}")
return None
# Use after editing transcript
edited_transcript = load_edited_transcript_from_database()
job_id = generate_highlights_from_edited_transcript(edited_transcript, 120, "YOUR_API_KEY")
2. Use Custom Transcript from External Source
When you have transcript data from a third-party service:async function generateHighlightsFromExternalTranscript(externalTranscript) {
// Convert external transcript format to Pictory format
const pictoryTranscript = externalTranscript.sentences.map((sentence, index) => ({
uid: `sentence-${index + 1}`,
speakerId: sentence.speaker_id || 1,
words: sentence.words.map((word, wordIndex) => ({
uid: `word-${index + 1}-${wordIndex + 1}`,
word: word.text,
start_time: word.start,
end_time: word.end,
speakerId: sentence.speaker_id || 1,
sentence_index: index
}))
}));
const response = await fetch(
'https://api.pictory.ai/pictoryapis/v2/transcription/highlights',
{
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
transcript: pictoryTranscript,
highlight_duration: 60,
duration: externalTranscript.total_duration,
language: 'en'
})
}
);
const data = await response.json();
return data.success ? data.data.jobId : null;
}
Usage Notes
Async Processing: This endpoint processes highlights asynchronously. You will receive a
jobId immediately, and the actual highlights will be generated in the background.Webhook Notifications: Provide a webhook URL to receive the completed highlights automatically. This is the recommended approach instead of 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.Best Practices
Transcript Quality
- Accurate Timing: Ensure start and end times are precise for smooth highlight transitions
- Complete Sentences: Structure transcript at natural sentence boundaries for better context
- No Overlaps: Word timings should not overlap
- Chronological Order: Sentences and words must be ordered by time
- Unique IDs: Use unique
uidvalues for all sentences and words
Duration Selection
-
Platform Optimization:
- TikTok/Reels: 15-30 seconds
- Instagram: 30-60 seconds
- YouTube Shorts: 60 seconds
- LinkedIn: 30-90 seconds
-
Content Type:
- Product demos: 60-90 seconds
- Testimonials: 30-45 seconds
- Educational: 45-60 seconds
Webhook Implementation
- Return 200 OK Quickly: Process the webhook payload asynchronously to avoid timeouts
- Implement Retry Logic: Webhooks may be retried if they fail
- Validate Signatures: Implement webhook signature validation for security
- Log All Webhooks: Keep logs for debugging and audit trails
Related Endpoints
- Generate Highlights from Transcription Job: Simpler option if you have not edited the transcript
- Video Transcription API - Generate the initial transcript
- Get Job by ID - Check job status and retrieve results
Was this page helpful?
