Skip to content

Commit

Permalink
feat: Add useBandwidthFromLocalStorage option (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
gesinger committed Nov 13, 2018
1 parent 970e3ce commit 60c88ae
Show file tree
Hide file tree
Showing 4 changed files with 344 additions and 4 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Video.js Compatibility: 6.0, 7.0
- [overrideNative](#overridenative)
- [blacklistDuration](#blacklistduration)
- [bandwidth](#bandwidth)
- [useBandwidthFromLocalStorage](#usebandwidthfromlocalstorage)
- [enableLowInitialPlaylist](#enablelowinitialplaylist)
- [limitRenditionByPlayerDimensions](#limitrenditionbyplayerdimensions)
- [smoothQualityChange](#smoothqualitychange)
Expand Down Expand Up @@ -327,6 +328,12 @@ When the `bandwidth` property is set (bits per second), it will be used in
the calculation for initial playlist selection, before more bandwidth
information is seen by the player.

##### useBandwidthFromLocalStorage
* Type: `boolean`
* can be used as an initialization option
If true, `bandwidth` and `throughput` values are stored in and retrieved from local
storage on startup (for initial rendition selection). This setting is `false` by default.

##### enableLowInitialPlaylist
* Type: `boolean`
* can be used as an initialization option
Expand Down Expand Up @@ -586,6 +593,8 @@ Each of the following usage events are fired once per source if (and when) detec
| hls-demuxed | audio and video are demuxed by default |
| hls-alternate-audio | alternate audio available in the master manifest |
| hls-playlist-cue-tags | a playlist used cue tags (see useCueTags(#usecuetags) for details) |
| hls-bandwidth-from-local-storage | starting bandwidth was retrieved from local storage (see useBandwidthFromLocalStorage(#useBandwidthFromLocalStorage) for details) |
| hls-throughput-from-local-storage | starting throughput was retrieved from local storage (see useBandwidthFromLocalStorage(#useBandwidthFromLocalStorage) for details) |

#### Use Stats

Expand Down
82 changes: 79 additions & 3 deletions src/videojs-http-streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ const Hls = {
});
});

export const LOCAL_STORAGE_KEY = 'videojs-vhs';

const simpleTypeFromSourceType = (type) => {
const mpegurlRE = /^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i;

Expand Down Expand Up @@ -190,6 +192,47 @@ const setupEmeOptions = (hlsHandler) => {
}
};

const getVhsLocalStorage = () => {
if (!window.localStorage) {
return null;
}

const storedObject = window.localStorage.getItem(LOCAL_STORAGE_KEY);

if (!storedObject) {
return null;
}

try {
return JSON.parse(storedObject);
} catch (e) {
// someone may have tampered with the value
return null;
}
};

const updateVhsLocalStorage = (options) => {
if (!window.localStorage) {
return false;
}

let objectToStore = getVhsLocalStorage();

objectToStore = objectToStore ? videojs.mergeOptions(objectToStore, options) : options;

try {
window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(objectToStore));
} catch (e) {
// Throws if storage is full (e.g., always on iOS 5+ Safari private mode, where
// storage is set to 0).
// https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem#Exceptions
// No need to perform any operation.
return false;
}

return objectToStore;
};

/**
* Whether the browser has built-in HLS support.
*/
Expand Down Expand Up @@ -348,13 +391,31 @@ class HlsHandler extends Component {
this.options_.withCredentials = this.options_.withCredentials || false;
this.options_.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions === false ? false : true;
this.options_.smoothQualityChange = this.options_.smoothQualityChange || false;
this.options_.useBandwidthFromLocalStorage =
typeof this.source_.useBandwidthFromLocalStorage !== 'undefined' ?
this.source_.useBandwidthFromLocalStorage :
this.options_.useBandwidthFromLocalStorage || false;

if (typeof this.options_.blacklistDuration !== 'number') {
this.options_.blacklistDuration = 5 * 60;
}

// start playlist selection at a reasonable bandwidth for
// broadband internet (0.5 MB/s) or mobile (0.0625 MB/s)
if (typeof this.options_.bandwidth !== 'number') {
if (this.options_.useBandwidthFromLocalStorage) {
const storedObject = getVhsLocalStorage();

if (storedObject && storedObject.bandwidth) {
this.options_.bandwidth = storedObject.bandwidth;
this.tech_.trigger({type: 'usage', name: 'hls-bandwidth-from-local-storage'});
}
if (storedObject && storedObject.throughput) {
this.options_.throughput = storedObject.throughput;
this.tech_.trigger({type: 'usage', name: 'hls-throughput-from-local-storage'});
}
}
}
// if bandwidth was not set by options or pulled from local storage, start playlist
// selection at a reasonable bandwidth
if (typeof this.options_.bandwidth !== 'number') {
this.options_.bandwidth = Config.INITIAL_BANDWIDTH;
}
Expand All @@ -372,7 +433,6 @@ class HlsHandler extends Component {
}
});

this.bandwidth = this.options_.bandwidth;
this.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions;
}
/**
Expand Down Expand Up @@ -492,6 +552,13 @@ class HlsHandler extends Component {
}
});

if (this.options_.bandwidth) {
this.bandwidth = this.options_.bandwidth;
}
if (this.options_.throughput) {
this.throughput = this.options_.throughput;
}

Object.defineProperties(this.stats, {
bandwidth: {
get: () => this.bandwidth || 0,
Expand Down Expand Up @@ -570,6 +637,15 @@ class HlsHandler extends Component {
this.tech_.one('canplay',
this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_));

this.tech_.on('bandwidthupdate', () => {
if (this.options_.useBandwidthFromLocalStorage) {
updateVhsLocalStorage({
bandwidth: this.bandwidth,
throughput: Math.round(this.throughput)
});
}
});

this.masterPlaylistController_.on('selectedinitialmedia', () => {
// Add the manual rendition mix-in to HlsHandler
renditionSelectionMixin(this);
Expand Down
1 change: 1 addition & 0 deletions test/master-playlist-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ QUnit.module('MasterPlaylistController', {
this.env.restore();
this.mse.restore();
videojs.Hls.supportsNativeHls = this.origSupportsNativeHls;
window.localStorage.clear();
videojs.browser = this.oldBrowser;
this.player.dispose();
}
Expand Down
Loading

0 comments on commit 60c88ae

Please sign in to comment.