JSPM

react-webrtc-viewer

1.0.4
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 18
    • Score
      100M100P100Q47449F
    • License MIT

    A React component for WebRTC streaming with WHEP protocol support, featuring zoom/pan functionality and customizable UI

    Package Exports

    • react-webrtc-viewer

    Readme

    React WebRTC Viewer

    CI npm version npm downloads License: MIT

    A React component for WebRTC live streaming with WHEP (WebRTC-HTTP Egress Protocol) support, featuring built-in zoom/pan functionality and customizable UI components.

    Installation

    npm install react-webrtc-viewer

    Dependencies

    This package requires the following peer dependencies:

    npm install react react-dom video.js whip-whep

    Basic Usage

    import WhepPlayer from "react-webrtc-viewer";
    
    function App() {
      return (
        <WhepPlayer
          url="https://example.com/live/stream/whep"
          onReady={(player) => console.log("Player ready:", player)}
          onError={(error) => console.error("Stream error:", error)}
        />
      );
    }

    Features

    • WebRTC WHEP streaming with automatic error handling and reconnection
    • Zoom and Pan functionality for interactive video viewing
    • Customizable UI components for loading, error, and reconnecting states
    • Event callbacks for stream lifecycle management
    • TypeScript support with full type definitions

    Props

    Basic Props

    Prop Type Default Description
    url string required WHEP stream URL
    options object {} Video.js player options
    className string "" Additional CSS class name

    Event Callbacks

    Prop Type Description
    onReady (player) => void Called when player is ready
    onError (error) => void Called on general errors
    onStreamNotFound (event) => void Called when stream returns 404
    onStreamRecovered (event) => void Called when stream recovers
    onStreamConnected (event) => void Called when stream connects
    onStreamDisconnected (event) => void Called when stream disconnects
    onForbidden (event) => void Called on 403 errors
    onServerError (event) => void Called on 500 errors

    Zoom/Pan Props

    Prop Type Default Description
    enableZoomPan boolean false Enable zoom and pan functionality
    maxZoom number 10 Maximum zoom level
    zoomStep number 0.05 Zoom step per scroll

    Custom UI Props

    Prop Type Description
    renderLoading () => ReactNode Custom loading spinner component
    renderError ({ error, onRetry }) => ReactNode Custom error display component
    renderReconnecting () => ReactNode Custom reconnecting display component
    customSpinnerCSS string Custom CSS for Video.js internal spinner
    messages object Custom messages for internationalization

    Advanced Usage

    With Zoom/Pan

    <WhepPlayer
      url="https://example.com/live/stream/whep"
      enableZoomPan={true}
      maxZoom={5}
      zoomStep={0.1}
      onReady={(player) => console.log("Player ready")}
    />

    With Custom UI Components

    <WhepPlayer
      url="https://example.com/live/stream/whep"
      renderLoading={() => <div>Custom loading...</div>}
      renderError={({ error, onRetry }) => (
        <div>
          <h3>Oops! {error}</h3>
          <button onClick={onRetry}>Try Again</button>
        </div>
      )}
      renderReconnecting={() => <div>Reconnecting to stream...</div>}
    />

    With Custom Video.js Spinner

    Customize the internal Video.js loading spinner:

    <WhepPlayer
      url="https://example.com/live/stream/whep"
      customSpinnerCSS={`
        .video-js .vjs-custom-spinner::after {
          border: 6px solid #f3f3f3;
          border-top: 6px solid #ff6b6b;
          width: 60px;
          height: 60px;
          animation: vjs-spin 1s linear infinite;
        }
        
        .video-js .vjs-custom-spinner {
          width: 60px;
          height: 60px;
        }
        
        @keyframes vjs-pulse {
          0% { opacity: 1; }
          50% { opacity: 0.5; }
          100% { opacity: 1; }
        }
        
        /* Add pulsing effect */
        .video-js .vjs-custom-spinner::before {
          content: '📺';
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          font-size: 20px;
          animation: vjs-pulse 1.5s ease-in-out infinite;
        }
      `}
    />

    With Internationalization (i18n)

    Customize all text messages for different languages:

    // English (default)
    const englishMessages = {
      loading: "Loading stream...",
      reconnecting: "Reconnecting...",
      streamError: "Stream Error",
      retry: "Retry",
      accessForbidden: "Stream access forbidden (403)",
      serverError: "Server error (500)",
      whepUrlRequired: "WHEP URL is required",
      failedToInitialize: "Failed to initialize WHEP stream",
    };
    
    // Spanish
    const spanishMessages = {
      loading: "Cargando transmisión...",
      reconnecting: "Reconectando...",
      streamError: "Error de Transmisión",
      retry: "Reintentar",
      accessForbidden: "Acceso a la transmisión prohibido (403)",
      serverError: "Error del servidor (500)",
      whepUrlRequired: "Se requiere URL WHEP",
      failedToInitialize: "Error al inicializar transmisión WHEP",
    };
    
    // French
    const frenchMessages = {
      loading: "Chargement du flux...",
      reconnecting: "Reconnexion...",
      streamError: "Erreur de Flux",
      retry: "Réessayer",
      accessForbidden: "Accès au flux interdit (403)",
      serverError: "Erreur du serveur (500)",
      whepUrlRequired: "URL WHEP requise",
      failedToInitialize: "Échec de l'initialisation du flux WHEP",
    };
    
    function App() {
      return (
        <WhepPlayer
          url="https://example.com/live/stream/whep"
          messages={spanishMessages}
        />
      );
    }

    Integration with i18n Libraries

    import { useTranslation } from "react-i18next";
    import WhepPlayer from "react-webrtc-viewer";
    
    function I18nPlayer() {
      const { t } = useTranslation();
    
      const messages = {
        loading: t("player.loading"),
        reconnecting: t("player.reconnecting"),
        streamError: t("player.streamError"),
        retry: t("player.retry"),
        accessForbidden: t("player.accessForbidden"),
        serverError: t("player.serverError"),
      };
    
      return (
        <WhepPlayer url="http://localhost/live/stream1/whep" messages={messages} />
      );
    }

    Dynamic Language Switching

    import { useState } from "react";
    import WhepPlayer from "react-webrtc-viewer";
    
    const translations = {
      en: {
        loading: "Loading stream...",
        reconnecting: "Reconnecting...",
        streamError: "Stream Error",
        retry: "Retry",
      },
      es: {
        loading: "Cargando transmisión...",
        reconnecting: "Reconectando...",
        streamError: "Error de Transmisión",
        retry: "Reintentar",
      },
      fr: {
        loading: "Chargement du flux...",
        reconnecting: "Reconnexion...",
        streamError: "Erreur de Flux",
        retry: "Réessayer",
      },
    };
    
    function MultiLanguagePlayer() {
      const [language, setLanguage] = useState("en");
    
      return (
        <div>
          <select
            value={language}
            onChange={(e) => setLanguage(e.target.value)}
            style={{ marginBottom: "10px" }}
          >
            <option value="en">English</option>
            <option value="es">Español</option>
            <option value="fr">Français</option>
          </select>
    
          <WhepPlayer
            url="https://example.com/live/stream/whep"
            messages={translations[language]}
          />
        </div>
      );
    }

    RTL Language Support

    const arabicMessages = {
      loading: "جاري تحميل البث...",
      reconnecting: "إعادة الاتصال...",
      streamError: "خطأ في البث",
      retry: "إعادة المحاولة",
      accessForbidden: "الوصول للبث محظور (403)",
      serverError: "خطأ في الخادم (500)",
    };
    
    function ArabicPlayer() {
      return (
        <div dir="rtl">
          <WhepPlayer
            url="http://localhost/live/stream1/whep"
            messages={arabicMessages}
            className="rtl-player"
          />
        </div>
      );
    }

    Full Event Handling

    <WhepPlayer
      url="https://example.com/live/stream/whep"
      onStreamConnected={() => console.log("Stream started")}
      onStreamNotFound={() => console.log("Stream not available")}
      onStreamRecovered={() => console.log("Stream is back online")}
      onStreamDisconnected={() => console.log("Stream disconnected")}
      onForbidden={() => console.log("Access denied")}
      onServerError={() => console.log("Server error")}
    />

    Available Message Keys

    For internationalization, you can customize the following message keys:

    Key Default Value Description
    loading "Loading stream..." Loading spinner text
    reconnecting "Reconnecting..." Reconnecting state text
    streamError "Stream Error" Error dialog title
    retry "Retry" Retry button text
    accessForbidden "Stream access forbidden (403)" 403 error message
    serverError "Server error (500)" 500 error message
    whepUrlRequired "WHEP URL is required" Missing URL error
    failedToInitialize "Failed to initialize WHEP stream" Initialization error
    videoPlayerError "Video player error" General player error
    connectionLost "Connection lost" Connection failure message

    Default Components

    The library exports default components that you can use independently:

    import { DefaultLoadingSpinner, DefaultErrorDisplay } from 'react-webrtc-viewer';
    
    // Use the default components in your own layouts
    <DefaultLoadingSpinner message="Please wait..." />
    <DefaultErrorDisplay
      error="Connection failed"
      onRetry={() => window.location.reload()}
    />

    License

    MIT