digraph MediaAnalyzer { // Graph settings rankdir=TB; bgcolor="white"; fontname="Arial"; fontsize=12; ratio=fill; size="9,10!"; ranksep=0.3; nodesep=0.3; // Node defaults node [fontname="Arial", fontsize=10, shape=box, style=filled]; edge [fontname="Arial", fontsize=8]; // Color scheme subgraph cluster_legend { label="Legend"; style=filled; color=lightgray; node [shape=plaintext, style=filled]; implemented [label="✅ Implemented", fillcolor="#28a745", color="#ffffff", fontcolor="#ffffff"]; planned [label="⏳ Planned", fillcolor="#ffc107", color="#212529", fontcolor="#212529"]; code_pattern [label="📐 Code Pattern", fillcolor="#8e24aa", color="#ffffff", fontcolor="#ffffff"]; service_arch [label="⚡ Service/Architecture", fillcolor="#1976d2", color="#ffffff", fontcolor="#ffffff"]; implemented -> planned [style=invis]; code_pattern -> service_arch [style=invis]; } // Input Sources subgraph cluster_sources { label="Video Sources"; style=filled; color="#1976d2"; webcam [label="Webcam", fillcolor="#28a745", fontcolor="#ffffff"]; rtmp [label="RTMP/OBS", fillcolor="#28a745", fontcolor="#ffffff"]; files [label="File Upload", fillcolor="#ffc107", fontcolor="#212529"]; } // Source Adapters (Design Pattern) subgraph cluster_adapters { label="Source Adapters Pattern"; style=filled; color="#8e24aa"; base_adapter [label="BaseSourceAdapter\n(Abstract)", fillcolor="#ce93d8"]; webcam_adapter [label="WebcamAdapter", fillcolor="#28a745", fontcolor="#ffffff"]; rtmp_adapter [label="RtmpAdapter", fillcolor="#28a745", fontcolor="#ffffff"]; file_adapter [label="FileAdapter", fillcolor="#ffc107", fontcolor="#212529"]; } // Core Services subgraph cluster_core { label="Core Platform"; style=filled; color="#1976d2"; django [label="Django API\n+ Channels\n:8000", fillcolor="#28a745", fontcolor="#ffffff"]; postgres [label="PostgreSQL\nDatabase", fillcolor="#28a745", fontcolor="#ffffff"]; redis [label="Redis\nCache & Broker", fillcolor="#28a745", fontcolor="#ffffff"]; nginx [label="NGINX\nReverse Proxy\n:80", fillcolor="#28a745", fontcolor="#ffffff"]; } // Execution Strategies (Design Pattern) subgraph cluster_execution { label="Execution Strategies Pattern"; style=filled; color="#8e24aa"; base_strategy [label="BaseExecutionStrategy\n(Abstract)", fillcolor="#ce93d8"]; local_strategy [label="LocalStrategy", fillcolor="#28a745", fontcolor="#ffffff"]; lan_strategy [label="LANStrategy", fillcolor="#ffc107", fontcolor="#212529"]; cloud_strategy [label="CloudStrategy", fillcolor="#ffc107", fontcolor="#212529"]; } // Event Source Pattern (NEW) subgraph cluster_event_sources { label="Event Source Pattern"; style=filled; color="#8e24aa"; base_event_source [label="SegmentEventSource\n(Abstract)", fillcolor="#ce93d8"]; file_watcher_source [label="FileWatcherEventSource\n(Local/LAN)", fillcolor="#28a745", fontcolor="#ffffff"]; cloud_storage_source [label="CloudStorageEventSource\n(GCS Pub/Sub)", fillcolor="#ffc107", fontcolor="#212529"]; webhook_source [label="WebhookEventSource\n(External)", fillcolor="#ffc107", fontcolor="#212529"]; } // Event-Driven Processing Pipeline subgraph cluster_events { label="Event-Driven Processing"; style=filled; color="#1976d2"; event_source_manager [label="EventSourceManager\n(Environment-based)", fillcolor="#28a745", fontcolor="#ffffff"]; redis_events [label="Redis Event Queue\n(segment_events)", fillcolor="#28a745", fontcolor="#ffffff"]; event_processor [label="Event Processor\n(triggers analysis)", fillcolor="#28a745", fontcolor="#ffffff"]; } // Analysis Workers subgraph cluster_workers { label="Celery Workers"; style=filled; color="#1976d2"; logo_worker [label="Logo Detection\nWorker\n(logo_queue)", fillcolor="#28a745", fontcolor="#ffffff"]; visual_worker [label="Visual Properties\nWorker\n(visual_queue)", fillcolor="#ffc107", fontcolor="#212529"]; audio_worker [label="Audio Transcript\nWorker\n(audio_queue)", fillcolor="#ffc107", fontcolor="#212529"]; text_worker [label="Text Recognition\nWorker\n(text_queue)", fillcolor="#ffc107", fontcolor="#212529"]; } // AI Adapters (Design Pattern) subgraph cluster_ai_adapters { label="Analysis Adapters Pattern"; style=filled; color="#8e24aa"; base_ai [label="DetectionAdapter\n(Abstract)", fillcolor="#ce93d8"]; clip_adapter [label="CLIPAdapter\n(Local)", fillcolor="#28a745", fontcolor="#ffffff"]; gcp_vision [label="GCPVisionAdapter\n(Cloud)", fillcolor="#ffc107", fontcolor="#212529"]; yolo_adapter [label="YOLOAdapter\n(Planned)", fillcolor="#ffc107", fontcolor="#212529"]; } // Storage Options subgraph cluster_storage { label="Media Storage"; style=filled; color="#1976d2"; local_storage [label="Local Files\n(nginx-served)", fillcolor="#28a745", fontcolor="#ffffff"]; gcs_storage [label="Google Cloud\nStorage", fillcolor="#ffc107", fontcolor="#212529"]; } // Frontend subgraph cluster_frontend { label="Frontend"; style=filled; color="#1976d2"; angular [label="Angular 17 SPA\n+ WebSocket\n:4200", fillcolor="#28a745", fontcolor="#ffffff"]; hls_player [label="HLS.js Player\n+ Canvas Overlays", fillcolor="#28a745", fontcolor="#ffffff"]; } // Cloud Services subgraph cluster_cloud { label="GCP Services"; style=filled; color="#1976d2"; vision_api [label="Cloud Vision API\n(Logo Detection)", fillcolor="#ffc107", fontcolor="#212529"]; speech_api [label="Speech-to-Text API\n(Audio Transcript)", fillcolor="#ffc107", fontcolor="#212529"]; } // Connections - Current Implementation (solid) webcam -> webcam_adapter [color="#2e7d32"]; rtmp -> rtmp_adapter [color="#2e7d32"]; webcam_adapter -> django [color="#2e7d32"]; rtmp_adapter -> django [color="#2e7d32"]; django -> postgres [color="#2e7d32"]; django -> redis [color="#2e7d32"]; django -> local_storage [color="#2e7d32"]; django -> gcs_storage [color="#2e7d32"]; // Event source pattern connections local_storage -> file_watcher_source [label="monitors\nHLS segments", color="#2e7d32"]; gcs_storage -> cloud_storage_source [label="storage\nevents", color="#2e7d32"]; file_watcher_source -> event_source_manager [color="#2e7d32"]; cloud_storage_source -> event_source_manager [color="#2e7d32"]; webhook_source -> event_source_manager [color="#2e7d32"]; // Event-driven processing flow event_source_manager -> redis_events [label="publishes\nevents", color="#2e7d32"]; redis_events -> event_processor [label="consumes\nevents", color="#2e7d32"]; event_processor -> logo_worker [label="triggers\nanalysis", color="#2e7d32"]; redis -> logo_worker [color="#2e7d32"]; logo_worker -> local_strategy [color="#2e7d32"]; local_strategy -> clip_adapter [color="#2e7d32"]; local_strategy -> gcp_vision [color="#2e7d32"]; gcp_vision -> vision_api [color="#2e7d32"]; // WebSocket real-time updates logo_worker -> django [label="analysis\nresults", color="#2e7d32"]; django -> angular [label="WebSocket\nAPI", color="#2e7d32"]; angular -> hls_player [color="#2e7d32"]; nginx -> angular [color="#2e7d32"]; // Planned Connections (dashed) files -> file_adapter [color="#f57f17", style=dashed]; file_adapter -> django [color="#f57f17", style=dashed]; redis -> visual_worker [color="#f57f17", style=dashed]; redis -> audio_worker [color="#f57f17", style=dashed]; redis -> text_worker [color="#f57f17", style=dashed]; visual_worker -> lan_strategy [color="#f57f17", style=dashed]; audio_worker -> cloud_strategy [color="#f57f17", style=dashed]; text_worker -> cloud_strategy [color="#f57f17", style=dashed]; cloud_strategy -> speech_api [color="#f57f17", style=dashed]; lan_strategy -> yolo_adapter [color="#f57f17", style=dashed]; // Inheritance relationships (dotted) base_adapter -> webcam_adapter [style=dotted, color=gray]; base_adapter -> rtmp_adapter [style=dotted, color=gray]; base_adapter -> file_adapter [style=dotted, color=gray]; base_strategy -> local_strategy [style=dotted, color=gray]; base_strategy -> lan_strategy [style=dotted, color=gray]; base_strategy -> cloud_strategy [style=dotted, color=gray]; base_ai -> clip_adapter [style=dotted, color=gray]; base_ai -> gcp_vision [style=dotted, color=gray]; base_ai -> yolo_adapter [style=dotted, color=gray]; // Event source inheritance (NEW) base_event_source -> file_watcher_source [style=dotted, color=gray]; base_event_source -> cloud_storage_source [style=dotted, color=gray]; base_event_source -> webhook_source [style=dotted, color=gray]; }