Files
usda-vision/web/docs/VIDEO_STREAMING_INTEGRATION.md
Alireza Vaezi 0b0e575080 Add 'web/' from commit '81828f61cf893039b89d3cf1861555f31167c37d'
git-subtree-dir: web
git-subtree-mainline: 7dbb36d619
git-subtree-split: 81828f61cf
2025-08-07 20:57:47 -04:00

8.5 KiB

🎬 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:

// 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)

// 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

// 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

// 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

// 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

// 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

// 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:

// 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:

// 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

// 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

// 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:

// 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:

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!