Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube API & Websockets Make sure two videos are in sync (Video 1 pauses when Video 2 buffers)

Background

I am trying to integrate Videos into a slide show presentation app. I have disabled the controls on the students side and have a play/pause button wired up to the YouTube API so that when it is clicked an event is triggered through pusher and the Video starts on the teachers screen and the Students screen.

Difficulties

The problem comes when one of the users has a slow internet connection. If The teacher has faster internet than the student then the videos will be out of sync.

My Approach

I have a function which uses the YouTube API to control the playing and pausing of a video.

/**
 *
 */
togglePlay: function(){
    var videoId = this.videoId;
    if (this.isPlaying) {
        this.players[videoId].pauseVideo(); // Pauses the video
        this.isPlaying = false;
    } else {
        this.players[videoId].playVideo(); // Starts the video
        this.isPlaying = true;
    }
},

Inside the video object I have added an onStateChange event listener that is triggered when a video is playing/paused/buffering. The event is sent to this function.

/**
 *
 */
emittStateChange: function(e){
    switch(e.data) {
        // if the teachers video is...
        case 1: // playing
            pusher.channel4.trigger('client-youtube-triggered', {
                videoId: youtube.videoId,
                status: 1, // start the students video
            });
        break;
        case 2: // paused
            pusher.channel4.trigger('client-youtube-triggered', {
                videoId: youtube.videoId,
                status: 2, // pause the students video
            });
        break;
        case 3: // buffering
            pusher.channel4.trigger('client-youtube-triggered', {
                videoId: youtube.videoId,
                status: 2, // pause the students video
            });
    }
},

So when the teachers presses play the video starts and truggers a play event which gets sent to the above function. This function sends a pusher event to the students browser with a status of 1 which means play the video. This event is received by this function:

/**
 * 
 */
receiveStateChange: function(data){
    this.videoId = data.videoId;
    switch(data.status) {
        // if the teachers video is...
        case 1: // playing
            this.isPlaying = false;
            this.togglePlay();
        break;
        case 2: // paused
            this.isPlaying = true;
            this.togglePlay();
        break;
        case 2: // buffering
            this.isPlaying = true;
            this.togglePlay();
    }
},

My understanding

  1. Teacher presses play button
  2. togglePlay() is called
  3. this.isPlaying = false so playVideo() is called
  4. video starts playing for teacher
  5. The YouTube api then triggers an onStateChange event
  6. this is sent to the emittStateChange() function with status 1 (playing)
  7. This status is sent via pusher to the students receiveStateChange() function
  8. for case = 1 this.isPlaying() is set to false
  9. toggle play is called to start the students video
  10. Students video starts buffering which triggers the youtube api onStateChange event again
  11. Status 3 (buffering) is then sent back to the teacher via pusher
  12. This pauses the teachers video to wait for the student

Problem:

  1. When the teachers video stops the onStateChange event is triggered yet again before the students video is done buffering and sent to the student.
  2. This stops the students video and now both videos are paused.

What I want:

When the students video is buffering I just want to temporarily pause the teachers video UNTIL the students is playing then play both. I just don't understand how I should break this cycle that ends in both videos being paused.

like image 657
Jethro Hazelhurst Avatar asked Mar 10 '17 10:03

Jethro Hazelhurst


1 Answers

I am sure you can send more than one event at a time.
So you can send info to the teacher about which student is "buffering" and any other relevant info.
Then on the teachers side, set up a conditional statement that will evaluate the message. So that in the function, the teachers player will not send a control instruction to the student if that condition exists.

As well as have a bypass on the teachers side that if they think it needed, they can stop/pause the video at any time on all players.

like image 123
Tempus Avatar answered Oct 12 '22 19:10

Tempus