@@ -1,6 +1,7 @@
1 1 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Command-line interface for PlanOpticon."""
2 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2 3 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import json
3 4 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import logging
4 5 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import os
5 6 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import sys
6 7 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import time
@@ -8,362 +9,254 @@
8 9 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
from typing import List, Optional
9 10 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
10 11 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import click
11 12 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
import colorlog
12 13 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
13 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.extractors.frame_extractor import extract_frames, save_frames
14 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.extractors.audio_extractor import AudioExtractor
15 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.api.transcription_api import TranscriptionAPI
16 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.api.vision_api import VisionAPI
17 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.analyzers.diagram_analyzer import DiagramAnalyzer
18 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.integrators.knowledge_graph import KnowledgeGraph
19 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.integrators.plan_generator import PlanGenerator
20 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.cli.output_formatter import OutputFormatter
21 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
22 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Configure logging
14 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
23 15 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def setup_logging(verbose: bool = False) -> None:
24 16 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Set up logging with color formatting."""
25 17 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
log_level = logging.DEBUG if verbose else logging.INFO
26 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Create a formatter that includes timestamp, level, and message
28 18 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
formatter = colorlog.ColoredFormatter(
29 19 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"%(log_color)s%(asctime)s [%(levelname)s] %(message)s",
30 20 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
datefmt="%Y-%m-%d %H:%M:%S",
31 21 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
log_colors={
32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 'DEBUG': 'cyan',
33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 'INFO': 'green',
34 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 'WARNING': 'yellow',
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 'ERROR': 'red',
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 'CRITICAL': 'red,bg_white',
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Set up console handler
22 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "DEBUG": "cyan",
23 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "INFO": "green",
24 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WARNING": "yellow",
25 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ERROR": "red",
26 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "CRITICAL": "red,bg_white",
27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ },
28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
41 29 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
console_handler = logging.StreamHandler()
42 30 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
console_handler.setFormatter(formatter)
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Configure root logger
45 31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
root_logger = logging.getLogger()
46 32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
root_logger.setLevel(log_level)
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Remove existing handlers and add our handler
49 33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for handler in root_logger.handlers:
50 34 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
root_logger.removeHandler(handler)
51 35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
root_logger.addHandler(console_handler)
52 36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Main CLI group
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
54 38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@click.group()
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--verbose', '-v', is_flag=True, help='Enable verbose output')
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.version_option('0.1.0', prog_name='PlanOpticon')
39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output")
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.version_option("0.2.0", prog_name="PlanOpticon")
57 41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@click.pass_context
58 42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def cli(ctx, verbose):
59 43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""PlanOpticon - Comprehensive Video Analysis & Knowledge Extraction Tool."""
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Initialize context
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ctx.ensure_object(dict)
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ctx.obj['verbose'] = verbose
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Set up logging
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- setup_logging(verbose)
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @cli.command()
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--input', '-i', required=True, type=click.Path(exists=True),
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- help='Input video file path')
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--output', '-o', required=True, type=click.Path(),
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- help='Output directory for extracted content')
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--depth', type=click.Choice(['basic', 'standard', 'comprehensive']),
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- default='standard', help='Processing depth')
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--focus', type=str, help='Comma-separated list of focus areas (e.g., "diagrams,action-items")')
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--use-gpu', is_flag=True, help='Enable GPU acceleration if available')
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--sampling-rate', type=float, default=0.5,
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- help='Frame sampling rate (1.0 = every frame)')
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--change-threshold', type=float, default=0.15,
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- help='Threshold for detecting visual changes between frames')
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--title', type=str, help='Title for the analysis report')
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--provider', '-p', type=click.Choice(['auto', 'openai', 'anthropic', 'gemini']),
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- default='auto', help='API provider (auto selects best available)')
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--vision-model', type=str, default=None, help='Override model for vision tasks')
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--chat-model', type=str, default=None, help='Override model for LLM/chat tasks')
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.pass_context
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- def analyze(ctx, input, output, depth, focus, use_gpu, sampling_rate, change_threshold, title,
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- provider, vision_model, chat_model):
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """Analyze video content and extract structured knowledge."""
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- start_time = time.time()
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Convert paths
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- input_path = Path(input)
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_dir = Path(output)
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_dir.mkdir(parents=True, exist_ok=True)
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Set up cache directory
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir = output_dir / "cache"
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir.mkdir(exist_ok=True)
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Handle focus areas
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- focus_areas = []
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if focus:
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- focus_areas = [area.strip().lower() for area in focus.split(',')]
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Set video title if not provided
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not title:
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- title = f"Analysis of {input_path.stem}"
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Log analysis parameters
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Starting analysis of {input_path}")
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Processing depth: {depth}")
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if focus_areas:
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Focus areas: {', '.join(focus_areas)}")
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- try:
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Create subdirectories
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frames_dir = output_dir / "frames"
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- audio_dir = output_dir / "audio"
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_dir = output_dir / "transcript"
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagrams_dir = output_dir / "diagrams"
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- results_dir = output_dir / "results"
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for directory in [frames_dir, audio_dir, transcript_dir, diagrams_dir, results_dir]:
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- directory.mkdir(exist_ok=True)
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Step 1: Extract frames
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Extracting video frames...")
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frames = extract_frames(
129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- input_path,
130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sampling_rate=sampling_rate,
131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- change_threshold=change_threshold,
132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- disable_gpu=not use_gpu
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Extracted {len(frames)} frames")
135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Save frames
137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frame_paths = save_frames(frames, frames_dir, "frame")
138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Saved frames to {frames_dir}")
139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Step 2: Extract audio
141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Extracting audio...")
142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- audio_extractor = AudioExtractor()
143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- audio_path = audio_extractor.extract_audio(
144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- input_path,
145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_path=audio_dir / f"{input_path.stem}.wav"
146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- audio_props = audio_extractor.get_audio_properties(audio_path)
148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Extracted audio: {audio_props['duration']:.2f}s, {audio_props['sample_rate']} Hz")
149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Step 3: Transcribe audio
151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Transcribing audio...")
152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription_api = TranscriptionAPI(
153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- provider="openai", # Could be configurable
154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir=cache_dir,
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- use_cache=True
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Process based on depth
159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- detect_speakers = depth != "basic"
160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription = transcription_api.transcribe_audio(
161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- audio_path,
162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- detect_speakers=detect_speakers,
163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- speakers=2 if detect_speakers else 1 # Default to 2 speakers if detecting
164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Save transcript in different formats
167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_path = transcription_api.save_transcript(
168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription,
169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_dir / f"{input_path.stem}",
170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- format="json"
171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription_api.save_transcript(
173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription,
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_dir / f"{input_path.stem}",
175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- format="txt"
176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription_api.save_transcript(
178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcription,
179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_dir / f"{input_path.stem}",
180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- format="srt"
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Saved transcripts to {transcript_dir}")
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Step 4: Diagram extraction and analysis
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Analyzing visual elements...")
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Initialize vision API
189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- vision_api = VisionAPI(
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- provider="openai", # Could be configurable
191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir=cache_dir,
192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- use_cache=True
193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Initialize diagram analyzer
196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagram_analyzer = DiagramAnalyzer(
197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- vision_api=vision_api,
198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir=cache_dir,
199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- use_cache=True
200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Detect and analyze diagrams
203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # We pass frame paths instead of numpy arrays for better caching
204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Detecting diagrams in frames...")
205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagrams = []
206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Skip diagram detection for basic depth
208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if depth != "basic" and (not focus_areas or "diagrams" in focus_areas):
209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # For demo purposes, limit to a subset of frames to reduce API costs
210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- max_frames_to_analyze = 10 if depth == "standard" else 20
211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frame_subset = frame_paths[:min(max_frames_to_analyze, len(frame_paths))]
212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- detected_frames = diagram_analyzer.detect_diagrams(frame_subset)
214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if detected_frames:
216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Detected {len(detected_frames)} potential diagrams")
217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Process each detected diagram
219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for idx, confidence in detected_frames:
220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if idx < len(frame_subset):
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frame_path = frame_subset[idx]
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Analyzing diagram in frame {idx} (confidence: {confidence:.2f})")
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Analyze the diagram
225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis = diagram_analyzer.analyze_diagram(frame_path, extract_text=True)
226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Add frame metadata
228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis['frame_index'] = idx
229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis['confidence'] = confidence
230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis['image_path'] = frame_path
231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Generate Mermaid if sufficient analysis available
233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if depth == "comprehensive" and 'semantic_analysis' in analysis and analysis.get('text_content'):
234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis['mermaid'] = diagram_analyzer.generate_mermaid(analysis)
235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Save diagram image to diagrams directory
237 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- import shutil
238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagram_path = diagrams_dir / f"diagram_{idx}.jpg"
239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- shutil.copy2(frame_path, diagram_path)
240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- analysis['image_path'] = str(diagram_path)
241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Save analysis as JSON
243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagram_json_path = diagrams_dir / f"diagram_{idx}.json"
244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- with open(diagram_json_path, 'w') as f:
245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- json.dump(analysis, f, indent=2)
246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagrams.append(analysis)
248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- else:
249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("No diagrams detected in analyzed frames")
250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Step 5: Generate knowledge graph and markdown report
252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("Generating knowledge graph and report...")
253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Initialize knowledge graph
255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph = KnowledgeGraph(
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir=cache_dir,
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- use_cache=True
258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Initialize plan generator
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- plan_generator = PlanGenerator(
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph=knowledge_graph,
263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_dir=cache_dir,
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- use_cache=True
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Process transcript and diagrams
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- with open(transcript_path) as f:
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_data = json.load(f)
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Process into knowledge graph
272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph.process_transcript(transcript_data)
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if diagrams:
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph.process_diagrams(diagrams)
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Save knowledge graph
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- kg_path = knowledge_graph.save(results_dir / "knowledge_graph.json")
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Extract key points
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- key_points = plan_generator.extract_key_points(transcript_data)
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Generate markdown
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- with open(kg_path) as f:
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- kg_data = json.load(f)
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- markdown_path = results_dir / "analysis.md"
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- markdown_content = plan_generator.generate_markdown(
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript=transcript_data,
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- key_points=key_points,
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagrams=diagrams,
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph=kg_data,
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- video_title=title,
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_path=markdown_path
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Format and organize outputs
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_formatter = OutputFormatter(output_dir)
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- outputs = output_formatter.organize_outputs(
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- markdown_path=markdown_path,
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- knowledge_graph_path=kg_path,
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- diagrams=diagrams,
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- frames_dir=frames_dir,
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- transcript_path=transcript_path
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- )
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Create HTML index
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- index_path = output_formatter.create_html_index(outputs)
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Finalize
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- elapsed = time.time() - start_time
311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Analysis completed in {elapsed:.2f} seconds")
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Results available at {index_path}")
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- except Exception as e:
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.error(f"Error during analysis: {str(e)}")
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if ctx.obj['verbose']:
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- import traceback
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- traceback.print_exc()
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sys.exit(1)
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @cli.command()
322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--cache-dir', type=click.Path(), help='Path to cache directory')
323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--older-than', type=int, help='Clear entries older than N seconds')
324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.option('--all', 'clear_all', is_flag=True, help='Clear all cache entries')
325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @click.pass_context
326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- def clear_cache(ctx, cache_dir, older_than, clear_all):
327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- """Clear API response cache."""
328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not cache_dir and not os.environ.get('CACHE_DIR'):
329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.error("Cache directory not specified")
330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sys.exit(1)
331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache_path = Path(cache_dir or os.environ.get('CACHE_DIR'))
333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not cache_path.exists():
335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.warning(f"Cache directory does not exist: {cache_path}")
336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return
337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- try:
339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Clear specific caches
340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- from video_processor.utils.api_cache import ApiCache
341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- namespaces = [d.name for d in cache_path.iterdir() if d.is_dir()]
343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if not namespaces:
345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info("No cache namespaces found")
346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return
347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- total_cleared = 0
349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for namespace in namespaces:
350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cache = ApiCache(cache_path, namespace)
351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cleared = cache.clear(older_than if not clear_all else None)
352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- total_cleared += cleared
353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Cleared {cleared} entries from {namespace} cache")
354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.info(f"Total cleared: {total_cleared} entries")
356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- except Exception as e:
358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- logging.error(f"Error clearing cache: {str(e)}")
359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if ctx.obj['verbose']:
360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- import traceback
361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- traceback.print_exc()
362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- sys.exit(1)
363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @cli.command('list-models')
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ctx.ensure_object(dict)
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ctx.obj["verbose"] = verbose
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ setup_logging(verbose)
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.command()
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--input", "-i", required=True, type=click.Path(exists=True), help="Input video file path")
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--output", "-o", required=True, type=click.Path(), help="Output directory")
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--depth",
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(["basic", "standard", "comprehensive"]),
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="standard",
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="Processing depth",
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--focus", type=str, help='Comma-separated focus areas (e.g., "diagrams,action-items")')
59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--use-gpu", is_flag=True, help="Enable GPU acceleration if available")
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--sampling-rate", type=float, default=0.5, help="Frame sampling rate")
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--change-threshold", type=float, default=0.15, help="Visual change threshold")
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--title", type=str, help="Title for the analysis report")
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--provider",
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "-p",
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(["auto", "openai", "anthropic", "gemini"]),
67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="auto",
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="API provider",
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--vision-model", type=str, default=None, help="Override model for vision tasks")
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks")
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.pass_context
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def analyze(
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ctx,
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ input,
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ output,
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ depth,
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ focus,
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ use_gpu,
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sampling_rate,
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ change_threshold,
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ title,
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ provider,
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ vision_model,
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ chat_model,
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ):
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Analyze a single video and extract structured knowledge."""
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.pipeline import process_single_video
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.providers.manager import ProviderManager
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ focus_areas = [a.strip().lower() for a in focus.split(",")] if focus else []
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ prov = None if provider == "auto" else provider
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pm = ProviderManager(
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ vision_model=vision_model,
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ chat_model=chat_model,
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ provider=prov,
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifest = process_single_video(
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ input_path=input,
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ output_dir=output,
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ provider_manager=pm,
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ depth=depth,
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ focus_areas=focus_areas,
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sampling_rate=sampling_rate,
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ change_threshold=change_threshold,
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ use_gpu=use_gpu,
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ title=title,
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Results at {output}/manifest.json")
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.error(f"Error: {e}")
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if ctx.obj["verbose"]:
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import traceback
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ traceback.print_exc()
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.command()
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--input-dir", "-i", required=True, type=click.Path(exists=True), help="Directory of videos")
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--output", "-o", required=True, type=click.Path(), help="Output directory")
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--depth",
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(["basic", "standard", "comprehensive"]),
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="standard",
129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="Processing depth",
130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--pattern",
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=str,
134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="*.mp4,*.mkv,*.avi,*.mov,*.webm",
135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="File glob patterns (comma-separated)",
136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--title", type=str, default="Batch Processing Results", help="Batch title")
138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--provider",
140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "-p",
141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(["auto", "openai", "anthropic", "gemini"]),
142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="auto",
143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="API provider",
144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--vision-model", type=str, default=None, help="Override model for vision tasks")
146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks")
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.pass_context
148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def batch(ctx, input_dir, output, depth, pattern, title, provider, vision_model, chat_model):
149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Process a folder of videos in batch."""
150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.integrators.knowledge_graph import KnowledgeGraph
151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.integrators.plan_generator import PlanGenerator
152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.models import BatchManifest, BatchVideoEntry
153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.output_structure import (
154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ create_batch_output_dirs,
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ read_video_manifest,
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ write_batch_manifest,
157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.pipeline import process_single_video
159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.providers.manager import ProviderManager
160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ input_dir = Path(input_dir)
162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ prov = None if provider == "auto" else provider
163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pm = ProviderManager(vision_model=vision_model, chat_model=chat_model, provider=prov)
164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Find videos
166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ patterns = [p.strip() for p in pattern.split(",")]
167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ videos = []
168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for pat in patterns:
169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ videos.extend(sorted(input_dir.glob(pat)))
170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ videos = sorted(set(videos))
171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not videos:
173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.error(f"No videos found in {input_dir} matching {pattern}")
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Found {len(videos)} videos to process")
177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dirs = create_batch_output_dirs(output, title)
179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifests = []
180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entries = []
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged_kg = KnowledgeGraph()
182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for idx, video_path in enumerate(videos):
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ video_name = video_path.stem
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ video_output = dirs["videos"] / video_name
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Processing video {idx + 1}/{len(videos)}: {video_path.name}")
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry = BatchVideoEntry(
189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ video_name=video_name,
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifest_path=f"videos/{video_name}/manifest.json",
191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifest = process_single_video(
195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ input_path=video_path,
196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ output_dir=video_output,
197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ provider_manager=pm,
198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ depth=depth,
199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ title=f"Analysis of {video_name}",
200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.status = "completed"
202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.diagrams_count = len(manifest.diagrams)
203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.action_items_count = len(manifest.action_items)
204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.key_points_count = len(manifest.key_points)
205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.duration_seconds = manifest.video.duration_seconds
206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifests.append(manifest)
207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Merge knowledge graph
209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = video_output / "results" / "knowledge_graph.json"
210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if kg_path.exists():
211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_data = json.loads(kg_path.read_text())
212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ video_kg = KnowledgeGraph.from_dict(kg_data)
213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged_kg.merge(video_kg)
214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.error(f"Failed to process {video_path.name}: {e}")
217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.status = "failed"
218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entry.error = str(e)
219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if ctx.obj["verbose"]:
220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import traceback
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ traceback.print_exc()
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entries.append(entry)
225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Save merged knowledge graph
227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged_kg_path = Path(output) / "knowledge_graph.json"
228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged_kg.save(merged_kg_path)
229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Generate batch summary
231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ plan_gen = PlanGenerator(provider_manager=pm, knowledge_graph=merged_kg)
232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ summary_path = Path(output) / "batch_summary.md"
233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ plan_gen.generate_batch_summary(
234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifests=manifests,
235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg=merged_kg,
236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ title=title,
237 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ output_path=summary_path,
238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Write batch manifest
241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ batch_manifest = BatchManifest(
242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ title=title,
243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_videos=len(videos),
244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ completed_videos=sum(1 for e in entries if e.status == "completed"),
245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ failed_videos=sum(1 for e in entries if e.status == "failed"),
246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_diagrams=sum(e.diagrams_count for e in entries),
247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_action_items=sum(e.action_items_count for e in entries),
248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_key_points=sum(e.key_points_count for e in entries),
249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ videos=entries,
250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ batch_summary_md="batch_summary.md",
251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ merged_knowledge_graph_json="knowledge_graph.json",
252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ write_batch_manifest(batch_manifest, output)
254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Batch complete: {batch_manifest.completed_videos}/{batch_manifest.total_videos} succeeded")
255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.command("list-models")
365 258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@click.pass_context
366 259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def list_models(ctx):
367 260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Discover and display available models from all configured providers."""
368 261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
from video_processor.providers.discovery import discover_available_models
369 262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@@ -371,11 +264,10 @@
371 264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if not models:
372 265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo("No models discovered. Check that at least one API key is set:")
373 266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo(" OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY")
374 267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return
375 268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
376 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- # Group by provider
377 269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
by_provider: dict[str, list] = {}
378 270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for m in models:
379 271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
by_provider.setdefault(m.provider, []).append(m)
380 272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
381 273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for provider, provider_models in sorted(by_provider.items()):
@@ -385,12 +277,54 @@
385 277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
caps = ", ".join(m.capabilities)
386 278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo(f" {m.id:<40} [{caps}]")
387 279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
388 280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo(f"\nTotal: {len(models)} models across {len(by_provider)} providers")
389 281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.command()
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--cache-dir", type=click.Path(), help="Path to cache directory")
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--older-than", type=int, help="Clear entries older than N seconds")
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--all", "clear_all", is_flag=True, help="Clear all cache entries")
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.pass_context
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def clear_cache(ctx, cache_dir, older_than, clear_all):
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Clear API response cache."""
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not cache_dir and not os.environ.get("CACHE_DIR"):
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.error("Cache directory not specified")
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cache_path = Path(cache_dir or os.environ.get("CACHE_DIR"))
295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not cache_path.exists():
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.warning(f"Cache directory does not exist: {cache_path}")
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.utils.api_cache import ApiCache
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespaces = [d.name for d in cache_path.iterdir() if d.is_dir()]
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not namespaces:
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info("No cache namespaces found")
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_cleared = 0
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for namespace in namespaces:
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cache = ApiCache(cache_path, namespace)
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cleared = cache.clear(older_than if not clear_all else None)
311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_cleared += cleared
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Cleared {cleared} entries from {namespace} cache")
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.info(f"Total cleared: {total_cleared} entries")
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logging.error(f"Error clearing cache: {e}")
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if ctx.obj["verbose"]:
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import traceback
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ traceback.print_exc()
321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
390 323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
391 324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def main():
392 325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Entry point for command-line usage."""
393 326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
cli(obj={})
394 327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
395 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if __name__ == '__main__':
328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if __name__ == "__main__":
396 330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
main()
397 331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
398 332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
A DDED video_processor/integrators/plan_generator.py
399 333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
A DDED video_processor/pipeline.py