javascriptreactjshttp-live-streaminghls.jsplyr.js

Uncaught DOMException on route change hls.js React.js


I use plyr.js to create a video player.
Caught an error with hls.js:

Uncaught DOMException: Failed to read the 'buffered' property from 'SourceBuffer': 
This SourceBuffer has been removed from the parent media source.

It happens when I change video src on route change.

My player:

import React from 'react'
import HLS from 'hls.js'
import Plyr from 'plyr'

const Player = ({src}) => {

  const [player, setPlayer] = useState(null);
  const video = useRef(null);

  useEffect(() => {

    const node = video.current;

    // Thought it would help, but no
    const destroy = () => {
      if (window.hls) {
        window.hls.stopLoad();
        window.hls.detachMedia();
        window.hls.destroy();
      }
    };

    if (node) {
      if(!player) setPlayer(new Plyr(node, {captions: {active: true, update: true}}))
      if (HLS.isSupported()) {
        destroy();
        window.hls = new HLS();
        window.hls.loadSource(src);
        window.hls.attachMedia(node);
      } else node.src = src;
    }

    }, [src, player]);

  return (
    <div>
      <video ref={video} src={src} controls/>
    </div>
  )
};

Solution

  • I fixed an useEffect so it works now:

    import React , { useEffect, useRef, useState,context }  from 'react'
    import HLS from 'hls.js'
    import Plyr from 'plyr'
    
    const destroyHLS = () => {
      window.hls.stopLoad();
      window.hls.detachMedia();
      window.hls.destroy();
    };
    
    
    const Player = ({src}) => {
    
      const [player, setPlayer] = useState(null);
      const video = useRef(null);
    
      useEffect(() => setPlayer(new Plyr(video.current, context)), [src]);
    
      useEffect(() => {
    
        let ignore = false;
    
        if (HLS.isSupported()) {
          if (window.hls) destroyHLS();
          window.hls = new HLS();
          window.hls.loadSource(src);
          window.hls.attachMedia(video.current);
        } else video.current.src = src;
    
        if (ignore) player.destroy();
    
        return () => {
          ignore = true;
        };
      }, [player, src]);
    
      return (
        <div>
          <video ref={video} src={src} controls/>
        </div>
      )
    };