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

Hls fragments don't stop loading after destroying player #2273

Closed
sergioavazquez opened this issue Jun 7, 2017 · 124 comments
Closed

Hls fragments don't stop loading after destroying player #2273

sergioavazquez opened this issue Jun 7, 2017 · 124 comments

Comments

@sergioavazquez
Copy link

After an hls stream starts I can't get it to stop streaming.
I'm using React 15.5.4, medialement 4.1.2 and hls.js 0.7.9, Chrome, latest version.

On player's componentWillUnmount() I do the following: (where 'player' is the MediaElementPlayer)

this.state.player.pause();
this.state.player.media.hlsPlayer.stopLoad();
this.state.player.media.hlsPlayer.destroy();
this.state.player.remove();

I even remove the node from the HTML. I checked step by step and everything's being executed properly, no errors.

As I navigate back in the browser I still see chunks being loaded. In the screenshot below, I accessed a different contents and navigated back twice more.

As a result you can see both .m3u8 lists as well as .ts chunks are being loaded for 3 different contents: canal9vivo, americatv and tvp.

hls-chunks

I tested it with medialelement 4.1.3 but controls are not working for me on chrome. Content starts, but I can't see the controls or pause it. I get no errors. It's working fine on android though.

Am I missing something?

Thanks in advance.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Do you have a URL I can check please?

@sergioavazquez
Copy link
Author

I created a user so you can check:
demo.rocstar.tv
user: debugger
pass: mediaelement

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

OK I'll check it and keep you posted. Thanks

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Once I'm there where should I look at? there are different sections and IDK which one I can test for issues

@sergioavazquez
Copy link
Author

You can test by accessing any of the items on the first carousel. All those contents are live and hls.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

And then I just play it and pause it? Or is there anything else I need to do?

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Nevermind, I see what you are saying. I'll take a look. When it is paused, it should stop the loading of fragments. But I'll confirm that

@sergioavazquez
Copy link
Author

Play one of those contents while having console and/or network tab open. You'll see Fetch messages for both .m3u8 and .ts files. When you go back or navigate somewhere else, content loading should stop but it doesn't. Furthermore, if you access another content on that carousel you'll see that there are Fetch logs for both contents, the one you closed and the one you're watching. My best guess is that once async hls fetching starts it doesn't stop until buffer's full. Regardless of what I do...

@sergioavazquez
Copy link
Author

As you said, when the video is paused this occurs as well but I don't think that's necessarily an issue because you could pause to allow the player to buffer, if you have a bad internet connection for example. My issue is that I can't stop destroyed, removed players from loading fragments.. the only thing that stops the load is refreshing the screen.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Gotcha. Well let me explore this situation and I'll let you know my findings

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

BTW, you prefer me to speak in Spanish with you?

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

First thing I noticed is the autoplay, and the way this behaves is that if the player detects that the player has that attribute it will inhibit the startLoad and stopLoad when playing/pausing. Try removing that attribute and see what happens

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

BTW, 4.1.3 fixed something related to autoplay and it will autoplay the media correctly.

@sergioavazquez
Copy link
Author

English keeps it universal, but thanks for the offer!
I changed the autoplay in hls to false but I experience the same behavior.
I updated to v4.1.3 earlier today, but I saw no controls or navigation. Plus I couldn't pause the video so I immediately went back to 4.1.2.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Can you put a test page where you use the 4.1.3 so I can see what's going on with this version, please? I'm setting up a test page to check this issue but I want to make sure I can have some reference to your issue

@sergioavazquez
Copy link
Author

Ok, I'll update and create a separate frontend version so you can test it. I'll let you know.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Thank you I appreciate it

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

And if you can provide me a code snippet of how you are setting this up I'd also appreciate it. I haven't dealt a lot with React to know how to execute a componentWillUnmount function

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Just FYI, I tried this inside the componentDidMount after MEJS initialization and worked:

// Destroy after 30 secs
setTimeout(() => {
	this.state.player.media.hlsPlayer.stopLoad();
	this.state.player.media.hlsPlayer.destroy();
	this.state.player.remove();
}, 30000);

@sergioavazquez
Copy link
Author

Here's the 4.1.3 version: http://iday.rocstar.tv/
The first time you access a content controls work fine, but as you navigate to another player they fail. I believe the problem with this version is that state.player.remove() is not defined. Did you change the remove method for this version?

componentWillUnmount() executes when a component is being removed. I checked on componentWillMount() and all those methods, stopLoad, destroy and remove, work. On unmount, of course I don't see the video stopping because it already did, but I see the player being removed and as I said, on v4.1.2 there are no errors.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

I don't think thats the issue since the snippet I posted above was using 4.1.3 and I used the remove method

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Ok so my question is how you remove the component? Can you share the piece of code that removes it? Because maybe that's what I didn't understand: the method will be called once the player is removed and that already happened

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

