Video Highlights Reel Planner

Plan video highlight clips from transcripts without heavy video editing

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.

What You’ll Build

A recipe that analyzes transcripts and outputs a structured clip plan with timestamps and titles.

Diagram

📝 Transcript

Analyze Content

Find Highlights

Create Clip Plan

📋 Clip Plan JSON

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

bash
export OPENAI_API_KEY=your_key_here
pip install praisonaiagents

Step-by-Step Build

  1. Create Recipe Directory
    bash
    mkdir -p ~/.praisonai/templates/simple-video-highlights-reel-planner
    cd ~/.praisonai/templates/simple-video-highlights-reel-planner
  2. Create TEMPLATE.yaml
    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
    python
    # recipe.py
    import os
    import json
    import re
    from praisonaiagents import Agent, Task, AgentTeam
    
    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 = AgentTeam(
                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
    python
    # 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

bash
# 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

python
from praisonai import recipe

# Load or define transcript
transcript = "00:00 Introduction to the topic..."

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

Model 2: CLI Invocation

bash
praison recipes run simple-video-highlights-reel-planner \
  --input '{"transcript_text": "..."}' \
  --json | jq '.clip_plan_json'

Model 3: Plugin Mode

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

Model 4: Local HTTP Sidecar

javascript
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
  })
});

Model 5: Remote Managed Runner

python
response = requests.post(
    "https://api.video-tools.com/highlights",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"transcript_text": transcript, "max_clips": 10}
)

Model 6: Event-Driven

python
def on_video_transcribed(event):
    import queue as q
    job_queue = q.Queue()  # Replace with SQS/RabbitMQ in production
    job_queue.put({
        "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

Ensure your transcript includes timestamps. The recipe needs timing information to plan clips.

Clips too long or short

The recipe targets 15-60 second clips. For different durations, adjust the instructions in a custom fork.

Next Steps