Skip to main content

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 managers
Why: 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

InputTypeRequiredDescription
transcript_textstringYes*Transcript with timestamps
video_pathstringYes*Path to video (alternative)
highlight_goalstringNoWhat to highlight (default: engaging)
max_clipsintegerNoMaximum clips to identify (default: 10)
*One of transcript_text or video_path is required.
OutputTypeDescription
clip_plan_jsonarrayPlanned clips with timestamps
title_suggestionsarraySuggested titles for each clip
okbooleanSuccess indicator

Prerequisites

export OPENAI_API_KEY=your_key_here
pip install praisonaiagents

Step-by-Step Build

1

Create Recipe Directory

mkdir -p ~/.praison/templates/simple-video-highlights-reel-planner
cd ~/.praison/templates/simple-video-highlights-reel-planner
2

Create TEMPLATE.yaml

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

# 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

# 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

# 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

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}")

Troubleshooting

Ensure your transcript includes timestamps. The recipe needs timing information to plan clips.
The recipe targets 15-60 second clips. For different durations, adjust the instructions in a custom fork.

Next Steps