2

Here I found an example how I can listen Play\Pause button of youtube iframe.

player.addEventListener('onStateChange', function(e) {
    console.log('State is:', e.data);
});

Now I need to listen the volume changes. In the youtube documentation and here I found a method player.getVolume(), but I have no idea how this method can be implemented if I want to be informed about volume changes from iframe side, instead of ask iframe from my side.

On YouTube Player Demo page such functionality exists (when I change the volume of a player, I see appropriate changes in the row Volume, (0-100) [current level: **]), but neither in the doc nor in internet I can not find how to implement it.

I also tried to use the above mentioned code with onApiChange event (it is not clear for me what this event actually does), like:

player.addEventListener('onApiChange', function(e) {
    console.log('onApiChange is:', e.data);
});

but console shows nothing new.

player.getOptions(); shows Promise {<resolved>: Array(0)}.

Could anyone show an example?

TitanFighter
  • 4,582
  • 3
  • 45
  • 73
  • Possible for you to give a [**Minimal example**](https://stackoverflow.com/help/mcve) for people to work with? – NewToJS Dec 20 '17 at 01:07
  • @NewToJS I added what I also tried. I can not provide any `minimal example` because I simply have no idea how I can even try to solve my problem. I have been digging internet and youtube docs for the last ~6 hours. Simply I can not find any hints, even in order to try to implement something myself and then provide some minimal code. Usually I provide minimal example, but in this case it is really hard. – TitanFighter Dec 20 '17 at 02:08
  • Are you wanting to have an `EventListener` for if/when the client changes the volume via the YouTubes video `iframe` to update your `slider/range`? IF so then no such event listener exists within the **API** from when I know of or can find. I am also currently working with this **API**. If you want to have your `slider/range` update the player then I can provide you with an example for that but unfortunately not for the opposite way round. – NewToJS Dec 20 '17 at 02:55

2 Answers2

3

See this question.

You can listen to postMessage events emitted by the IFrame and react only to the volume change ones:

// Instantiate the Player.
function onYouTubeIframeAPIReady() {
  var player = new YT.Player("player", {
    height: "390",
    width: "640",
    videoId: "dQw4w9WgXcQ"
  });

  // This is the source "window" that will emit the events.
  var iframeWindow = player.getIframe().contentWindow;

  // Listen to events triggered by postMessage.
  window.addEventListener("message", function(event) {
    // Check that the event was sent from the YouTube IFrame.
    if (event.source === iframeWindow) {
      var data = JSON.parse(event.data);

      // The "infoDelivery" event is used by YT to transmit any
      // kind of information change in the player,
      // such as the current time or a volume change.
      if (
        data.event === "infoDelivery" &&
        data.info &&
        data.info.volume
      ) {
        console.log(data.info.volume); // there's also data.info.muted (a boolean)
      }
    }
  });
}

See it live.

Note that this relies on a private API that may change at anytime without previous notice.

Felipe Zavan
  • 1,654
  • 1
  • 14
  • 33
1

I inspected the code of YouTube Player Demo page and found that the html line which shows the current YouTube volume (<span id="volume">**</span>) constantly blinking (~ 2 times per 1 sec), so I can assume this demo page uses something like this:

// YouTube returns Promise, but we need actual data
self = this
setInterval(function () { self.player.getVolume().then(data => { self.volumeLv = data }) }, 250)

Possibly not the best method, but it seems there is no other option (I also tried to listen changes in the appropriate style of the volume bar, but no luck due to the cross-origin problem).

So, this let us 'listen' volume changes of youtube.

Just in case, if someone wants to set youtube volume, you need to use [this.]player.setVolume(volume_from_0_to_100)

TitanFighter
  • 4,582
  • 3
  • 45
  • 73