Commit d33c4fc8 by Valera Rozuvan

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.
parent 0c7e2036
...@@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes, ...@@ -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 in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected. 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: Fix bug when image response in Firefox does not retain input. BLD-711.
Blades: Give numerical response tolerance as a range. BLD-25. Blades: Give numerical response tolerance as a range. BLD-25.
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
); );
Player.getDuration.andReturn(60); 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; return Player;
}, },
......
...@@ -204,6 +204,52 @@ ...@@ -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 () { describe('checking start and end times', function () {
var miniTestSuite = [ var miniTestSuite = [
{ {
......
...@@ -447,12 +447,16 @@ function (HTML5Video, Resizer) { ...@@ -447,12 +447,16 @@ function (HTML5Video, Resizer) {
this.trigger('videoCaption.pause', null); this.trigger('videoCaption.pause', null);
} }
// When only `startTime` is set, the video will play to the end if (this.videoPlayer.skipOnEndedStartEndReset) {
// starting at `startTime`. After the first time the video reaches the this.videoPlayer.skipOnEndedStartEndReset = undefined;
// end, `startTime` and `endTime` are disabled. The video will play } else {
// from start to the end on subsequent runs. // When only `startTime` is set, the video will play to the end
this.videoPlayer.startTime = 0; // starting at `startTime`. After the first time the video reaches the
this.videoPlayer.endTime = null; // 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 // Sometimes `onEnded` events fires when `currentTime` not equal
// `duration`. In this case, slider doesn't reach the end point of // `duration`. In this case, slider doesn't reach the end point of
...@@ -633,12 +637,21 @@ function (HTML5Video, Resizer) { ...@@ -633,12 +637,21 @@ function (HTML5Video, Resizer) {
case this.videoPlayer.PlayerState.ENDED: case this.videoPlayer.PlayerState.ENDED:
this.videoPlayer.onEnded(); this.videoPlayer.onEnded();
break; 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) { function updatePlayTime(time) {
var duration = this.videoPlayer.duration(), var duration = this.videoPlayer.duration(),
durationChange, tempStartTime, tempEndTime; durationChange, tempStartTime, tempEndTime, youTubeId;
if ( if (
duration > 0 && duration > 0 &&
...@@ -722,7 +735,38 @@ function (HTML5Video, Resizer) { ...@@ -722,7 +735,38 @@ function (HTML5Video, Resizer) {
this.videoPlayer.startTime > 0 && this.videoPlayer.startTime > 0 &&
!(tempStartTime === 0 && tempEndTime === null) !(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 // Reset back the actual startTime and endTime if they have been
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment