shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.21k stars 1.34k forks source link

Add a simple tutorial on using Shaka Player UI w/ ReactJS #2163

Closed joeyparrish closed 3 years ago

joeyparrish commented 5 years ago

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

Is your feature request related to a problem? Please describe. We provide no guidance on using Shaka Player with ReactJS, primarily because we have no experience with ReactJS on this team.

Describe the solution you'd like A tutorial showing the most basic usage of the Shaka Player UI in a ReactJS component.

Describe alternatives you've considered Leaving specific frameworks out of scope. It could be a slippery slope with folks expecting documentation on integration with many other frameworks, none of which is used by this team.

Additional context Spawned from discussion on #2159 with @amit08255.

amit08255 commented 5 years ago

Added a repository with simple projects in ReactJS to demonstrate how shaka player can be used and how video player UI can be configured with shaka player. https://github.com/amit08255/shaka-player-react-with-ui-config

joeyparrish commented 5 years ago

Thanks! We'll take a look.

theodab commented 5 years ago

You're configuring the UI incorrectly. The Overlay constructor does not take a configuration object as a parameter; instead, you should call the configure method after creation. For example:

const ui = new shaka.ui.Overlay(player, videoContainer, video);
ui.configure(uiConfig);
ui.getControls();

Although, if this is a tutorial, then I'm not sure if it's even appropriate to be configuring the UI. We already have an entire tutorial about configuring the UI, so putting that stuff into an unrelated tutorial also would be redundant.

amit08255 commented 5 years ago

Well @theodab I don't mean to be blunt, but your lovely tutorial was absolutely zero help when I was trying to implement shaka player in ReactJS. I had to find the implementation from several other issues and websites. I am not providing a tutorial, I am just providing simple projects to demonstrate how shaka player can be implemented in ReactJS. Please provide an example if you feel I am configuring the UI incorrectly because the code is working perfectly without an issue. Thanks.

theodab commented 5 years ago

I apologize if I offended you. I had assumed, from the way that the README was worded, with step-by-step instructions and such, that you had intended that repository as some sort of reference for others?

And your code is working without issue because customizing the order of UI elements is optional, and the UI will still work without it.

If it is important for your application that the mute button is to the left of the volume control, and so on, then you could configure that this way:

// Make the UI layer.
const ui = new shaka.ui.Overlay(player, videoContainer, video);

// Configure the order of controls.
const uiConfig = {};
uiConfig['controlPanelElements'] =
  ['mute', 'volume', 'time_and_duration', 'fullscreen', 'overflow_menu'];
ui.configure(uiConfig);
amit08255 commented 5 years ago

No no you didn't offend me. The repository is just for helping other beginners with implementation. Thanks for the example. I will try it. Thanks for your help and sorry for my inappropriate choice of words, I didn't mean to offend anyone just trying to help.

theodab commented 5 years ago

Hm. Looking at our changelog, I think the confusion might have been that you found a tutorial or project from before the v2.5 launch. Back when the UI was still in beta, you could configure it that way, but that was refactored out when we added the ability to dynamically re-configure the UI.

amit08255 commented 5 years ago

Please help me out here. Is ui.configure() required? should I use it?

theodab commented 5 years ago

If you don't actually care about re-arranging the UI, then you don't need to do any configuration.

amit08255 commented 5 years ago

Ok got it. Thanks. Actually I had to use UI configuration because the default UI didn't had features like - video quality change button.

kauly commented 5 years ago

Why use the Overlay constructor? Just init the UI like they do in the ui tutorial. https://gist.github.com/kauly/410f516f00d997fdb5e7506432c008d4

ismena commented 5 years ago

Hi @amit08255

Video quality control should be part of the default UI, e g you shouldn't have to configure to get it. If you do, then we have broken something :(

On the subject of the Overlay constructor: as @theodab mentioned, there was a point in time when it accepted a config object, but we changed it and it doesn't anymore.

Now, if you want a custom configuration, you will need to do exactly what @kauly mentioned: ui.configure(your_config);

I'm sorry we changed the code on you!

Looking at your code, I don't think you need to call configure(). Does the video quality control not show up for you if you remove all the config logic and just do this:

    //Link to MPEG-DASH video
    var manifestUri = 'https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd';

    //Getting reference to video and video container on DOM
    const video = this.videoComponent.current;
    const videoContainer = this.videoContainer.current;

    //Initialize shaka player
    var player = new shaka.Player(video);

    //Setting up shaka player UI configuration
    const ui = new shaka.ui.Overlay(player, videoContainer, video);`

`

joeyparrish commented 5 years ago

I suggested the constructor because I am not familiar with ReactJS or when the DOM elements are created. Shaka Player's UI will scan the DOM at load time, and if the elements with data-shaka-player-container are created after the scan, then they will be missed. Using the API to construct the UI will work no matter when the DOM elements were created.

kauly commented 5 years ago

@joeyparrish you are right I think. Sometimes I must manually reload the page because the UI wont start. I thought it was a webpack-dev-server problem but looks like its not.

amit08255 commented 5 years ago

@ismena Thank you very much for your help your suggestion worked perfectly. Can I please ask if using shaka.ui.Overlay correct or not? because solution that @theodab suggested worked without an issue.

matvp91 commented 5 years ago

I've written a ShakaPlayer component a while ago, I'll dig it up and see if it can be of any help to you guys.

Does it make sense to provide a separate library that simply bridges shaka-player as a component? We can keep the API the same, have a prop define the config and use forwardRef in combination with a useImperativeHandle hook to expose the instance.

