package camera import ( "fmt" "sync" ) type CameraInfo struct { ID string `json:"id"` Name string `json:"name"` Index int `json:"index"` Width int `json:"width"` Height int `json:"height"` } type Manager struct { ffmpegCam *FFmpegCamera isOpen bool mu sync.Mutex } func NewManager() *Manager { return &Manager{} } func (m *Manager) ListCameras() []CameraInfo { // Try to detect real cameras via ffmpeg (auto-detects OS) devices := ListFFmpegDevices() if len(devices) > 0 { return devices } if !DetectFFmpeg() { fmt.Println("[WARN] ffmpeg not found — install with: brew install ffmpeg (macOS) or winget install ffmpeg (Windows)") } else { fmt.Println("[WARN] No video devices detected by ffmpeg") } return []CameraInfo{} } func (m *Manager) Open(index, width, height int) error { m.mu.Lock() defer m.mu.Unlock() // Try real camera via ffmpeg if !DetectFFmpeg() { return fmt.Errorf("ffmpeg not found — install with: brew install ffmpeg (macOS) or winget install ffmpeg (Windows)") } cam, err := NewFFmpegCamera(index, width, height, 30) if err != nil { return fmt.Errorf("failed to open camera (index=%d): %w", index, err) } m.ffmpegCam = cam m.isOpen = true fmt.Printf("[INFO] Opened real camera (index=%d) via ffmpeg\n", index) return nil } func (m *Manager) Close() error { m.mu.Lock() defer m.mu.Unlock() if m.ffmpegCam != nil { _ = m.ffmpegCam.Close() m.ffmpegCam = nil } m.isOpen = false return nil } func (m *Manager) ReadFrame() ([]byte, error) { m.mu.Lock() defer m.mu.Unlock() if !m.isOpen { return nil, fmt.Errorf("camera not open") } if m.ffmpegCam != nil { return m.ffmpegCam.ReadFrame() } return nil, fmt.Errorf("no camera available") } func (m *Manager) IsOpen() bool { m.mu.Lock() defer m.mu.Unlock() return m.isOpen }