> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

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

> [!TIP]
>
> **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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Input[📝 Transcript] --> Analyze[Analyze Content]
    Analyze --> Identify[Find Highlights]
    Identify --> Plan[Create Clip Plan]
    Plan --> Output[📋 Clip Plan JSON]

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff

    class Input,Output input
    class Analyze,Identify,Plan process
```

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

\*One of `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

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
export OPENAI_API_KEY=your_key_here
pip install praisonaiagents
```

## Step-by-Step Build

**1. Create Recipe Directory**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
mkdir -p ~/.praisonai/templates/simple-video-highlights-reel-planner
cd ~/.praisonai/templates/simple-video-highlights-reel-planner
```

**2. Create TEMPLATE.yaml**

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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

> [tab] Model 1: Embedded SDK
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> 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}")
> ```

> [tab] Model 2: CLI Invocation
>
> ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> praison recipes run simple-video-highlights-reel-planner \
>   --input '{"transcript_text": "..."}' \
>   --json | jq '.clip_plan_json'
> ```

> [tab] Model 3: Plugin Mode
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> 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}
>         )
> ```

> [tab] Model 4: Local HTTP Sidecar
>
> ```javascript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> 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
>   })
> });
> ```

> [tab] Model 5: Remote Managed Runner
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> response = requests.post(
>     "https://api.video-tools.com/highlights",
>     headers={"Authorization": f"Bearer {api_key}"},
>     json={"transcript_text": transcript, "max_clips": 10}
> )
> ```

> [tab] Model 6: Event-Driven
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> 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

> [accordion] No highlights found
>
> Ensure your transcript includes timestamps. The recipe needs timing information to plan clips.

> [accordion] 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](https://praison.ai/docs/examples/recipe-examples/youtube-chapter-generator.md)** - Generate chapters for full videos
* **[Video Caption Generator](https://praison.ai/docs/examples/recipe-examples/video-caption-generator.md)** - Generate transcripts first


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.