sampotts / plyr

A simple HTML5, YouTube and Vimeo player
https://plyr.io
MIT License
26.35k stars 2.92k forks source link

How to NOT autostart the YouTube movie clip #1838

Open AlGantori opened 4 years ago

AlGantori commented 4 years ago

I am using the iframe per the documentation, however I would like the option to NOT autostart the initial clip I am having to specify par of the iframe.

I found the following post suggesting adding autostart=false to the iframe parameters, but it did not work. Apparently it was meant for a different player relating to that post palyer.twitch.tv.

I am also noticing this init clip fires twice the volume event with a value of 1.

You can verify this behavior as well in the following reproduction code https://stackblitz.com/edit/ionic-zphr1n?file=pages%2Fhome%2FPlyrPlayerComp.ts

My plyr setup looks something like this

  Setup() {
    console.log("PlyrService.Setup------.------>>");
    if (typeof this.Player === "undefined") {
      this.Player = new Plyr("#plyrjs");
    }
    if (typeof this.Player === "undefined") {
      let msg = "Video Player could be created, returned as undefined";
      console.log("PlyrService.Setup------.------>>FAIL", msg);
      alert(msg);
       // this.Error.next(msg)
    } else {
      console.log(
        "PlyrService.Setup------.------>>SUCCESS, this.Player.playing",
        this.Player.playing
      );
      this.WireDesiredEvents();
    }
  }

Even if I was to use the options object during creation of plyr object and specify my user.options.volume, the autoplayed video from the iframe beats me and generated volume events with value 1.

I want to listen to the plyr volume event if the user adjusts volume via the plyr volume slider itself, but the current behavior corrupts the last volume session setting I saved in local storage.

Said differently, the video clip whether started via an iframe or later explicitly should not fire volumechange event if the no volume value was explicitly requested.

Thanks for a great API, it's very obvious lots of thoughts and effort is going into this plyr library.

AlGantori commented 4 years ago

In case the typescript stuff confuses you, here is some JS/HTML "TESTER" version I typically use when I upgrade to newer plyr releases. Even though this tester code is not using iframe (embedding) the video fires "volumechange" twice.

https://jsbin.com/komaxetuga/edit?js,console,output

image

Thanks for looking into this.

akuma06 commented 4 years ago

First, in your example, you're calling Player.play() inside your events. Therefore you can't specify autoplay=0 inside the iframe url and still make it play at the same time in your events. You should either choose to let youtube autoplay with autoplay=1 or not, don't make it play directly from your events.

Second I don't know if I get what you meant but if you want to override no matter what the volume of your video with your own settings, you need to remove the plyr storage. Plyr saves the user previously selected volume inside his local storage. Therefore if you specify the volume in your constructor options, it won't change the volume since user saved preferences override default configuration. So you either disable the storage inside the constructor options:

const Player = new Plyr('#plyrjs', {
  volume: 0.5,
  storage: {
    enabled: false
  }
});

Or you change the volume inside the ready event which will override the user defined volume:

    Player.on('ready', function (event) {
        console.log("video READY");
      Player.volume = 0.5;
    });

Here is an example based on your own script: (https://jsbin.com/tatiboguco/edit?html,js,console,output)

AlGantori commented 4 years ago

Thanks for helping out. The link you sent does not have your edits, the JS code is the same as what I posted in the other link? I typically use stackblitz.com for my ionic/angular issue reproductions but it does not seem to have a simple html/js template, that's why I selected jsbin.

BTW, I don't program in JS but in TS, consider me beginner in both. Regarding autoplay=0 I was shoving it in the wrong place in the iframe.

I was not aware plyr saves user settings in storage so I will see how disabling that changes the behavior. Thanks for pointing that out. Does it mean that because plyr restores the last audio setting from the storage it causes those two volumechange to fire?

From the perspective of the client (ie. my app) if my client says .play() it expects a play event or the like. But if the client does not alter or specifies an initial volume plyr should not fire a volumechange event even if it restored a value from storage.

My plyr setup looks like this image

Even though, I disabled storage during the creation of plyr it seemed it did not take effect. I also manually cleared plyr storage from dev console. ... ..... I think it's because if you don't specify volume it still fires volumechange making me believe it pulled it from the storage.

I have been listening to "ready" for a couple of years now in order to chain the actual play() command which otherwise seems to be ignored that's why I have the .play() on the "ready" event. I have been able to keep up with the releases plyr against my ionic/TypeScript app, it was not the case in the beginning. Perhaps there is a better way to code my wrapper around plyr?

Let me explain:

I introduced the "dummy" short clip in the iframe because I could not create Plyr() without the src specified in the iframe, perhaps there is a way around that, I don't know. Ideally, I wanted to initialize Plyr (ie create the object and wire its events all in one place) without any video specified. Then I would wait for the user to a select a media targeted for plyr, which I would play via my PlayVideoByID() method in my plyr wrapper class. But perhaps because of how plyr and YouTube embed is setup I was not successful with that approach.

Here is the PlayVideoByID() after a user selects video to play. It was only recently that I decided to set the volume from my UserOptions (which are cached into storage) that I realized the issue I am running against. If setting plyr.source returned a promise I could chain .play there but it's a prop, probably props are not meant to return promises :) that caused me to listen to on "ready" then play().

image

Here is where I listen to volume change and update the UserOptions. If plyr fires volumechanged with 1 that would corrupt my UserOptions volume setting.

image

Even if I remove any volume setting both on new Plyr() and volumechange() when the clip in the dummy iframe is loaded but NOT autoplayed I see volumechange

image

image

I reproduce the same in jsbin when storage is disabled and I don't specify any volume, it stile fires volume set to 1 twice. I am fine if it sets to volume to 1 but I think it should NOT fire the event.

https://jsbin.com/jelaboluni/edit?js,console

I see the following image

Finally, combining 1) plyr storage disabled, 2) allowing autoplay, and 3) setting volume from my UserOptions seems to works and not corrupt my user cached value.

Thanks for all your insights I appreciate all.

I know I am loosing it and all of this programming has become challenging by the day. I am working on a reproduction on stackblitz relating to overlaying my user messages over plyr while in FullScreen the pits is that it seems to be working on stackblitz but not in my app :)

https://stackblitz.com/edit/ionic-4aduqf?file=pages%2Fhome%2FPlyrPlayerComp.ts

I better go grab some sleep, I've been up all night.

akuma06 commented 4 years ago

Yes, the volumechange fire event happens every time the Plyr ui is built and twice. You can see in ui.js that this.volume is set to null and this.muted the same. Both those assignment forces a volumechange event. Since they can't be avoided, the only way to resolve this for you is to just disable the plyr storage. Doing it this way, when the event is fired, you get what you just set so nothing really changes :). You might also think of storing the mute state inside your UserOptions since by removing the storage, Plyr won't remember by itself if the user previously muted the video.

AlGantori commented 4 years ago

Thank you. I just got started on saving some user session stuff about plyr playing, because I have a need for other players in my app with different volume settings, I will include muted state.

Regarding startup is there a way to create Plyr and wire its events without specifying a video? Also, I am under the assumption, I should be using the iframe for youtube for progressive enhancement. I think I must have been using

I would like to play every video thru the same method even if I needed some intro video. Thanks.

akuma06 commented 4 years ago

From the code base, it's not possible, listeners are instantiated in the constructor after it has verified that the target HTMLElement is not null (and is a playable element). So you need to provide an element for Plyr to work. However, you could do a reference to your first instance of Plyr and store it somewhere so you can just change its source.