gajus/youtube-player

on('stateChange') is not triggering

MarcelRobitaille opened this issue · 13 comments

I stopped getting events recently. I commented on #7 a while ago but didn't get an answer so I figured I'd ask here. I'm on the latest 5.4.0.

gajus commented

Have you tried inspecting the code?

I did look at it but I couldn't make too much sense out of it.

I have not been able to reproduce the issue with a minimal configuration (this one might be my bad. sorry).

Here is my implementation. Any idea what might be wrong?

/* globals gapi */

import YoutubePlayer from 'youtube-player'

export class Player {
  static States = {
    UNSTARTED: -1,
    ENDED: 0,
    PLAYING: 1,
    PAUSED: 2,
    BUFFERING: 3,
    CUED: 5,
  }

  _events = {
    end: [],
    start: [],
  }
  _trigger = (event, data) => this._events[event].forEach(cb => cb(data))
  on = (event, cb) => this._events[event].push(cb)

  constructor () {
    this.state = Player.States.UNSTARTED
    this.data = {}

    this.youtubePlayer = YoutubePlayer('video-player', {
      height: 1080,
      width: 1920,
    })

    this.youtubePlayer.on('stateChange', event => {
      console.log('event', event)
      if (event.data === Player.States.ENDED) return this._trigger('end', event)
    })

    this.youtubePlayer.on('error', event => {
      if (event.data >= 100) return this._trigger('end', event)
    })
  }

  load = video => {
    console.log(video)
    if (!video) throw new Error('Video null')

    const videoId = typeof video === 'string' ? video : video.video.id
    this.video = video
    this.data = {}

    return this.youtubePlayer.loadVideoById({
      videoId,
      suggestedQuality: 'hd1080',
    }).then(() => this._trigger('start', video))
  }

  getData = part => {
    part = typeof part === 'string' ? part : 'snippet'

    if (part in this.data) return Promise.resolve(this.data)

    return gapi.client.youtube.videos.list({
      id: this.video.video.id,
      part,
    }).then(res => {
      this.data = res.result.items[0]
      return this.data
    })
  }
}

I am not getting .on('error') either.

@Iambecomeroot Is YouTube's code doing what it should be in this case?

@resistdesign The whole point of using this module was to avoid youtube's implementation but I'll give it a shot. Give me a minute.

@Iambecomeroot I know, I was just asking if you minded checking.

This is weird. Using the official api I am not getting events either. Does anybody have any ideas?

export default new Promise(resolve => {
  var tag = document.createElement('script')

  tag.src = 'https://www.youtube.com/iframe_api'
  var firstScriptTag = document.getElementsByTagName('script')[0]
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag)

  var player
  window.onYouTubeIframeAPIReady = () => {
    player = new YT.Player('player', {
      height: '390',
      width: '640',
      videoId: 'M7lc1UVf-VE',
      events: {
        'onReady': () => resolve(player),
        'onStateChange': event => console.log(event),
      }
    })
  }
})

I would need to see the whole page in context, idk why you just wouldn't get events. Something is intercepting somewhere!

Interestingly, when I do this, I get events -1 and 3 right off the bat but nothing else (not even 3 again if I skip ahead and buffer again). What could be intercepting it?

var player
export default new Promise(resolve => {
  var tag = document.createElement('script')

  tag.src = 'https://www.youtube.com/iframe_api'
  var firstScriptTag = document.getElementsByTagName('script')[0]
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag)

  window.onYouTubeIframeAPIReady = () => {
    player = new YT.Player('player', {
      height: '390',
      width: '640',
      videoId: 'M7lc1UVf-VE',
      events: {
        'onReady': () => { player.playVideo() },
        'onStateChange': event => console.log(event),
      }
    })
  }
})

@Iambecomeroot Is there something else in the app that interacts with the player somehow? Some jQuery something or other thingamawhozit?

There should be nothing using it directly. It should all go through that class. Just to be safe, I commented everything that calls that class but it still doesn't work. I am using the google api too though.

I'm stumped. That's weird.