PlanOpticon
feat(cli): add --output-format json and --templates-dir to analyze command
Commit
5e5d3c2161f14858d3beb94f461258a4bc5c294428b03a63b693deb601e7a114
Parent
b1d426992ff933d…
1 file changed
+29
-4
+29
-4
| --- video_processor/cli/commands.py | ||
| +++ video_processor/cli/commands.py | ||
| @@ -92,10 +92,22 @@ | ||
| 92 | 92 | default="auto", |
| 93 | 93 | help="API provider", |
| 94 | 94 | ) |
| 95 | 95 | @click.option("--vision-model", type=str, default=None, help="Override model for vision tasks") |
| 96 | 96 | @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks") |
| 97 | +@click.option( | |
| 98 | + "--output-format", | |
| 99 | + type=click.Choice(["default", "json"]), | |
| 100 | + default="default", | |
| 101 | + help="Output format: default (files + summary) or json (structured JSON to stdout)", | |
| 102 | +) | |
| 103 | +@click.option( | |
| 104 | + "--templates-dir", | |
| 105 | + type=click.Path(exists=True), | |
| 106 | + default=None, | |
| 107 | + help="Directory with custom prompt template .txt files", | |
| 108 | +) | |
| 97 | 109 | @click.pass_context |
| 98 | 110 | def analyze( |
| 99 | 111 | ctx, |
| 100 | 112 | input, |
| 101 | 113 | output, |
| @@ -107,10 +119,12 @@ | ||
| 107 | 119 | periodic_capture, |
| 108 | 120 | title, |
| 109 | 121 | provider, |
| 110 | 122 | vision_model, |
| 111 | 123 | chat_model, |
| 124 | + output_format, | |
| 125 | + templates_dir, | |
| 112 | 126 | ): |
| 113 | 127 | """Analyze a single video and extract structured knowledge.""" |
| 114 | 128 | from video_processor.pipeline import process_single_video |
| 115 | 129 | from video_processor.providers.manager import ProviderManager |
| 116 | 130 | |
| @@ -121,12 +135,17 @@ | ||
| 121 | 135 | vision_model=vision_model, |
| 122 | 136 | chat_model=chat_model, |
| 123 | 137 | provider=prov, |
| 124 | 138 | ) |
| 125 | 139 | |
| 140 | + if templates_dir: | |
| 141 | + from video_processor.utils.prompt_templates import PromptTemplate | |
| 142 | + | |
| 143 | + pm.prompt_templates = PromptTemplate(templates_dir=templates_dir) | |
| 144 | + | |
| 126 | 145 | try: |
| 127 | - process_single_video( | |
| 146 | + manifest = process_single_video( | |
| 128 | 147 | input_path=input, |
| 129 | 148 | output_dir=output, |
| 130 | 149 | provider_manager=pm, |
| 131 | 150 | depth=depth, |
| 132 | 151 | focus_areas=focus_areas, |
| @@ -134,15 +153,21 @@ | ||
| 134 | 153 | change_threshold=change_threshold, |
| 135 | 154 | periodic_capture_seconds=periodic_capture, |
| 136 | 155 | use_gpu=use_gpu, |
| 137 | 156 | title=title, |
| 138 | 157 | ) |
| 139 | - click.echo(pm.usage.format_summary()) | |
| 140 | - click.echo(f"\n Results: {output}/manifest.json") | |
| 158 | + if output_format == "json": | |
| 159 | + click.echo(json.dumps(manifest.model_dump(), indent=2, default=str)) | |
| 160 | + else: | |
| 161 | + click.echo(pm.usage.format_summary()) | |
| 162 | + click.echo(f"\n Results: {output}/manifest.json") | |
| 141 | 163 | except Exception as e: |
| 142 | 164 | logging.error(f"Error: {e}") |
| 143 | - click.echo(pm.usage.format_summary()) | |
| 165 | + if output_format == "json": | |
| 166 | + click.echo(json.dumps({"error": str(e)})) | |
| 167 | + else: | |
| 168 | + click.echo(pm.usage.format_summary()) | |
| 144 | 169 | if ctx.obj["verbose"]: |
| 145 | 170 | import traceback |
| 146 | 171 | |
| 147 | 172 | traceback.print_exc() |
| 148 | 173 | sys.exit(1) |
| 149 | 174 |
| --- video_processor/cli/commands.py | |
| +++ video_processor/cli/commands.py | |
| @@ -92,10 +92,22 @@ | |
| 92 | default="auto", |
| 93 | help="API provider", |
| 94 | ) |
| 95 | @click.option("--vision-model", type=str, default=None, help="Override model for vision tasks") |
| 96 | @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks") |
| 97 | @click.pass_context |
| 98 | def analyze( |
| 99 | ctx, |
| 100 | input, |
| 101 | output, |
| @@ -107,10 +119,12 @@ | |
| 107 | periodic_capture, |
| 108 | title, |
| 109 | provider, |
| 110 | vision_model, |
| 111 | chat_model, |
| 112 | ): |
| 113 | """Analyze a single video and extract structured knowledge.""" |
| 114 | from video_processor.pipeline import process_single_video |
| 115 | from video_processor.providers.manager import ProviderManager |
| 116 | |
| @@ -121,12 +135,17 @@ | |
| 121 | vision_model=vision_model, |
| 122 | chat_model=chat_model, |
| 123 | provider=prov, |
| 124 | ) |
| 125 | |
| 126 | try: |
| 127 | process_single_video( |
| 128 | input_path=input, |
| 129 | output_dir=output, |
| 130 | provider_manager=pm, |
| 131 | depth=depth, |
| 132 | focus_areas=focus_areas, |
| @@ -134,15 +153,21 @@ | |
| 134 | change_threshold=change_threshold, |
| 135 | periodic_capture_seconds=periodic_capture, |
| 136 | use_gpu=use_gpu, |
| 137 | title=title, |
| 138 | ) |
| 139 | click.echo(pm.usage.format_summary()) |
| 140 | click.echo(f"\n Results: {output}/manifest.json") |
| 141 | except Exception as e: |
| 142 | logging.error(f"Error: {e}") |
| 143 | click.echo(pm.usage.format_summary()) |
| 144 | if ctx.obj["verbose"]: |
| 145 | import traceback |
| 146 | |
| 147 | traceback.print_exc() |
| 148 | sys.exit(1) |
| 149 |
| --- video_processor/cli/commands.py | |
| +++ video_processor/cli/commands.py | |
| @@ -92,10 +92,22 @@ | |
| 92 | default="auto", |
| 93 | help="API provider", |
| 94 | ) |
| 95 | @click.option("--vision-model", type=str, default=None, help="Override model for vision tasks") |
| 96 | @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks") |
| 97 | @click.option( |
| 98 | "--output-format", |
| 99 | type=click.Choice(["default", "json"]), |
| 100 | default="default", |
| 101 | help="Output format: default (files + summary) or json (structured JSON to stdout)", |
| 102 | ) |
| 103 | @click.option( |
| 104 | "--templates-dir", |
| 105 | type=click.Path(exists=True), |
| 106 | default=None, |
| 107 | help="Directory with custom prompt template .txt files", |
| 108 | ) |
| 109 | @click.pass_context |
| 110 | def analyze( |
| 111 | ctx, |
| 112 | input, |
| 113 | output, |
| @@ -107,10 +119,12 @@ | |
| 119 | periodic_capture, |
| 120 | title, |
| 121 | provider, |
| 122 | vision_model, |
| 123 | chat_model, |
| 124 | output_format, |
| 125 | templates_dir, |
| 126 | ): |
| 127 | """Analyze a single video and extract structured knowledge.""" |
| 128 | from video_processor.pipeline import process_single_video |
| 129 | from video_processor.providers.manager import ProviderManager |
| 130 | |
| @@ -121,12 +135,17 @@ | |
| 135 | vision_model=vision_model, |
| 136 | chat_model=chat_model, |
| 137 | provider=prov, |
| 138 | ) |
| 139 | |
| 140 | if templates_dir: |
| 141 | from video_processor.utils.prompt_templates import PromptTemplate |
| 142 | |
| 143 | pm.prompt_templates = PromptTemplate(templates_dir=templates_dir) |
| 144 | |
| 145 | try: |
| 146 | manifest = process_single_video( |
| 147 | input_path=input, |
| 148 | output_dir=output, |
| 149 | provider_manager=pm, |
| 150 | depth=depth, |
| 151 | focus_areas=focus_areas, |
| @@ -134,15 +153,21 @@ | |
| 153 | change_threshold=change_threshold, |
| 154 | periodic_capture_seconds=periodic_capture, |
| 155 | use_gpu=use_gpu, |
| 156 | title=title, |
| 157 | ) |
| 158 | if output_format == "json": |
| 159 | click.echo(json.dumps(manifest.model_dump(), indent=2, default=str)) |
| 160 | else: |
| 161 | click.echo(pm.usage.format_summary()) |
| 162 | click.echo(f"\n Results: {output}/manifest.json") |
| 163 | except Exception as e: |
| 164 | logging.error(f"Error: {e}") |
| 165 | if output_format == "json": |
| 166 | click.echo(json.dumps({"error": str(e)})) |
| 167 | else: |
| 168 | click.echo(pm.usage.format_summary()) |
| 169 | if ctx.obj["verbose"]: |
| 170 | import traceback |
| 171 | |
| 172 | traceback.print_exc() |
| 173 | sys.exit(1) |
| 174 |