Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvalidStateError: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source. #8228

Open
hellofrontendxxx opened this issue Mar 8, 2025 · 1 comment
Labels
type: question A question from the community

Comments

@hellofrontendxxx
Copy link

Have you read the Tutorials?

  • Yes

Have you read the FAQ and checked for duplicate open issues?

  • Yes

If the question is related to FairPlay, have you read the tutorial?

What version of Shaka Player are you using?

  • 4.13.8

What browser and OS are you using?

  • Chrome 134.0.6998.44
  • MacOS Sonoma 14.2.1

Please ask your question
I am using ReactJS in combination with shaka-player to view a list of live streaming/VOD channels (.m3u8). For example, when I press the enter button to switch to the next channel (update the url), I understand that I have to rerun the initialPlayer function with the new url. But when I check the console, I find an error being logged when switching from one channel to another.

I am trying to use destroy(), unload() but it is not working.

Looking forward to your help. Thanks a lot.

// Error
{
    category: 3,
    code: 3015,
    data: [
        "InvalidStateError: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source.",
        "No error in the media element",
        "xxxxxxxxxx.ts"
    ],
    handled: false,
    message: "Shaka Error 3015",
    severity: 2
}
useEffect(() => {
    if (isSupported) {
      (async () => {
        const player = new shaka.Player();
        await player.attach(videoRef.current);

        window.player = playerRef.current;
        playerRef.current = player;

        player.addEventListener('error', (event) => {
          const error = event.detail;
          console.error('Error code', error.code, 'object', error);
        });

        console.log({ url });

        try {
          await player.load(url);
          console.log('The video has now been loaded!');
        } catch (error) {
          console.error('Error code', error.code, 'object', error);
        }
      })();
    }

    return () => {
      if (isSupported && playerRef.current) {
        // TODO:
      }
    };
  }, [isSupported, url]);
@hellofrontendxxx hellofrontendxxx added the type: question A question from the community label Mar 8, 2025
@matvp91
Copy link
Contributor

matvp91 commented Mar 8, 2025

I think this is related to your implementation. On each url change, you'd fire a new async function (I'd strongly advise against this) that recreates shaka. A previous instance might still have claimed the video element. You'd also have to keep track of the destroy promise to figure out the video element is available for a new instance to claim.

An alternative approach is to use a single player instance, call load as a side effect of an url change and discard LOAD_INTERRUPTED in a catch handler (as that particular error doesn't matter in your case).

Can you try something like this? Quickly drafted a sample up here: https://stackblitz.com/edit/matvp-shaka-react-1?file=src%2FApp.jsx

function Player({ url }) {
  // Create an instance once, use it during the lifecycle of this component.
  const [player] = useState(() => new shaka.Player());
  const videoRef = useRef();

  useEffect(() => {
    player.attach(videoRef.current);
    return () => {
      player.destroy();
    }
  }, [player]);

  useEffect(() => {
    // Don't await here, side effects run in sync.
    player.load(url).catch((error) => {
      if (error.code === shaka.util.Error.Code.LOAD_INTERRUPTED) {
        // Load interrupted, by unload or successive load. Discard.
        return;
      }
      // Handle error during load, put in state, etc...
    });
    return () => {
      player.unload();
    };
  }, [url]);

  return (
    <video ref={videoRef} />
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question A question from the community
Projects
None yet
Development

No branches or pull requests

2 participants