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.
name: simple-video-highlights-reel-plannerversion: "1.0.0"description: "Plan video highlight clips from transcripts"author: "PraisonAI"license: "MIT"tags: - video - highlights - planning - contentrequires: env: - OPENAI_API_KEY packages: - praisonaiagentsinputs: 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: 50outputs: 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.pyimport osimport jsonimport refrom praisonaiagents import Agent, Task, AgentTeamdef 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
# test_recipe.pyimport pytestfrom recipe import run, parse_clipsdef 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.integrationdef 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
from praisonai import recipe# Load or define transcripttranscript = "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}")