UNPKG

media-stream-player

Version:

Player built on top of media-stream-library

124 lines 4.77 kB
import React, { useState, useEffect, useRef } from 'react'; import styled from 'styled-components'; import debug from 'debug'; import { pipelines, utils, } from 'media-stream-library'; const debugLog = debug('msp:ws-rtsp-video'); const CanvasNative = styled.canvas ` max-height: 100%; object-fit: contain; width: 100%; `; /** * Properties: * * play: indicated the _intended_ playback state * ws/rtsp: src URIs for WebSocket/RTP server * * Internal state: * canplay: there is enough data on the video element to play * playing: the video element playback is progressing */ export const WsRtspCanvas = ({ forwardedRef, play = true, ws = '', rtsp = '', onPlaying, onSdp, offset = 0, autoRetry = false, }) => { let canvasRef = useRef(null); // Forwarded refs can either be a callback or the result of useRef if (typeof forwardedRef === 'function') { forwardedRef(canvasRef.current); } else if (forwardedRef) { canvasRef = forwardedRef; } // State tied to resources const [pipeline, setPipeline] = useState(null); const [fetching, setFetching] = useState(false); // keep track of changes in starting time // (offset in seconds to start playing from) const __offsetRef = useRef(offset); const __rangeRef = useRef([offset, undefined]); useEffect(() => { __offsetRef.current = offset; const canvas = canvasRef.current; if (ws && rtsp && canvas) { debugLog('create pipeline'); const newPipeline = new pipelines.Html5CanvasPipeline({ ws: { uri: ws }, rtsp: { uri: rtsp }, mediaElement: canvas, }); if (autoRetry) { utils.addRTSPRetry(newPipeline.rtsp); } setPipeline(newPipeline); return () => { debugLog('destroy pipeline'); newPipeline.pause(); newPipeline.close(); setPipeline(null); setFetching(false); debugLog('canvas cleared'); }; } }, [ws, rtsp, offset, autoRetry]); // keep a stable reference to the external onPlaying callback const __onPlayingRef = useRef(onPlaying); __onPlayingRef.current = onPlaying; // keep a stable reference to the external SDP handler const __onSdpRef = useRef(onSdp); __onSdpRef.current = onSdp; const __sensorTmRef = useRef(); useEffect(() => { if (play && pipeline && !fetching) { pipeline.ready .then(() => { debugLog('fetch'); pipeline.onSdp = (sdp) => { var _a; const videoMedia = sdp.media.find((m) => { return m.type === 'video'; }); if (videoMedia !== undefined) { __sensorTmRef.current = (_a = videoMedia['x-sensor-transform']) !== null && _a !== void 0 ? _a : videoMedia['transform']; } if (__onSdpRef.current !== undefined) { __onSdpRef.current(sdp); } }; pipeline.rtsp.onPlay = (range) => { if (range !== undefined) { __rangeRef.current = [ parseFloat(range[0]) || 0, parseFloat(range[1]) || undefined, ]; } }; pipeline.rtsp.play(__offsetRef.current); setFetching(true); }) .catch(console.error); } else if (play && pipeline !== null) { debugLog('play'); pipeline.play(); // Callback `onCanPlay` is called when the canvas element is ready to // play. We need to wait for that event to get the correct width/height. pipeline.onCanplay = () => { if (canvasRef.current !== null && __onPlayingRef.current !== undefined) { __onPlayingRef.current({ el: canvasRef.current, width: canvasRef.current.width, height: canvasRef.current.height, range: __rangeRef.current, sensorTm: __sensorTmRef.current, }); } }; } else if (!play && pipeline) { debugLog('pause'); pipeline.pause(); } }, [play, pipeline, fetching]); return React.createElement(CanvasNative, { ref: canvasRef }); }; //# sourceMappingURL=WsRtspCanvas.js.map