Browse Source
Immediately reload the source when an error is emitted by the player (#902)
Immediately reload the source when an error is emitted by the player (#902)
* Immediately reload the source when an error is emitted by the player * Fixed linting opinions * Updated pluging to use the Tech for currentSourcepull/6/head

committed by
David LaPalomento

4 changed files with 142 additions and 1 deletions
-
34src/reload-source-on-error.js
-
2src/videojs-contrib-hls.js
-
105test/reload-source-on-error.test.js
-
2test/test-helpers.js
@ -0,0 +1,34 @@ |
|||
/** |
|||
* Reload the source when an error is detected as long as there |
|||
* wasn't an error previously within the last 30 seconds |
|||
*/ |
|||
const reloadSourceOnError = function() { |
|||
const player = this; |
|||
let lastCalled = 0; |
|||
const reloadSource = function() { |
|||
let tech = player.tech({ IWillNotUseThisInPlugins: true }); |
|||
let sourceObj = tech.currentSource_; |
|||
let seekTo = (player.duration() !== Infinity && player.currentTime()) || 0; |
|||
|
|||
if (Date.now() - lastCalled < 30 * 1000) { |
|||
return; |
|||
} |
|||
lastCalled = Date.now(); |
|||
|
|||
if (seekTo) { |
|||
player.one('loadedmetadata', () => { |
|||
player.currentTime(seekTo); |
|||
}); |
|||
} |
|||
|
|||
player.src(sourceObj); |
|||
player.play(); |
|||
}; |
|||
|
|||
player.on('error', reloadSource); |
|||
player.on('dispose', () => { |
|||
player.off('error', reloadSource); |
|||
}); |
|||
}; |
|||
|
|||
export default reloadSourceOnError; |
@ -0,0 +1,105 @@ |
|||
import QUnit from 'qunit'; |
|||
import videojs from 'video.js'; |
|||
import sinon from 'sinon'; |
|||
import reloadSourceOnError from '../src/reload-source-on-error'; |
|||
|
|||
QUnit.module('ReloadSourceOnError', { |
|||
beforeEach() { |
|||
this.clock = sinon.useFakeTimers(); |
|||
|
|||
// setup a player
|
|||
this.player = new videojs.EventTarget(); |
|||
this.player.currentValues = { |
|||
currentTime: 10, |
|||
duration: 12 |
|||
}; |
|||
|
|||
this.tech = { |
|||
currentSource_: { |
|||
src: 'thisisasource.m3u8', |
|||
type: 'doesn\'t/matter' |
|||
} |
|||
}; |
|||
|
|||
this.player.tech = () => { |
|||
return this.tech; |
|||
}; |
|||
|
|||
this.player.duration = () => { |
|||
return this.player.currentValues.duration; |
|||
}; |
|||
|
|||
this.player.src = (source) => { |
|||
this.player.currentValues.currentTime = 0; |
|||
this.player.src.calledWith.push(source); |
|||
}; |
|||
this.player.src.calledWith = []; |
|||
|
|||
this.player.currentTime = (time) => { |
|||
if (time) { |
|||
this.player.currentTime.calledWith.push(time); |
|||
this.player.currentValues.currentTime = time; |
|||
} |
|||
return this.player.currentValues.currentTime; |
|||
}; |
|||
this.player.currentTime.calledWith = []; |
|||
|
|||
this.player.play = () => { |
|||
this.player.play.called++; |
|||
}; |
|||
this.player.play.called = 0; |
|||
|
|||
reloadSourceOnError.call(this.player); |
|||
this.clock.tick(60 * 1000); |
|||
}, |
|||
|
|||
afterEach() { |
|||
this.clock.restore(); |
|||
} |
|||
}); |
|||
|
|||
QUnit.test('triggers on player error', function() { |
|||
this.player.trigger('error', -2); |
|||
|
|||
QUnit.equal(this.player.src.calledWith.length, 1, 'player.src was called'); |
|||
QUnit.deepEqual(this.player.src.calledWith[0], this.tech.currentSource_, 'player.src was called with player.currentSource'); |
|||
}); |
|||
|
|||
QUnit.test('seeks to currentTime in VOD', function() { |
|||
this.player.trigger('error', -2); |
|||
this.player.trigger('loadedmetadata'); |
|||
|
|||
QUnit.equal(this.player.currentTime.calledWith.length, 1, 'player.currentTime was called'); |
|||
QUnit.deepEqual(this.player.currentTime.calledWith[0], 10, 'player.currentTime was called with the right value'); |
|||
}); |
|||
|
|||
QUnit.test('doesn\'t seek to currentTime in live', function() { |
|||
this.player.currentValues.duration = Infinity; |
|||
|
|||
this.player.trigger('error', -2); |
|||
this.player.trigger('loadedmetadata'); |
|||
|
|||
QUnit.equal(this.player.currentTime.calledWith.length, 0, 'player.currentTime was not called'); |
|||
QUnit.deepEqual(this.player.currentTime(), 0, 'player.currentTime is still zero'); |
|||
}); |
|||
|
|||
QUnit.test('only allows a retry once every 30 seconds', function() { |
|||
this.player.trigger('error', -2); |
|||
this.player.trigger('loadedmetadata'); |
|||
|
|||
QUnit.equal(this.player.src.calledWith.length, 1, 'player.src was called once'); |
|||
|
|||
// Advance 60 seconds
|
|||
this.clock.tick(60 * 1000); |
|||
this.player.trigger('error', -2); |
|||
this.player.trigger('loadedmetadata'); |
|||
|
|||
QUnit.equal(this.player.src.calledWith.length, 2, 'player.src was called twice'); |
|||
|
|||
// Advance 29 seconds
|
|||
this.clock.tick(29 * 1000); |
|||
this.player.trigger('error', -2); |
|||
this.player.trigger('loadedmetadata'); |
|||
|
|||
QUnit.equal(this.player.src.calledWith.length, 2, 'player.src was called twice'); |
|||
}); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue