Skip to content

Commit

Permalink
feat(playback watcher): Configurable live seekable window (#997)
Browse files Browse the repository at this point in the history
  • Loading branch information
dario-fiore authored Dec 2, 2020
1 parent f7b528c commit ad5c270
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Video.js Compatibility: 6.0, 7.0
- [customTagMappers](#customtagmappers)
- [cacheEncryptionKeys](#cacheencryptionkeys)
- [handlePartialData](#handlepartialdata)
- [liveRangeSafeTimeDelta](#liverangesafetimedelta)
- [Runtime Properties](#runtime-properties)
- [vhs.playlists.master](#vhsplaylistsmaster)
- [vhs.playlists.media](#vhsplaylistsmedia)
Expand Down Expand Up @@ -451,6 +452,11 @@ This option defaults to `false`.
* Default: `false`
* Use partial appends in the transmuxer and segment loader

##### liveRangeSafeTimeDelta
* Type: `number`,
* Default: [`SAFE_TIME_DELTA`](https://github.com/videojs/http-streaming/blob/e7cb63af010779108336eddb5c8fd138d6390e95/src/ranges.js#L17)
* Allow to re-define length (in seconds) of time delta when you compare current time and the end of the buffered range.

### Runtime Properties
Runtime properties are attached to the tech object when HLS is in
use. You can get a reference to the VHS source handler like this:
Expand Down
3 changes: 2 additions & 1 deletion src/playback-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export default class PlaybackWatcher {
this.tech_ = options.tech;
this.seekable = options.seekable;
this.allowSeeksWithinUnsafeLiveWindow = options.allowSeeksWithinUnsafeLiveWindow;
this.liveRangeSafeTimeDelta = options.liveRangeSafeTimeDelta;
this.media = options.media;

this.consecutiveUpdates = 0;
Expand Down Expand Up @@ -502,7 +503,7 @@ export default class PlaybackWatcher {
if (seekable.length &&
// can't fall before 0 and 0 seekable start identifies VOD stream
seekable.start(0) > 0 &&
currentTime < seekable.start(0) - Ranges.SAFE_TIME_DELTA) {
currentTime < seekable.start(0) - this.liveRangeSafeTimeDelta) {
return true;
}

Expand Down
23 changes: 17 additions & 6 deletions src/videojs-http-streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from './playlist-selectors.js';
import {isAudioCodec, isVideoCodec, browserSupportsCodec} from '@videojs/vhs-utils/dist/codecs.js';
import logger from './util/logger';
import {SAFE_TIME_DELTA} from './ranges';

// IMPORTANT:
// keep these at the bottom they are replaced at build time
Expand Down Expand Up @@ -673,7 +674,8 @@ class VhsHandler extends Component {
'handlePartialData',
'playlistSelector',
'initialPlaylistSelector',
'experimentalBufferBasedABR'
'experimentalBufferBasedABR',
'liveRangeSafeTimeDelta'
].forEach((option) => {
if (typeof this.source_[option] !== 'undefined') {
this.options_[option] = this.source_[option];
Expand Down Expand Up @@ -706,11 +708,20 @@ class VhsHandler extends Component {
};

this.masterPlaylistController_ = new MasterPlaylistController(this.options_);
this.playbackWatcher_ = new PlaybackWatcher(videojs.mergeOptions(this.options_, {
seekable: () => this.seekable(),
media: () => this.masterPlaylistController_.media(),
masterPlaylistController: this.masterPlaylistController_
}));

const playbackWatcherOptions = videojs.mergeOptions(
{
liveRangeSafeTimeDelta: SAFE_TIME_DELTA
},
this.options_,
{
seekable: () => this.seekable(),
media: () => this.masterPlaylistController_.media(),
masterPlaylistController: this.masterPlaylistController_
}
);

this.playbackWatcher_ = new PlaybackWatcher(playbackWatcherOptions);

this.masterPlaylistController_.on('error', () => {
const player = videojs.players[this.tech_.options_.playerId];
Expand Down
20 changes: 20 additions & 0 deletions test/playback-watcher.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../src/playback-watcher';
// needed for plugin registration
import '../src/videojs-http-streaming';
import { SAFE_TIME_DELTA } from '../src/ranges';

let monitorCurrentTime_;

Expand Down Expand Up @@ -1184,6 +1185,8 @@ QUnit.test('skips gap from muxed video underflow', function(assert) {
});

QUnit.test('detects live window falloff', function(assert) {
this.playbackWatcher.liveRangeSafeTimeDelta = SAFE_TIME_DELTA;

const beforeSeekableWindow_ =
this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher);

Expand Down Expand Up @@ -1222,6 +1225,23 @@ QUnit.test('detects live window falloff', function(assert) {
);
});

QUnit.test('respects liveRangeSafeTimeDelta flag', function(assert) {
this.playbackWatcher.liveRangeSafeTimeDelta = 1;

const beforeSeekableWindow_ =
this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher);

assert.ok(
beforeSeekableWindow_(videojs.createTimeRanges([[12, 20]]), 10),
'true if playlist live and current time before seekable'
);

assert.ok(
!beforeSeekableWindow_(videojs.createTimeRanges([]), 10),
'false if no seekable range'
);
});

QUnit.test('detects beyond seekable window for VOD', function(assert) {
const playlist = {
endList: true,
Expand Down

0 comments on commit ad5c270

Please sign in to comment.