Files
usda-vision/docs/VIDEO_STREAMING_INTEGRATION.md
Alireza Vaezi 551e5dc2e3 feat(video-streaming): Implement video streaming feature with components, hooks, services, and utilities
- Added centralized exports for video streaming components and hooks.
- Implemented `useVideoInfo` hook for fetching and managing video metadata and streaming information.
- Developed `useVideoList` hook for managing video list state, fetching, filtering, and pagination.
- Created `useVideoPlayer` hook for managing video player state and controls.
- Established `videoApiService` for handling API interactions related to video streaming.
- Defined TypeScript types for video streaming feature, including video metadata, API responses, and component props.
- Added utility functions for video operations, formatting, and data processing.
- Created main entry point for the video streaming feature, exporting all public APIs.
2025-08-04 15:02:48 -04:00

352 lines
8.5 KiB
Markdown

# 🎬 Video Streaming Integration Guide
This guide shows how to integrate the modular video streaming feature into your existing dashboard.
## 🚀 Quick Start
### 1. Add to Dashboard Navigation
Update your sidebar or navigation to include the video streaming page:
```tsx
// In src/components/Sidebar.tsx or similar
import { VideoStreamingPage } from '../features/video-streaming';
const navigationItems = [
// ... existing items
{
name: 'Video Library',
href: '/videos',
icon: VideoCameraIcon,
component: VideoStreamingPage,
},
];
```
### 2. Add Route (if using React Router)
```tsx
// In your main App.tsx or router configuration
import { VideoStreamingPage } from './features/video-streaming';
function App() {
return (
<Routes>
{/* ... existing routes */}
<Route path="/videos" element={<VideoStreamingPage />} />
</Routes>
);
}
```
## 🧩 Using Individual Components
The beauty of the modular architecture is that you can use individual components anywhere:
### Dashboard Home - Recent Videos
```tsx
// In src/components/DashboardHome.tsx
import { VideoList } from '../features/video-streaming';
export const DashboardHome = () => {
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Existing dashboard content */}
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-4">Recent Videos</h2>
<VideoList
limit={6}
filters={{ /* recent videos only */ }}
className="grid grid-cols-2 gap-4"
/>
</div>
</div>
);
};
```
### Vision System - Camera Videos
```tsx
// In src/components/VisionSystem.tsx
import { VideoList, VideoCard } from '../features/video-streaming';
export const VisionSystem = () => {
const [selectedCamera, setSelectedCamera] = useState(null);
return (
<div>
{/* Existing vision system content */}
{/* Add video section for selected camera */}
{selectedCamera && (
<div className="mt-8">
<h3 className="text-lg font-semibold mb-4">
Recent Videos - {selectedCamera}
</h3>
<VideoList
filters={{ cameraName: selectedCamera }}
limit={8}
/>
</div>
)}
</div>
);
};
```
### Experiment Data Entry - Video Evidence
```tsx
// In src/components/DataEntry.tsx
import { VideoThumbnail, VideoModal } from '../features/video-streaming';
export const DataEntry = () => {
const [selectedVideo, setSelectedVideo] = useState(null);
const [showVideoModal, setShowVideoModal] = useState(false);
return (
<form>
{/* Existing form fields */}
{/* Add video evidence section */}
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">
Video Evidence
</label>
<div className="grid grid-cols-4 gap-4">
{experimentVideos.map(video => (
<VideoThumbnail
key={video.file_id}
fileId={video.file_id}
onClick={() => {
setSelectedVideo(video);
setShowVideoModal(true);
}}
/>
))}
</div>
</div>
<VideoModal
video={selectedVideo}
isOpen={showVideoModal}
onClose={() => setShowVideoModal(false)}
/>
</form>
);
};
```
## 🎨 Customizing Components
### Custom Video Card for Experiments
```tsx
// Create a specialized version for your use case
import { VideoCard } from '../features/video-streaming';
export const ExperimentVideoCard = ({ video, experimentId, onAttach }) => {
return (
<div className="relative">
<VideoCard video={video} showMetadata={false} />
{/* Add experiment-specific actions */}
<div className="absolute top-2 right-2">
<button
onClick={() => onAttach(video.file_id, experimentId)}
className="bg-blue-500 text-white px-2 py-1 rounded text-xs"
>
Attach to Experiment
</button>
</div>
</div>
);
};
```
### Custom Video Player with Annotations
```tsx
// Extend the base video player
import { VideoPlayer } from '../features/video-streaming';
export const AnnotatedVideoPlayer = ({ fileId, annotations }) => {
return (
<div className="relative">
<VideoPlayer fileId={fileId} />
{/* Add annotation overlay */}
<div className="absolute inset-0 pointer-events-none">
{annotations.map(annotation => (
<div
key={annotation.id}
className="absolute bg-yellow-400 bg-opacity-75 p-2 rounded"
style={{
left: `${annotation.x}%`,
top: `${annotation.y}%`,
}}
>
{annotation.text}
</div>
))}
</div>
</div>
);
};
```
## 🔧 Configuration
### API Base URL
Update the API base URL if needed:
```tsx
// In your app configuration
import { VideoApiService } from './features/video-streaming';
// Create a configured instance
export const videoApi = new VideoApiService('http://your-api-server:8000');
// Or set globally
process.env.REACT_APP_VIDEO_API_URL = 'http://your-api-server:8000';
```
### Custom Styling
The components use Tailwind CSS classes. You can customize them:
```tsx
// Override default styles
<VideoList
className="grid grid-cols-1 md:grid-cols-3 gap-8" // Custom grid
/>
<VideoCard
className="border-2 border-blue-200 hover:border-blue-400" // Custom border
/>
```
## 🎯 Integration Examples
### 1. Camera Management Integration
```tsx
// In your camera management page
import { VideoList, useVideoList } from '../features/video-streaming';
export const CameraManagement = () => {
const [selectedCamera, setSelectedCamera] = useState(null);
const { videos } = useVideoList({
initialParams: { camera_name: selectedCamera?.name }
});
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Camera controls */}
<CameraControls onCameraSelect={setSelectedCamera} />
{/* Videos from selected camera */}
<div>
<h3>Videos from {selectedCamera?.name}</h3>
<VideoList
filters={{ cameraName: selectedCamera?.name }}
limit={12}
/>
</div>
</div>
);
};
```
### 2. Experiment Timeline Integration
```tsx
// Show videos in experiment timeline
import { VideoThumbnail } from '../features/video-streaming';
export const ExperimentTimeline = ({ experiment }) => {
return (
<div className="timeline">
{experiment.events.map(event => (
<div key={event.id} className="timeline-item">
<div className="timeline-content">
<h4>{event.title}</h4>
<p>{event.description}</p>
{/* Show related videos */}
{event.videos?.length > 0 && (
<div className="flex space-x-2 mt-2">
{event.videos.map(videoId => (
<VideoThumbnail
key={videoId}
fileId={videoId}
width={120}
height={80}
/>
))}
</div>
)}
</div>
</div>
))}
</div>
);
};
```
## 📱 Responsive Design
The components are designed to be responsive:
```tsx
// Automatic responsive grid
<VideoList className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4" />
// Mobile-friendly video player
<VideoPlayer
fileId={video.file_id}
className="w-full h-auto max-h-96"
/>
```
## 🔍 Search Integration
Add search functionality:
```tsx
import { useVideoList } from '../features/video-streaming';
export const VideoSearch = () => {
const [searchTerm, setSearchTerm] = useState('');
const { videos, loading } = useVideoList({
initialParams: { search: searchTerm }
});
return (
<div>
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search videos..."
className="w-full px-4 py-2 border rounded-lg"
/>
<VideoList videos={videos} loading={loading} />
</div>
);
};
```
## 🚀 Next Steps
1. **Start Small**: Begin by adding the video library page
2. **Integrate Gradually**: Add individual components to existing pages
3. **Customize**: Create specialized versions for your specific needs
4. **Extend**: Add new features like annotations, bookmarks, or sharing
The modular architecture makes it easy to start simple and grow the functionality over time!