From d33c4fc81faf096b23727b3fc4e46799bcf68b80 Mon Sep 17 00:00:00 2001 From: Valera Rozuvan Date: Mon, 27 Jan 2014 14:05:36 +0200 Subject: [PATCH] Fix for BLD-708: Firefox YouTube video start time. In Firefox YouTube video with start time plays from 00:00:00. The reason was that seekTo() could not start playing a video from a point that hasn't been buffered yet. Why this started happening just now, really is hard to explain. BLD-708. --- CHANGELOG.rst | 3 + common/lib/xmodule/xmodule/js/spec/helper.js | 2 +- .../xmodule/js/spec/video/general_spec.js | 46 ++++++++++++++ .../xmodule/js/src/video/03_video_player.js | 60 ++++++++++++++++--- 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fb722bb7db..501baee768 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes, in roughly chronological order, most recent first. Add your entries at or near the top. Include a label indicating the component affected. +Blades: Bugfix "In Firefox YouTube video with start time plays from 00:00:00". +BLD-708. + Blades: Fix bug when image response in Firefox does not retain input. BLD-711. Blades: Give numerical response tolerance as a range. BLD-25. diff --git a/common/lib/xmodule/xmodule/js/spec/helper.js b/common/lib/xmodule/xmodule/js/spec/helper.js index de10cf914c..b680164249 100644 --- a/common/lib/xmodule/xmodule/js/spec/helper.js +++ b/common/lib/xmodule/xmodule/js/spec/helper.js @@ -16,7 +16,7 @@ ); Player.getDuration.andReturn(60); - Player.getAvailablePlaybackRates.andReturn(['0.50', '1.0', '1.50', '2.0']); + Player.getAvailablePlaybackRates.andReturn([0.50, 1.0, 1.50, 2.0]); return Player; }, diff --git a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js index 8c884ab51b..06d42d7520 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js @@ -204,6 +204,52 @@ }); }); + describe('YouTube video in FireFox will cue first', function () { + var oldUserAgent; + + beforeEach(function () { + oldUserAgent = window.navigator.userAgent; + window.navigator.userAgent = 'firefox'; + + state = jasmine.initializePlayer('video.html', { + start: 10, + end: 30 + }); + }); + + afterEach(function () { + window.navigator.userAgent = oldUserAgent; + }); + + it('cue is called, skipOnEndedStartEndReset is set', function () { + state.videoPlayer.updatePlayTime(10); + expect(state.videoPlayer.player.cueVideoById).toHaveBeenCalledWith('cogebirgzzM', 10); + expect(state.videoPlayer.skipOnEndedStartEndReset).toBe(true); + }); + + it('Handling cue state', function () { + spyOn(state.videoPlayer, 'play'); + + state.videoPlayer.startTime = 10; + state.videoPlayer.onStateChange({data: 5}); + + expect(state.videoPlayer.player.seekTo).toHaveBeenCalledWith(10, true); + expect(state.videoPlayer.play).toHaveBeenCalled(); + }); + + it('when cued, onEnded resets start and end time only the second time', function () { + state.videoPlayer.skipOnEndedStartEndReset = true; + state.videoPlayer.onEnded(); + expect(state.videoPlayer.startTime).toBe(10); + expect(state.videoPlayer.endTime).toBe(30); + + state.videoPlayer.skipOnEndedStartEndReset = undefined; + state.videoPlayer.onEnded(); + expect(state.videoPlayer.startTime).toBe(0); + expect(state.videoPlayer.endTime).toBe(null); + }); + }); + describe('checking start and end times', function () { var miniTestSuite = [ { diff --git a/common/lib/xmodule/xmodule/js/src/video/03_video_player.js b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js index cd47840646..ffd373718b 100644 --- a/common/lib/xmodule/xmodule/js/src/video/03_video_player.js +++ b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js @@ -447,12 +447,16 @@ function (HTML5Video, Resizer) { this.trigger('videoCaption.pause', null); } - // When only `startTime` is set, the video will play to the end - // starting at `startTime`. After the first time the video reaches the - // end, `startTime` and `endTime` are disabled. The video will play - // from start to the end on subsequent runs. - this.videoPlayer.startTime = 0; - this.videoPlayer.endTime = null; + if (this.videoPlayer.skipOnEndedStartEndReset) { + this.videoPlayer.skipOnEndedStartEndReset = undefined; + } else { + // When only `startTime` is set, the video will play to the end + // starting at `startTime`. After the first time the video reaches the + // end, `startTime` and `endTime` are disabled. The video will play + // from start to the end on subsequent runs. + this.videoPlayer.startTime = 0; + this.videoPlayer.endTime = null; + } // Sometimes `onEnded` events fires when `currentTime` not equal // `duration`. In this case, slider doesn't reach the end point of @@ -633,12 +637,21 @@ function (HTML5Video, Resizer) { case this.videoPlayer.PlayerState.ENDED: this.videoPlayer.onEnded(); break; + case this.videoPlayer.PlayerState.CUED: + this.videoPlayer.player.seekTo(this.videoPlayer.startTime, true); + // We need to call play() explicitly because after the call + // to functions cueVideoById() followed by seekTo() the video + // is in a PAUSED state. + // + // Why? This is how the YouTube API is implemented. + this.videoPlayer.play(); + break; } } function updatePlayTime(time) { var duration = this.videoPlayer.duration(), - durationChange, tempStartTime, tempEndTime; + durationChange, tempStartTime, tempEndTime, youTubeId; if ( duration > 0 && @@ -722,7 +735,38 @@ function (HTML5Video, Resizer) { this.videoPlayer.startTime > 0 && !(tempStartTime === 0 && tempEndTime === null) ) { - this.videoPlayer.player.seekTo(this.videoPlayer.startTime); + // After a bug came up (BLD-708: "In Firefox YouTube video with + // start time plays from 00:00:00") the video refused to play + // from start time, and only played from the beginning. + // + // It turned out that for some reason if Firefox you couldn't + // seek beyond some amount of time before the video loaded. + // Very strange, but in Chrome there is no such bug. + // + // HTML5 video sources play fine from start time in both Chrome + // and Firefox. + if (this.browserIsFirefox && this.videoType === 'youtube') { + if (this.currentPlayerMode === 'flash') { + youTubeId = this.youtubeId(); + } else { + youTubeId = this.youtubeId('1.0'); + } + + // When we will call cueVideoById() for some strange reason + // an ENDED event will be fired. It really does no damage + // except for the fact that the end time is reset to null. + // We do not want this. + // + // The flag `skipOnEndedStartEndReset` will notify the + // onEnded() callback for the ENDED event that just this + // once there is no need in resetting the start and end + // times + this.videoPlayer.skipOnEndedStartEndReset = true; + + this.videoPlayer.player.cueVideoById(youTubeId, this.videoPlayer.startTime); + } else { + this.videoPlayer.player.seekTo(this.videoPlayer.startTime); + } } // Reset back the actual startTime and endTime if they have been