As for the component itself, I'd avoid class components (soonish to be deprecated and if I'm not mistaken, React 17 will stop calling lifecycle methods if they're not prefixed with UNSTABLE_). Also, make sure the shaka instance is disposed when the component unmounts. :)

ismena commented 5 years ago

@amit08255 The use of shaka.ui.Overlay is correct. Passing a uiConfig object to it is no longer correct (it was, but we changed it).

What @theodab suggested is also correct, but IMO you don't need it for your specific case.

Thank you for putting a shaka+React example together!

@matvp91 we would appreciate it, thank you!

Seems like there's a fair bit of interest in an "official" shaka/react tutorial. We'll see if the team can find some time to figure react out and put one together!

matvp91 commented 5 years ago

@ismena, quickly wrote a ShakaPlayer component, it's still somewhat present at the back of my head. If you want, I can spend some more time and release it as a npm package (react-shaka-player), unless you guys feel like providing a component wrapper as part of shaka itself.

I'm currently in doubt whether it's a good idea to expose Shaka's API as an imperative handle instead of using a config prop (along with a manifestUri and uiConfig prop, these would be used to load the asset at mount instead of waiting for the parent component to configure shaka). The upside is that it's a generic approach and wouldn't take a whole lot of maintenance to keep it up to date with Shaka's upcoming changes (as all the ref does is expose the player and ui api).

function ShakaPlayer({}, ref) {
  const containerRef = useRef();
  const api = useRef();

  /**
   * Creates a container for the UI and a video element.
   * @param {HTMLDivElement} container
   * @returns {{uiContainer: HTMLDivElement, videoElement: HTMLVideoElement}}
   */
  function createPlaceholders({ container }) {
    const uiContainer = document.createElement('div');
    container.appendChild(uiContainer);

    const videoElement = document.createElement('video');
    videoElement.style.maxWidth = '100%';
    uiContainer.appendChild(videoElement);

    return {
      uiContainer,
      videoElement,
    };
  }

  /**
   * Effect to handle component mount & unmount.
   */
  useEffect(() => {
    const container = containerRef.current;

    const { uiContainer, videoElement } = createPlaceholders({ container });

    const player = new shaka.Player(videoElement);
    const ui = new shaka.ui.Overlay(player, uiContainer, videoElement);

    // Store Shaka's API in order to expose it as a handle.
    api.current = { player, ui };

    /**
     * Cleanup.
     */
    return () => {
      player.destroy();
      ui.destroy();

      // Let's remove unused DOM nodes.
      while (container.firstChild) {
        container.removeChild(container.firstChild);
      }
    };
  }, []);

  /**
   * Define a handle for easily referencing Shaka's player & ui API's.
   */
  useImperativeHandle(ref, () => ({
    get player() {
      return api.current.player;
    },
    get ui() {
      return api.current.ui;
    },
  }));

  return <div ref={containerRef} />;
}

export default forwardRef(ShakaPlayer);

Usage would work like this:

function App() {
  const shakaRef = useRef();

  useEffect(() => {
    const { player, ui } = shakaRef.current;
    // player & ui point to an instance of shaka.Player & shaka.ui.Overlay.
    player.load('https://bitmovin-a.akamaihd.net/content/playhouse-vr/mpds/105560.mpd');
  }, []);

  return (
    <div>
      <h1>Look ma, Shaka in React!</h1>
      <ShakaPlayer ref={shakaRef} />
    </div>
  )
}

Let me know what you think.

ismena commented 5 years ago

@matvp91 Thanks Matthias!

I know nothing about React, that's the problem! :| I'll try to find time and learn some, though, if there's interest in the community. In the meantime, I'm sure folks will appreciate these examples from you and Amit @amit08255.

matvp91 commented 5 years ago

@joeyparrish @ismena I've published the code as an npm package, see https://github.com/matvp91/shaka-player-react https://www.npmjs.com/package/shaka-player-react

Would it make sense to add this to the README or include it in the docs?

giovannipds commented 4 years ago

@matvp91 nice idea of creating the package, congrats! It would be awesome if we could ship some samples with UI. Also, it seems like it doesn't support SSR, so I couldn't just insert it at Next.js, a popular react framework.

amit08255 commented 4 years ago

@giovannipds Please check this project. It's not a library, it just shows how you can use shaka player with Next.JS

https://github.com/amit08255/shaka-player-react-with-ui-config/tree/master/nextjs-shaka-player

giovannipds commented 4 years ago

@amit08255 awesome! I solved it in a similar way. Nice idea of adding it to the examples.

ismena commented 4 years ago

Oh, I never updated this thread with the fact that we did add the React integrations to README! Let me go ahead and add the Next.js one, too.

If there are other reference projects for Shaka integrations that people find useful, please let us know, we'd love to spread the word!

matvp91 commented 4 years ago

@giovannipds it surprises me that it does not work out of the box with nextjs.

As for SSR, there is nothing to render upfront and ship as initial HTML. Shaka's UI is not written in React, thus SSR will not be able to prepare the UI upfront. But it totally makes sense to have a seamless integration with nextjs. Would you mind opening up an issue in the repository of shaka-player-react? I'll follow up with nextjs's integration there.

giovannipds commented 4 years ago

@matvp91 not at all! Nice to read your feedback.

joeyparrish commented 3 years ago

Since we have mention of ReactJS integration in README, I'm going to close this issue. Thanks!