That way I can update the documentation if needed

@sergioavazquez
Copy link
Author

This is the code I use to remove the player

componentWillUnmount() {
        if(this.state){ 
        // If player exists
          if (this.state.player) {
              this.state.player.pause();
              // If player is reproducing hls
              if(this.state.player.media.hlsPlayer){
                this.state.player.media.hlsPlayer.stopLoad();
                this.state.player.media.hlsPlayer.destroy();
              }
              try{
                this.state.player.remove();
              }catch(e){
                console.log(e);
              }
          }
          var videos = document.getElementsByTagName('video');
          for( var i = 0, total = videos.length; i < total; i++ ){
            try{
              videos[i].parentNode.removeChild(videos[i]);
            }catch(e){
              console.log(e);
            } 
          }
        }
    }

On version 4.1.3 this method: this.state.player.remove(); throws an error that just says error.

@sergioavazquez
Copy link
Author

componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any DOM elements that were created in componentDidMount

Official docs

@sergioavazquez
Copy link
Author

In React you don't remove a component. You update the state and React figures out if a component, in this case the player, is no longer needed thus it unmounts it. Before it is unmounted the method componentWillUnmount() is executed.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

And what executes your componentWillUnmount in your code? I'm just trying to imitate this locally

@sergioavazquez
Copy link
Author

I use redux to handle state so I dispatch an action. In order to imitate that exact behavior you need react and redux. It should be the same as calling a function... but maybe not.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 7, 2017

Ok I'll keep trying and keep you posted

@rafa8626
Copy link
Contributor

OK Android cast should work with the caveat of the issue we still need to debug. So once that's debug we can declare this as stable and I'll merge the branches accordingly. Here's an screenshot of what I saw with a Samsung S7 so we are good on that.
img_5858
img_5859
img_5860

@sergioavazquez
Copy link
Author

I've tested 2 different chromecast devices in 3 different networks but it's not working for me. I click on the cast button and select a casting device, just like in the screenshots but it only casts for a second, then it goes into pause. When I click play again it won't start. It looks like it's loading on the device I'm casting to, but the player is automatically set to pause. There are no error messages. I experience the same behavior on android and desktop every time so at least it's consistent. When I stop casting I get this error:

Uncaught TypeError: Cannot read property 'loadMedia' of null
    at e.value (chromecast.min.js:12)
    at new e (chromecast.min.js:12)
    at chromecast.min.js:12
    at HTMLUnknownElement.u.mediaElement.dispatchEvent (mediaelement-and-player.js:963)
    at chromecast.min.js:12

HLS chunks are being loaded, everything else looks normal. Any ideas on what to try next?

@sergioavazquez
Copy link
Author

If you want to test it yourself you can go to iday.rocstar.tv, same user and pass. Keep in mind that I haven't worked on the unmounting issue, so refresh the screen to test instead of navigating in and out of a channel.

@rafa8626
Copy link
Contributor

In your configuration have you used castIsLive: true?

@rafa8626
Copy link
Contributor

I know you are streaming TV so you must set the live flag so Chromecast takes care of some specific elements

@sergioavazquez
Copy link
Author

Nice catch. I added it and but still experience the same behavior. The only change is that when I press play after stream got paused it doesn't automatically set itself to pause on the player. Still no errors.

@rafa8626
Copy link
Contributor

I'll take a look because I tried something on my local following that approach and it worked fine.

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 21, 2017

Also, I'm seeing some errors that are related to the streamings themselves:
screen shot 2017-06-21 at 10 03 18 am
That might be also causing issues for Cast

@sergioavazquez
Copy link
Author

The first error on api/auth/me means you're no longer logged in. Log in again and test other channels on the first carousel, some contents might have geolocation protection. I don't manage all streams.

@rafa8626
Copy link
Contributor

Yeah I logged in and I could see the streamings. I just took the screenshot of everything I saw. So you can ignore the first error. But definitely there's something going on with the streamings

@sergioavazquez
Copy link
Author

Ok, so I'm going to update that version with the castIsLive=true and point it to another server that shouldn't have problems. I'll let you know how it goes.

@sergioavazquez
Copy link
Author

Ready: http://iday.rocstar.tv/ I can't reproduce the hlsError you're getting. Hopefully it'll work now.

@rafa8626
Copy link
Contributor

OK I'll check this later; if you can point any other issues while you test, let me know

@rafa8626
Copy link
Contributor

Where did you set the castIsLive? I cannot find it

@rafa8626
Copy link
Contributor

if loadMedia reports that error means the session got lost. I never saw this on my test is there anything else you are doing in your code that might cause the lost of the session?

@sergioavazquez
Copy link
Author

