Initial project scaffold - Phase 1 MVP structure
Core modules: - cli.py: Command-line interface with Click - pipeline.py: Main orchestrator - video_processor.py: Frame extraction with ffmpeg - audio_analyzer.py: Whisper transcription - vision_analyzer.py: Component detection (placeholder) - doc_generator.py: Markdown + PDF output Also includes: - pyproject.toml with uv/hatch config - Prompts for AI analysis - Basic tests - ROADMAP.md with 4-week plan
This commit is contained in:
86
src/cad_documenter/cli.py
Normal file
86
src/cad_documenter/cli.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""CAD-Documenter CLI - Main entry point."""
|
||||
|
||||
import click
|
||||
from pathlib import Path
|
||||
from rich.console import Console
|
||||
|
||||
from .pipeline import DocumentationPipeline
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("video", type=click.Path(exists=True, path_type=Path))
|
||||
@click.option("-o", "--output", type=click.Path(path_type=Path), help="Output directory")
|
||||
@click.option("--frames-only", is_flag=True, help="Only extract frames, skip documentation")
|
||||
@click.option("--atomizer-hints", is_flag=True, help="Generate Atomizer FEA hints")
|
||||
@click.option("--bom", is_flag=True, help="Generate Bill of Materials")
|
||||
@click.option("--pdf", is_flag=True, help="Generate PDF via Atomaste Report Standard")
|
||||
@click.option("--frame-interval", default=2.0, help="Seconds between frame extractions")
|
||||
@click.option("--whisper-model", default="base", help="Whisper model size (tiny/base/small/medium/large)")
|
||||
@click.version_option()
|
||||
def main(
|
||||
video: Path,
|
||||
output: Path | None,
|
||||
frames_only: bool,
|
||||
atomizer_hints: bool,
|
||||
bom: bool,
|
||||
pdf: bool,
|
||||
frame_interval: float,
|
||||
whisper_model: str,
|
||||
):
|
||||
"""
|
||||
Generate engineering documentation from a CAD walkthrough video.
|
||||
|
||||
VIDEO: Path to the video file (.mp4, .mov, .avi, etc.)
|
||||
"""
|
||||
console.print(f"[bold blue]CAD-Documenter[/bold blue] v0.1.0")
|
||||
console.print(f"Processing: [cyan]{video}[/cyan]")
|
||||
|
||||
# Default output directory
|
||||
if output is None:
|
||||
output = video.parent / f"{video.stem}_docs"
|
||||
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Run pipeline
|
||||
pipeline = DocumentationPipeline(
|
||||
video_path=video,
|
||||
output_dir=output,
|
||||
frame_interval=frame_interval,
|
||||
whisper_model=whisper_model,
|
||||
)
|
||||
|
||||
if frames_only:
|
||||
console.print("[yellow]Extracting frames only...[/yellow]")
|
||||
pipeline.extract_frames()
|
||||
console.print(f"[green]✓[/green] Frames saved to {output / 'frames'}")
|
||||
return
|
||||
|
||||
# Full pipeline
|
||||
console.print("[yellow]Step 1/4:[/yellow] Extracting frames...")
|
||||
frames = pipeline.extract_frames()
|
||||
console.print(f" [green]✓[/green] Extracted {len(frames)} frames")
|
||||
|
||||
console.print("[yellow]Step 2/4:[/yellow] Transcribing audio...")
|
||||
transcript = pipeline.transcribe_audio()
|
||||
console.print(f" [green]✓[/green] Transcribed {len(transcript.segments)} segments")
|
||||
|
||||
console.print("[yellow]Step 3/4:[/yellow] Analyzing components...")
|
||||
analysis = pipeline.analyze_components(frames, transcript)
|
||||
console.print(f" [green]✓[/green] Identified {len(analysis.components)} components")
|
||||
|
||||
console.print("[yellow]Step 4/4:[/yellow] Generating documentation...")
|
||||
doc_path = pipeline.generate_documentation(analysis, atomizer_hints=atomizer_hints, bom=bom)
|
||||
console.print(f" [green]✓[/green] Documentation saved to {doc_path}")
|
||||
|
||||
if pdf:
|
||||
console.print("[yellow]Generating PDF...[/yellow]")
|
||||
pdf_path = pipeline.generate_pdf(doc_path)
|
||||
console.print(f" [green]✓[/green] PDF saved to {pdf_path}")
|
||||
|
||||
console.print(f"\n[bold green]Done![/bold green] Output: {output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user