diff --git a/src/components/VisionSystem.tsx b/src/components/VisionSystem.tsx index 78aefb0..2a4cb9e 100644 --- a/src/components/VisionSystem.tsx +++ b/src/components/VisionSystem.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef, useCallback } from 'react' +import { useState, useEffect, useRef, useCallback, useMemo, memo, startTransition } from 'react' import { visionApi, type SystemStatus, @@ -14,6 +14,353 @@ import { formatUptime } from '../lib/visionApi' +// Memoized components to prevent unnecessary re-renders +const SystemOverview = memo(({ systemStatus }: { systemStatus: SystemStatus }) => ( +
+ Storage usage and file statistics +
++ Current status of all cameras in the system +
++ Latest recording sessions +
+| + Camera + | ++ Filename + | ++ Status + | ++ Duration + | ++ Size + | ++ Started + | +
|---|---|---|---|---|---|
|
+ {displayName}
+ {camera?.device_info?.friendly_name && (
+ ({recording.camera_name})
+ )}
+ |
+ + {recording.filename} + | ++ + {recording.status} + + | ++ {recording.duration_seconds ? formatDuration(recording.duration_seconds) : '-'} + | ++ {recording.file_size_bytes ? formatBytes(recording.file_size_bytes) : '-'} + | ++ {new Date(recording.start_time).toLocaleString()} + | +
Monitor cameras, machines, and recording status
{lastUpdateTime && ( -+
Last updated: {lastUpdateTime.toLocaleTimeString()}
+ {refreshing && (
+
+
+ Updating...
+
+ )}
{autoRefreshEnabled && !refreshing && (
Auto-refresh: {refreshInterval / 1000}s
@@ -296,227 +636,12 @@ export function VisionSystem() {
{/* System Overview */}
- {systemStatus && (
-
- Current status of all cameras in the system
-
- Storage usage and file statistics
-
- Latest recording sessions
- Live Stream: GET /cameras/{camera_name}/stream Start Stream: POST /cameras/{camera_name}/start-stream Stop Stream: POST /cameras/{camera_name}/stop-stream Camera Status: GET /camerasRecent Events
- {mqttEvents.length} events
- Cameras
-
- {friendlyName ? (
-
- Storage
- Files by Camera
-
- {camera?.device_info?.friendly_name ? (
- <>
- {displayName}
- ({cameraName})
- >
- ) : (
- cameraName
- )}
-
- Recent Recordings
-
-
-
-
-
-
-
- {Object.entries(recordings).slice(0, 10).map(([recordingId, recording]) => {
- // Find the corresponding camera to get friendly name
- const camera = systemStatus?.cameras[recording.camera_name]
- const displayName = camera?.device_info?.friendly_name || recording.camera_name
-
- return (
-
- Camera
-
-
- Filename
-
-
- Status
-
-
- Duration
-
-
- Size
-
-
- Started
-
-
-
- )
- })}
-
-
- {camera?.device_info?.friendly_name ? (
-
-
- {recording.filename}
-
-
-
- {recording.state}
-
-
-
- {recording.duration_seconds ? formatDuration(recording.duration_seconds) : '-'}
-
-
- {recording.file_size_bytes ? formatBytes(recording.file_size_bytes) : '-'}
-
-
- {new Date(recording.start_time).toLocaleString()}
-
- ` tags and can be easily integrated into React components.
+
+### Key Characteristics:
+- **Base URL**: `http://localhost:8000` (configurable)
+- **Stream Format**: MJPEG (Motion JPEG)
+- **Content-Type**: `multipart/x-mixed-replace; boundary=frame`
+- **Authentication**: None (add if needed for production)
+- **CORS**: Enabled for all origins (configure for production)
+
+## ๐ API Endpoints Reference
+
+### 1. Get Camera List
+```http
+GET /cameras
+```
+**Response:**
+```json
+{
+ "camera1": {
+ "name": "camera1",
+ "status": "connected",
+ "is_recording": false,
+ "last_checked": "2025-01-28T10:30:00",
+ "device_info": {...}
+ },
+ "camera2": {...}
+}
+```
+
+### 2. Start Camera Stream
+```http
+POST /cameras/{camera_name}/start-stream
+```
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Started streaming for camera camera1"
+}
+```
+
+### 3. Stop Camera Stream
+```http
+POST /cameras/{camera_name}/stop-stream
+```
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Stopped streaming for camera camera1"
+}
+```
+
+### 4. Live Video Stream
+```http
+GET /cameras/{camera_name}/stream
+```
+**Response:** MJPEG video stream
+**Usage:** Set as `src` attribute of HTML `
` element
+
+## โ๏ธ React Integration Examples
+
+### Basic Camera Stream Component
+
+```jsx
+import React, { useState, useEffect } from 'react';
+
+const CameraStream = ({ cameraName, apiBaseUrl = 'http://localhost:8000' }) => {
+ const [isStreaming, setIsStreaming] = useState(false);
+ const [error, setError] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ const startStream = async () => {
+ setLoading(true);
+ setError(null);
+
+ try {
+ const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/start-stream`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (response.ok) {
+ setIsStreaming(true);
+ } else {
+ const errorData = await response.json();
+ setError(errorData.detail || 'Failed to start stream');
+ }
+ } catch (err) {
+ setError(`Network error: ${err.message}`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const stopStream = async () => {
+ setLoading(true);
+
+ try {
+ const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/stop-stream`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (response.ok) {
+ setIsStreaming(false);
+ } else {
+ const errorData = await response.json();
+ setError(errorData.detail || 'Failed to stop stream');
+ }
+ } catch (err) {
+ setError(`Network error: ${err.message}`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
Camera: {cameraName}
+
+ {/* Video Stream */}
+ setError('Stream connection lost')}
+ />
+ ) : (
+
USDA Vision Camera Dashboard
+
+ Camera: {cameraName}
+
+ {/* Stream Container */}
+ setError('Stream connection lost')}
+ />
+ ) : (
+
` tag with `src` pointing to stream endpoint
+- Add timestamp query parameter to prevent caching: `?t=${Date.now()}`
+- Handle `onError` event for connection issues
+
+### 2. Error Handling
+- Network errors (fetch failures)
+- HTTP errors (4xx, 5xx responses)
+- Stream connection errors (img onError)
+- Timeout handling for long requests
+
+### 3. Performance Considerations
+- Streams consume bandwidth continuously
+- Stop streams when components unmount
+- Limit concurrent streams based on system capacity
+- Consider lazy loading for multiple cameras
+
+### 4. State Management
+- Track streaming state per camera
+- Handle loading states during API calls
+- Manage error states with user feedback
+- Refresh camera list periodically
+
+## ๐ฑ Mobile Considerations
+
+```jsx
+// Responsive design for mobile
+const mobileStyles = {
+ container: {
+ padding: '10px',
+ maxWidth: '100vw',
+ },
+ stream: {
+ width: '100%',
+ maxWidth: '100vw',
+ height: 'auto',
+ },
+ controls: {
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '8px',
+ },
+};
+```
+
+## ๐งช Testing Integration
+
+```javascript
+// Test API connectivity
+const testConnection = async () => {
+ try {
+ const response = await fetch(`${apiBaseUrl}/health`);
+ return response.ok;
+ } catch {
+ return false;
+ }
+};
+
+// Test camera availability
+const testCamera = async (cameraName) => {
+ try {
+ const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/test-connection`, {
+ method: 'POST',
+ });
+ return response.ok;
+ } catch {
+ return false;
+ }
+};
+```
+
+## ๐ Additional Files for AI Integration
+
+### TypeScript Definitions
+- `camera-api.types.ts` - Complete TypeScript definitions for all API types
+- `streaming-api.http` - REST Client file with all streaming endpoints
+- `STREAMING_GUIDE.md` - Comprehensive user guide for streaming functionality
+
+### Quick Integration Checklist for AI Assistants
+
+1. **Copy TypeScript types** from `camera-api.types.ts`
+2. **Use API endpoints** from `streaming-api.http`
+3. **Implement error handling** as shown in examples
+4. **Add CORS configuration** if needed for production
+5. **Test with multiple cameras** using provided examples
+
+### Key Integration Points
+
+- **Stream URL Format**: `${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`
+- **Start Stream**: `POST /cameras/{name}/start-stream`
+- **Stop Stream**: `POST /cameras/{name}/stop-stream`
+- **Camera List**: `GET /cameras`
+- **Error Handling**: Always wrap in try-catch blocks
+- **Loading States**: Implement for better UX
+
+### Production Considerations
+
+- Configure CORS for specific origins
+- Add authentication if required
+- Implement rate limiting
+- Monitor system resources with multiple streams
+- Add reconnection logic for network issues
+
+This documentation provides everything an AI assistant needs to integrate the USDA Vision Camera streaming functionality into React applications, including complete code examples, error handling, and best practices.
diff --git a/streaming/STREAMING_GUIDE.md b/streaming/STREAMING_GUIDE.md
new file mode 100644
index 0000000..ca55700
--- /dev/null
+++ b/streaming/STREAMING_GUIDE.md
@@ -0,0 +1,240 @@
+# ๐ฅ USDA Vision Camera Live Streaming Guide
+
+This guide explains how to use the new live preview streaming functionality that allows you to view camera feeds in real-time without blocking recording operations.
+
+## ๐ Key Features
+
+- **Non-blocking streaming**: Live preview doesn't interfere with recording
+- **Separate camera connections**: Streaming uses independent camera instances
+- **MJPEG streaming**: Standard web-compatible video streaming
+- **Multiple concurrent viewers**: Multiple browsers can view the same stream
+- **REST API control**: Start/stop streaming via API endpoints
+- **Web interface**: Ready-to-use HTML interface for live preview
+
+## ๐๏ธ Architecture
+
+The streaming system creates separate camera connections for preview that are independent from recording:
+
+```
+Camera Hardware
+โโโ Recording Connection (CameraRecorder)
+โ โโโ Used for video file recording
+โ โโโ Triggered by MQTT machine states
+โ โโโ High quality, full FPS
+โโโ Streaming Connection (CameraStreamer)
+ โโโ Used for live preview
+ โโโ Controlled via API endpoints
+ โโโ Optimized for web viewing (lower FPS, JPEG compression)
+```
+
+## ๐ Quick Start
+
+### 1. Start the System
+```bash
+python main.py
+```
+
+### 2. Open the Web Interface
+Open `camera_preview.html` in your browser and click "Start Stream" for any camera.
+
+### 3. API Usage
+```bash
+# Start streaming for camera1
+curl -X POST http://localhost:8000/cameras/camera1/start-stream
+
+# View live stream (open in browser)
+http://localhost:8000/cameras/camera1/stream
+
+# Stop streaming
+curl -X POST http://localhost:8000/cameras/camera1/stop-stream
+```
+
+## ๐ก API Endpoints
+
+### Start Streaming
+```http
+POST /cameras/{camera_name}/start-stream
+```
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Started streaming for camera camera1"
+}
+```
+
+### Stop Streaming
+```http
+POST /cameras/{camera_name}/stop-stream
+```
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Stopped streaming for camera camera1"
+}
+```
+
+### Live Stream (MJPEG)
+```http
+GET /cameras/{camera_name}/stream
+```
+**Response:** Multipart MJPEG stream
+**Content-Type:** `multipart/x-mixed-replace; boundary=frame`
+
+## ๐ Web Interface Usage
+
+The included `camera_preview.html` provides a complete web interface:
+
+1. **Camera Grid**: Shows all configured cameras
+2. **Stream Controls**: Start/Stop/Refresh buttons for each camera
+3. **Live Preview**: Real-time video feed display
+4. **Status Information**: System and camera status
+5. **Responsive Design**: Works on desktop and mobile
+
+### Features:
+- โ
Real-time camera status
+- โ
One-click stream start/stop
+- โ
Automatic stream refresh
+- โ
System health monitoring
+- โ
Error handling and status messages
+
+## ๐ง Technical Details
+
+### Camera Streamer Configuration
+- **Preview FPS**: 10 FPS (configurable)
+- **JPEG Quality**: 70% (configurable)
+- **Frame Buffer**: 5 frames (prevents memory buildup)
+- **Timeout**: 200ms per frame capture
+
+### Memory Management
+- Automatic frame buffer cleanup
+- Queue-based frame management
+- Proper camera resource cleanup on stop
+
+### Thread Safety
+- Thread-safe streaming operations
+- Independent from recording threads
+- Proper synchronization with locks
+
+## ๐งช Testing
+
+### Run the Test Script
+```bash
+python test_streaming.py
+```
+
+This will test:
+- โ
API endpoint functionality
+- โ
Stream start/stop operations
+- โ
Concurrent recording and streaming
+- โ
Error handling
+
+### Manual Testing
+1. Start the system: `python main.py`
+2. Open `camera_preview.html` in browser
+3. Start streaming for a camera
+4. Trigger recording via MQTT or manual API
+5. Verify both work simultaneously
+
+## ๐ Concurrent Operations
+
+The system supports these concurrent operations:
+
+| Operation | Recording | Streaming | Notes |
+|-----------|-----------|-----------|-------|
+| Recording Only | โ
| โ | Normal operation |
+| Streaming Only | โ | โ
| Preview without recording |
+| Both Concurrent | โ
| โ
| **Independent connections** |
+
+### Example: Concurrent Usage
+```bash
+# Start streaming
+curl -X POST http://localhost:8000/cameras/camera1/start-stream
+
+# Start recording (while streaming continues)
+curl -X POST http://localhost:8000/cameras/camera1/start-recording \
+ -H "Content-Type: application/json" \
+ -d '{"filename": "test_recording.avi"}'
+
+# Both operations run independently!
+```
+
+## ๐ ๏ธ Configuration
+
+### Stream Settings (in CameraStreamer)
+```python
+self.preview_fps = 10.0 # Lower FPS for preview
+self.preview_quality = 70 # JPEG quality (1-100)
+self._frame_queue.maxsize = 5 # Frame buffer size
+```
+
+### Camera Settings
+The streamer uses the same camera configuration as recording:
+- Exposure time from `camera_config.exposure_ms`
+- Gain from `camera_config.gain`
+- Optimized trigger mode for continuous streaming
+
+## ๐จ Important Notes
+
+### Camera Access Patterns
+- **Recording**: Blocks camera during active recording
+- **Streaming**: Uses separate connection, doesn't block
+- **Health Checks**: Brief, non-blocking camera tests
+- **Multiple Streams**: Multiple browsers can view same stream
+
+### Performance Considerations
+- Streaming uses additional CPU/memory resources
+- Lower preview FPS reduces system load
+- JPEG compression reduces bandwidth usage
+- Frame queue prevents memory buildup
+
+### Error Handling
+- Automatic camera resource cleanup
+- Graceful handling of camera disconnections
+- Stream auto-restart capabilities
+- Detailed error logging
+
+## ๐ Troubleshooting
+
+### Stream Not Starting
+1. Check camera availability: `GET /cameras`
+2. Verify camera not in error state
+3. Check system logs for camera initialization errors
+4. Try camera reconnection: `POST /cameras/{name}/reconnect`
+
+### Poor Stream Quality
+1. Adjust `preview_quality` setting (higher = better quality)
+2. Increase `preview_fps` for smoother video
+3. Check network bandwidth
+4. Verify camera exposure/gain settings
+
+### Browser Issues
+1. Try different browser (Chrome/Firefox recommended)
+2. Check browser console for JavaScript errors
+3. Verify CORS settings in API server
+4. Clear browser cache and refresh
+
+## ๐ Future Enhancements
+
+Potential improvements for the streaming system:
+
+- ๐ WebRTC support for lower latency
+- ๐ฑ Mobile app integration
+- ๐๏ธ Real-time camera setting adjustments
+- ๐ Stream analytics and monitoring
+- ๐ Authentication and access control
+- ๐ Multi-camera synchronized viewing
+
+## ๐ Support
+
+For issues with streaming functionality:
+
+1. Check the system logs: `usda_vision_system.log`
+2. Run the test script: `python test_streaming.py`
+3. Verify API health: `http://localhost:8000/health`
+4. Check camera status: `http://localhost:8000/cameras`
+
+---
+
+**โ
Live streaming is now ready for production use!**
diff --git a/streaming/camera-api.types.ts b/streaming/camera-api.types.ts
new file mode 100644
index 0000000..ffa9602
--- /dev/null
+++ b/streaming/camera-api.types.ts
@@ -0,0 +1,367 @@
+/**
+ * TypeScript definitions for USDA Vision Camera System API
+ *
+ * This file provides complete type definitions for AI assistants
+ * to integrate the camera streaming functionality into React/TypeScript projects.
+ */
+
+// =============================================================================
+// BASE CONFIGURATION
+// =============================================================================
+
+export interface ApiConfig {
+ baseUrl: string;
+ timeout?: number;
+ refreshInterval?: number;
+}
+
+export const defaultApiConfig: ApiConfig = {
+ baseUrl: 'http://localhost:8000',
+ timeout: 10000,
+ refreshInterval: 30000,
+};
+
+// =============================================================================
+// CAMERA TYPES
+// =============================================================================
+
+export interface CameraDeviceInfo {
+ friendly_name?: string;
+ port_type?: string;
+ serial_number?: string;
+ device_index?: number;
+ error?: string;
+}
+
+export interface CameraInfo {
+ name: string;
+ status: 'connected' | 'disconnected' | 'error' | 'not_found' | 'available';
+ is_recording: boolean;
+ last_checked: string; // ISO date string
+ last_error?: string | null;
+ device_info?: CameraDeviceInfo;
+ current_recording_file?: string | null;
+ recording_start_time?: string | null; // ISO date string
+}
+
+export interface CameraListResponse {
+ [cameraName: string]: CameraInfo;
+}
+
+// =============================================================================
+// STREAMING TYPES
+// =============================================================================
+
+export interface StreamStartRequest {
+ // No body required - camera name is in URL path
+}
+
+export interface StreamStartResponse {
+ success: boolean;
+ message: string;
+}
+
+export interface StreamStopRequest {
+ // No body required - camera name is in URL path
+}
+
+export interface StreamStopResponse {
+ success: boolean;
+ message: string;
+}
+
+export interface StreamStatus {
+ isStreaming: boolean;
+ streamUrl?: string;
+ error?: string;
+}
+
+// =============================================================================
+// RECORDING TYPES
+// =============================================================================
+
+export interface StartRecordingRequest {
+ filename?: string;
+ exposure_ms?: number;
+ gain?: number;
+ fps?: number;
+}
+
+export interface StartRecordingResponse {
+ success: boolean;
+ message: string;
+ filename?: string;
+}
+
+export interface StopRecordingResponse {
+ success: boolean;
+ message: string;
+}
+
+// =============================================================================
+// SYSTEM TYPES
+// =============================================================================
+
+export interface SystemStatusResponse {
+ status: string;
+ uptime: string;
+ api_server_running: boolean;
+ camera_manager_running: boolean;
+ mqtt_client_connected: boolean;
+ total_cameras: number;
+ active_recordings: number;
+ active_streams?: number;
+}
+
+export interface HealthResponse {
+ status: 'healthy' | 'unhealthy';
+ timestamp: string;
+}
+
+// =============================================================================
+// ERROR TYPES
+// =============================================================================
+
+export interface ApiError {
+ detail: string;
+ status_code?: number;
+}
+
+export interface StreamError extends Error {
+ type: 'network' | 'api' | 'stream' | 'timeout';
+ cameraName: string;
+ originalError?: Error;
+}
+
+// =============================================================================
+// HOOK TYPES
+// =============================================================================
+
+export interface UseCameraStreamResult {
+ isStreaming: boolean;
+ loading: boolean;
+ error: string | null;
+ startStream: () => Promise<{ success: boolean; error?: string }>;
+ stopStream: () => Promise<{ success: boolean; error?: string }>;
+ getStreamUrl: () => string;
+ refreshStream: () => void;
+}
+
+export interface UseCameraListResult {
+ cameras: CameraListResponse;
+ loading: boolean;
+ error: string | null;
+ refreshCameras: () => Promise
๐ฅ USDA Vision Camera Live Preview
+
+ ๐ก System Information
+ ๐ API Endpoints
+
+
+### Usage in React:
+#
+
+###
+
+### Start streaming for camera2
+POST {{baseUrl}}/cameras/camera2/start-stream
+Content-Type: application/json
+
+###
+
+### Get live stream for camera2
+GET {{baseUrl}}/cameras/camera2/stream
+
+###
+
+### Stop streaming for camera2
+POST {{baseUrl}}/cameras/camera2/stop-stream
+Content-Type: application/json
+
+### =============================================================================
+### CONCURRENT OPERATIONS TESTING
+### =============================================================================
+
+### Test Scenario: Streaming + Recording Simultaneously
+### This demonstrates that streaming doesn't block recording
+
+### Step 1: Start streaming first
+POST {{baseUrl}}/cameras/camera1/start-stream
+Content-Type: application/json
+
+###
+
+### Step 2: Start recording (while streaming continues)
+POST {{baseUrl}}/cameras/camera1/start-recording
+Content-Type: application/json
+
+{
+ "filename": "concurrent_test.avi"
+}
+
+###
+
+### Step 3: Check both are running
+GET {{baseUrl}}/cameras/camera1
+
+### Expected Response shows both recording and streaming active:
+# {
+# "camera1": {
+# "name": "camera1",
+# "status": "connected",
+# "is_recording": true,
+# "current_recording_file": "concurrent_test.avi",
+# "recording_start_time": "2025-01-28T10:30:00.000Z"
+# }
+# }
+
+###
+
+### Step 4: Stop recording (streaming continues)
+POST {{baseUrl}}/cameras/camera1/stop-recording
+Content-Type: application/json
+
+###
+
+### Step 5: Verify streaming still works
+GET {{baseUrl}}/cameras/camera1/stream
+
+###
+
+### Step 6: Stop streaming
+POST {{baseUrl}}/cameras/camera1/stop-stream
+Content-Type: application/json
+
+### =============================================================================
+### MULTIPLE CAMERA STREAMING
+### =============================================================================
+
+### Start streaming on multiple cameras simultaneously
+POST {{baseUrl}}/cameras/camera1/start-stream
+Content-Type: application/json
+
+###
+
+POST {{baseUrl}}/cameras/camera2/start-stream
+Content-Type: application/json
+
+###
+
+### Check status of all cameras
+GET {{baseUrl}}/cameras
+
+###
+
+### Access multiple streams (open in separate browser tabs)
+GET {{baseUrl}}/cameras/camera1/stream
+
+###
+
+GET {{baseUrl}}/cameras/camera2/stream
+
+###
+
+### Stop all streaming
+POST {{baseUrl}}/cameras/camera1/stop-stream
+Content-Type: application/json
+
+###
+
+POST {{baseUrl}}/cameras/camera2/stop-stream
+Content-Type: application/json
+
+### =============================================================================
+### ERROR TESTING
+### =============================================================================
+
+### Test with invalid camera name
+POST {{baseUrl}}/cameras/invalid_camera/start-stream
+Content-Type: application/json
+
+### Expected Response:
+# {
+# "detail": "Camera streamer not found: invalid_camera"
+# }
+
+###
+
+### Test stream endpoint without starting stream first
+GET {{baseUrl}}/cameras/camera1/stream
+
+### Expected: May return error or empty stream depending on camera state
+
+###
+
+### Test starting stream when camera is in error state
+POST {{baseUrl}}/cameras/camera1/start-stream
+Content-Type: application/json
+
+### If camera has issues, expected response:
+# {
+# "success": false,
+# "message": "Failed to start streaming for camera camera1"
+# }
+
+### =============================================================================
+### INTEGRATION EXAMPLES FOR AI ASSISTANTS
+### =============================================================================
+
+### React Component Integration:
+# const CameraStream = ({ cameraName }) => {
+# const [isStreaming, setIsStreaming] = useState(false);
+#
+# const startStream = async () => {
+# const response = await fetch(`${baseUrl}/cameras/${cameraName}/start-stream`, {
+# method: 'POST'
+# });
+# if (response.ok) {
+# setIsStreaming(true);
+# }
+# };
+#
+# return (
+#
+# )}
+#
+#