Video Highlights Reel Planner
Plan video highlight clips from transcripts—identify the best moments without heavy video editing.Problem Statement
Who: Video editors, content creators, social media managersWhy: Finding highlight-worthy moments in long videos is time-consuming. AI can identify key moments from transcripts.
Planning Only: This recipe focuses on identifying and planning clips, not actual video editing. Keep dependencies minimal for maximum portability.
What You’ll Build
A recipe that analyzes transcripts and outputs a structured clip plan with timestamps and titles.Input/Output Contract
| Input | Type | Required | Description |
|---|---|---|---|
transcript_text | string | Yes* | Transcript with timestamps |
video_path | string | Yes* | Path to video (alternative) |
highlight_goal | string | No | What to highlight (default: engaging) |
max_clips | integer | No | Maximum clips to identify (default: 10) |
transcript_text or video_path is required.
| Output | Type | Description |
|---|---|---|
clip_plan_json | array | Planned clips with timestamps |
title_suggestions | array | Suggested titles for each clip |
ok | boolean | Success indicator |
Prerequisites
Copy
export OPENAI_API_KEY=your_key_here
pip install praisonaiagents
Step-by-Step Build
1
Create Recipe Directory
Copy
mkdir -p ~/.praison/templates/simple-video-highlights-reel-planner
cd ~/.praison/templates/simple-video-highlights-reel-planner
2
Create TEMPLATE.yaml
Copy
name: simple-video-highlights-reel-planner
version: "1.0.0"
description: "Plan video highlight clips from transcripts"
author: "PraisonAI"
license: "MIT"
tags:
- video
- highlights
- planning
- content
requires:
env:
- OPENAI_API_KEY
packages:
- praisonaiagents
inputs:
transcript_text:
type: string
description: "Transcript text with timestamps"
required: false
video_path:
type: string
description: "Path to video file (alternative)"
required: false
highlight_goal:
type: string
description: "What type of highlights to find"
required: false
default: "engaging"
enum:
- engaging
- educational
- funny
- emotional
- actionable
max_clips:
type: integer
description: "Maximum number of clips to identify"
required: false
default: 10
minimum: 1
maximum: 50
outputs:
clip_plan_json:
type: array
description: "Planned clips with timestamps and descriptions"
title_suggestions:
type: array
description: "Suggested titles for clips"
ok:
type: boolean
description: "Success indicator"
cli:
command: "praison recipes run simple-video-highlights-reel-planner"
examples:
- 'praison recipes run simple-video-highlights-reel-planner --input ''{"transcript_text": "00:00 Welcome..."}'''
safety:
dry_run_default: false
requires_consent: false
overwrites_files: false
network_access: true
pii_handling: false
3
Create recipe.py
Copy
# recipe.py
import os
import json
import re
from praisonaiagents import Agent, Task, PraisonAIAgents
def run(input_data: dict, config: dict = None) -> dict:
"""Plan video highlight clips from transcript."""
transcript_text = input_data.get("transcript_text")
video_path = input_data.get("video_path")
highlight_goal = input_data.get("highlight_goal", "engaging")
max_clips = input_data.get("max_clips", 10)
if not transcript_text and not video_path:
return {"ok": False, "error": {"code": "MISSING_INPUT", "message": "Either transcript_text or video_path is required"}}
if video_path and not transcript_text:
if not os.path.exists(video_path):
return {"ok": False, "error": {"code": "FILE_NOT_FOUND", "message": f"Video not found: {video_path}"}}
return {"ok": False, "error": {"code": "NOT_IMPLEMENTED", "message": "Video transcription not implemented. Provide transcript_text."}}
try:
goal_guidelines = {
"engaging": "Find moments that grab attention, surprising reveals, or compelling stories",
"educational": "Find clear explanations, key insights, and teachable moments",
"funny": "Find humorous moments, jokes, and entertaining segments",
"emotional": "Find touching moments, inspiring stories, and emotional peaks",
"actionable": "Find practical tips, how-to segments, and advice"
}
# Create highlight finder agent
finder = Agent(
name="Highlight Finder",
role="Video Content Analyst",
goal=f"Find the most {highlight_goal} moments",
instructions=f"""
You are a video content analyst specializing in finding highlights.
Goal: {highlight_goal} - {goal_guidelines[highlight_goal]}
For each highlight:
- Identify start and end timestamps
- Explain why it's highlight-worthy
- Suggest a clip duration (15-60 seconds ideal)
- Rate engagement potential (1-10)
Find up to {max_clips} highlights.
""",
)
# Create title generator
titler = Agent(
name="Title Generator",
role="Social Media Specialist",
goal="Create compelling clip titles",
instructions="""
You are a social media specialist.
- Create catchy, clickable titles
- Keep titles under 60 characters
- Use power words and hooks
- Match the content tone
""",
)
# Define tasks
find_task = Task(
name="find_highlights",
description=f"""
Analyze this transcript and find up to {max_clips} {highlight_goal} highlights:
{transcript_text[:10000]}
Output as JSON array:
[{{
"start_time": "MM:SS",
"end_time": "MM:SS",
"description": "What happens",
"why_highlight": "Why it's engaging",
"engagement_score": 8
}}]
""",
expected_output="JSON array of highlight clips",
agent=finder,
)
title_task = Task(
name="generate_titles",
description="Generate compelling titles for each highlight clip",
expected_output="List of titles matching each clip",
agent=titler,
context=[find_task],
)
# Execute
agents = PraisonAIAgents(
agents=[finder, titler],
tasks=[find_task, title_task],
)
result = agents.start()
# Parse clips
clips_text = result.get("find_highlights", "[]")
clips = parse_clips(clips_text)
# Parse titles
titles_text = result.get("generate_titles", "")
titles = [t.strip() for t in titles_text.split("\n") if t.strip() and len(t.strip()) > 5]
return {
"ok": True,
"clip_plan_json": clips[:max_clips],
"title_suggestions": titles[:max_clips],
"artifacts": [],
"warnings": [],
}
except Exception as e:
return {"ok": False, "error": {"code": "PROCESSING_ERROR", "message": str(e)}}
def parse_clips(text: str) -> list:
"""Parse clip plan from agent output."""
try:
match = re.search(r'\[.*\]', text, re.DOTALL)
if match:
return json.loads(match.group())
except json.JSONDecodeError:
pass
# Fallback parsing
clips = []
current_clip = {}
for line in text.split('\n'):
if 'start' in line.lower() and ':' in line:
time_match = re.search(r'(\d{1,2}:\d{2}(?::\d{2})?)', line)
if time_match:
current_clip['start_time'] = time_match.group(1)
elif 'end' in line.lower() and ':' in line:
time_match = re.search(r'(\d{1,2}:\d{2}(?::\d{2})?)', line)
if time_match:
current_clip['end_time'] = time_match.group(1)
elif 'description' in line.lower():
current_clip['description'] = line.split(':', 1)[-1].strip()
if current_clip.get('start_time') and current_clip.get('end_time'):
clips.append(current_clip)
current_clip = {}
return clips
4
Create test_recipe.py
Copy
# test_recipe.py
import pytest
from recipe import run, parse_clips
def test_missing_input():
result = run({})
assert result["ok"] is False
assert result["error"]["code"] == "MISSING_INPUT"
def test_parse_clips_json():
text = '[{"start_time": "00:30", "end_time": "01:00", "description": "Key moment"}]'
clips = parse_clips(text)
assert len(clips) == 1
assert clips[0]["start_time"] == "00:30"
def test_highlight_goals():
valid_goals = ["engaging", "educational", "funny", "emotional", "actionable"]
for goal in valid_goals:
assert goal in valid_goals
@pytest.mark.integration
def test_end_to_end():
transcript = """
00:00 Welcome to today's video about productivity tips.
02:30 Here's the number one tip that changed my life.
05:00 Let me show you exactly how to implement this.
10:00 The results were incredible - I saved 10 hours per week.
15:00 Thanks for watching, don't forget to subscribe!
"""
result = run({
"transcript_text": transcript,
"highlight_goal": "actionable",
"max_clips": 5
})
assert result["ok"] is True
assert len(result["clip_plan_json"]) > 0
Run Locally
Copy
# Basic usage
praison recipes run simple-video-highlights-reel-planner \
--input '{"transcript_text": "00:00 Welcome..."}'
# Find funny moments
praison recipes run simple-video-highlights-reel-planner \
--input '{"transcript_text": "...", "highlight_goal": "funny", "max_clips": 5}'
Deploy & Integrate: 6 Integration Models
- Model 1: Embedded SDK
- Model 2: CLI Invocation
- Model 3: Plugin Mode
- Model 4: Local HTTP Sidecar
- Model 5: Remote Managed Runner
- Model 6: Event-Driven
Copy
from praisonai import recipe
result = recipe.run(
"simple-video-highlights-reel-planner",
input={
"transcript_text": transcript,
"highlight_goal": "engaging",
"max_clips": 10
}
)
if result.ok:
for i, clip in enumerate(result.output["clip_plan_json"]):
title = result.output["title_suggestions"][i] if i < len(result.output["title_suggestions"]) else "Untitled"
print(f"{clip['start_time']} - {clip['end_time']}: {title}")
Copy
praison recipes run simple-video-highlights-reel-planner \
--input '{"transcript_text": "..."}' \
--json | jq '.clip_plan_json'
Copy
class HighlightsPlugin:
def find_highlights(self, transcript, goal="engaging"):
from praisonai import recipe
return recipe.run(
"simple-video-highlights-reel-planner",
input={"transcript_text": transcript, "highlight_goal": goal}
)
Copy
const response = await fetch('http://localhost:8765/recipes/simple-video-highlights-reel-planner/run', {
method: 'POST',
body: JSON.stringify({
transcript_text: transcript,
highlight_goal: 'funny',
max_clips: 5
})
});
Copy
response = requests.post(
"https://api.video-tools.com/highlights",
headers={"Authorization": f"Bearer {api_key}"},
json={"transcript_text": transcript, "max_clips": 10}
)
Copy
def on_video_transcribed(event):
queue.send({
"recipe": "simple-video-highlights-reel-planner",
"input": {
"transcript_text": event['transcript'],
"highlight_goal": "engaging"
},
"callback_url": f"https://api.example.com/videos/{event['video_id']}/highlights"
})
Troubleshooting
No highlights found
No highlights found
Ensure your transcript includes timestamps. The recipe needs timing information to plan clips.
Clips too long or short
Clips too long or short
The recipe targets 15-60 second clips. For different durations, adjust the instructions in a custom fork.
Next Steps
- YouTube Chapter Generator - Generate chapters for full videos
- Video Caption Generator - Generate transcripts first