castIsLive is set here:

           <video autoPlay controls preload="none" id="rcsPlayer" height={height} width="100%"
              tabIndex="0" key={content.id}
              data-cast-title={content.name}
              data-cast-description={content.name}
              data-cast-is-live={true}
              >
              <source src={content.url} type={content.mediaType}/>
            </video>

Replacing camlCase for '-' is a react thing. If the property doesn't exist it warns you so I know it's working. Where would you add it if not there? I followed the example here: https://github.com/mediaelement/mediaelement-plugins/blob/master/docs/chromecast.md

I get the loadMedia error after I close the cast session so it makes sense.

Where you able to cast on iday.rocstar.tv?

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 21, 2017

Yes but that particular element integrates like this:

new MediaElementPlayer('player-id', {
    // All your config...
    castIsLive: true
});

The only elements that data-* grabs are for informational purposes. All the API elements should be configured like that, not through data-*. That's why it's still pausing and giving you troubles

@sergioavazquez
Copy link
Author

YES! It works now! thanks! I'm going to keep testing. I still have to figure out how to work with chromecast sessions and react but I will! I'll keep you posted!

@rafa8626
Copy link
Contributor

Such good news! Yes keep me posted on anything so I can release these changes

@sergioavazquez
Copy link
Author

It's working great. I just have a few cosmetic issues and a few improvement ideas.
1 - The "casting to" text on the top left corner appears the second time I open a player. It doesn't matter if I casted or not. More over, if I'm using a poster, not only the casting to text appears but a fullscreen overlay of the poster that doesn't go away on play. I see no errors on the screen. You can test it in iday.rocstar.tv.

2 - I can no longer pause the video player by touching the screen. I find it useful to have control of the player from the screen, specially on mobile devices. Once the video is paused I can set it to play from the screen, no problem. This only happens when castIsLive is set to true, otherwise it works fine.

I want to handle casting "a la Netflix" and it's been working great. If I don't stop the cast and change channels the stream updates, so I can do zapping while casting. Some channels get automatically paused when I do this, others not. I'm going to test this further and try to get cast information from window.cast.framework and see what can be done there. Maybe add a few listeners, if casts stops, check if casting is established, etc.

Improvement ideas (mostly based on the "a la Netflix" concept):

  • I would like to be able to change the initial blue chromecast logo to a custom image. (Not important)

  • I want to be able to use the poster for casting only. Meaning I don't want the poster displayed locally on the player. The poster on the cast is small, like a preview thumbnail, but when applied on the local player it's a fullscreen image. I rather control these two separately.

  • It would be great to be able to set a background image on TV when casting is connecting.

I'm going to keep testing and trying stuff. Let me know how can I help move this along. Great work!

@sergioavazquez
Copy link
Author

I'm not able cast youtube videos embedded on the player. Cast starts, sends title and description information but that's all it happens.

@rafa8626
Copy link
Contributor

Thanks I'll check your suggestions about the plugin. As for the YouTube, the plugin only allows to play what natively plays with Chromecast. YouTube is loaded through an iframe and that's not something that natively supports

@rafa8626
Copy link
Contributor

And for your concerns with customizing the icon in the app, I'm using the default receiver but it's gonna be on your side to develop a new receiver with all the customized features you want to see on TV. I just provide the basic platform for it. You will need to check Cast documentation about how to build a new receiver.

@rafa8626
Copy link
Contributor

I really appreciate the time you have spent testing. I'll address the issues with play pause and the poster image locally, and with that I'll release the changes on this plugin

@sergioavazquez
Copy link
Author

Sounds great, keep me posted!

@rafa8626
Copy link
Contributor

rafa8626 commented Jun 22, 2017

So as far as the poster issue, YouTube implements that same workflow: a poster that remains static with every interaction you are having when you are connected to Chromecast. If you don't need that, you must avoid the poster attribute. Please download the master branch to test the rest of the fixes for Chromecast. Let me know if they worked for you. Thanks

@rafa8626
Copy link
Contributor

Just FYI, I'm doing some last fixes to make sure the interaction with MEJS and chromecast gets better. I'll keep you posted when I'm done with this final adjustments

@rafa8626
Copy link
Contributor

OK I have pushed everything to the master branches in both projects; if you can test them once more before I release I'd appreciate it. One thing to note: everything works as expected in a single page player, but with ReactJS there are not a lot of resources to dig more. Once you have something online, and if you feel stuck, reach Chromecast team so they give you guidance, and if needed, I can perform more fixes. But as it is right now, the plugin should be ready to go. It's more a matter of implementation on ReactJS at this point. If you have feedback from them, create a new ticket rather than writing on this one. Thanks again for all your help on this

@sergioavazquez
Copy link
Author

Awesome, I'll be testing it today, I'll open another issue if something comes up. Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants