nsplayer
Version:
NSPlayer, a player which supports quality list of dash and hls
233 lines (180 loc) • 7.53 kB
JavaScript
'use strict';
var global = typeof self !== 'undefined' ? self : globalThis;
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var common = require('@newstudios/common');
var index = require('./index-773e68b1.js');
var dashjs = require('dashjs');
require('delegates');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
function getBytesLength(request) {
return request.trace.reduce((a, b) => a + b.b[0], 0);
}
function getTime(request) {
return request.trace.reduce((a, b) => a + b.d, 0);
}
function caculateBandWidthFor(player, type) {
const metrics = player.getDashMetrics();
const requests = metrics.getHttpRequests(type);
const lastCount = 4;
const requestWindow = requests.slice(-lastCount * 5).filter(req => {
return req.type === 'MediaSegment' && req._stream === type && req.trace.length > 1 && req._tfinish.getTime() - req.tresponse.getTime() > 0;
}).slice(-lastCount);
if (requestWindow.length === 0) {
return 0;
}
const downloadLengths = requestWindow.map(req => getBytesLength(req) * 8);
const downloadTimes = requestWindow.map(req => getTime(req) / 1000);
const size = downloadLengths.reduce((a, b) => a + b, 0);
const time = downloadTimes.reduce((a, b) => a + b, 0);
return Math.round(size / time);
}
function caculateBandWidth(player) {
return caculateBandWidthFor(player, 'video') + caculateBandWidthFor(player, 'audio');
}
class DashPlayer extends index.CorePlayer {
static setDefaultMediaPlayerFactory(factory) {
DashPlayer._mediaPlayerFactory = factory;
}
constructor(video, source, fastSwitch = true, capLevelToPlayerSize = false) {
super(video, source);
_defineProperty__default["default"](this, "_mediaType", 'video');
_defineProperty__default["default"](this, "_currentLevelIndex", 0);
_defineProperty__default["default"](this, "_initialized", false);
this._fastSwitchEnabled = fastSwitch;
this._dashPlayer = DashPlayer._mediaPlayerFactory.create();
this._dashPlayer.updateSettings({
streaming: {
buffer: {
fastSwitchEnabled: this._fastSwitchEnabled
},
abr: {
limitBitrateByPortal: capLevelToPlayerSize,
usePixelRatioInLimitBitrateByPortal: capLevelToPlayerSize
}
}
}); // debug error
this.debugError();
this._register(common.toDisposable(() => this._dashPlayer.reset()));
}
debugError() {
const onError = common.Event.fromNodeEventEmitter(this._dashPlayer, dashjs.MediaPlayer.events.ERROR);
const onPlaybackError = common.Event.fromNodeEventEmitter(this._dashPlayer, dashjs.MediaPlayer.events.PLAYBACK_ERROR);
this._register(onError(err => console.info(err)));
this._register(onPlaybackError(err => console.info(err)));
}
get levels() {
return this._initialized ? this._dashPlayer.getBitrateInfoListFor(this._mediaType) : [];
}
get currentLevel() {
return this.levels[this._currentLevelIndex];
}
get nextLevel() {
return this._initialized ? this.levels[this._dashPlayer.getQualityFor(this._mediaType)] : undefined;
}
get autoQualityEnabled() {
var _this$_dashPlayer$get, _this$_dashPlayer$get2;
const autoSwitchBitrate = (_this$_dashPlayer$get = this._dashPlayer.getSettings().streaming) === null || _this$_dashPlayer$get === void 0 ? void 0 : (_this$_dashPlayer$get2 = _this$_dashPlayer$get.abr) === null || _this$_dashPlayer$get2 === void 0 ? void 0 : _this$_dashPlayer$get2.autoSwitchBitrate;
if (autoSwitchBitrate) {
return typeof autoSwitchBitrate[this._mediaType] === 'boolean' ? autoSwitchBitrate[this._mediaType] : true;
}
return true;
}
levelToQuality(bitrateInfo) {
const level = {
bitrate: bitrateInfo.bitrate,
width: bitrateInfo.width,
height: bitrateInfo.height,
type: bitrateInfo.mediaType
};
return level;
}
findLevelIndexByQualityLevel(playLevel) {
const levels = this.levels; // bitrate match
const idx = levels.findIndex(level => level.bitrate === playLevel.bitrate);
if (idx >= 0) {
return idx;
} // short side match
const shortSide = Math.min(playLevel.width, playLevel.height);
return levels.findIndex(level => Math.min(level.width, level.height) === shortSide);
}
setAutoQualityState(auto) {
const dashPlayer = this._dashPlayer;
dashPlayer.updateSettings({
streaming: {
buffer: {
fastSwitchEnabled: this._fastSwitchEnabled
},
abr: {
autoSwitchBitrate: {
[this._mediaType]: auto
}
}
}
});
}
setNextLevelIndex(index) {
const dashPlayer = this._dashPlayer;
if (index >= 0) {
dashPlayer.setQualityFor(this._mediaType, index);
}
}
onInit(video, source) {
const dashPlayer = this._dashPlayer;
dashPlayer.initialize(video, source.src, this.video.autoplay);
this._initialized = true;
this.log('onInit', 'initialized');
const disposables = this._register(new common.DisposableStore());
const onManifestParsed = common.Event.fromNodeEventEmitter(dashPlayer, dashjs.MediaPlayer.events.STREAM_INITIALIZED);
const onLevelSwitched = common.Event.filter(common.Event.fromNodeEventEmitter(dashPlayer, dashjs.MediaPlayer.events.QUALITY_CHANGE_RENDERED), evt => evt.mediaType === this._mediaType);
const onLevelSwitching = common.Event.filter(common.Event.fromNodeEventEmitter(dashPlayer, dashjs.MediaPlayer.events.QUALITY_CHANGE_REQUESTED), evt => evt.mediaType === this._mediaType);
onManifestParsed(this.updatePlayList, this, disposables);
onManifestParsed(this.setReady, this, disposables);
onLevelSwitching(this.updateNextQualityLevel, this, disposables);
onLevelSwitched(evt => {
this._currentLevelIndex = evt.newQuality;
this.updateQualityLevel();
}, null, disposables);
}
setInitialBitrate(bitrate) {
const dashPlayer = this._dashPlayer;
dashPlayer.updateSettings({
streaming: {
buffer: {
fastSwitchEnabled: this._fastSwitchEnabled
},
abr: {
initialBitrate: {
[this._mediaType]: bitrate / 1000
}
}
}
});
}
setCapLevelToPlayerSize(capLevelToPlayerSize) {
const dashPlayer = this._dashPlayer;
dashPlayer.updateSettings({
streaming: {
abr: {
limitBitrateByPortal: capLevelToPlayerSize,
usePixelRatioInLimitBitrateByPortal: capLevelToPlayerSize
}
}
});
}
get capLevelToPlayerSize() {
var _this$_dashPlayer$get3, _this$_dashPlayer$get4, _this$_dashPlayer$get5;
return (_this$_dashPlayer$get3 = (_this$_dashPlayer$get4 = this._dashPlayer.getSettings().streaming) === null || _this$_dashPlayer$get4 === void 0 ? void 0 : (_this$_dashPlayer$get5 = _this$_dashPlayer$get4.abr) === null || _this$_dashPlayer$get5 === void 0 ? void 0 : _this$_dashPlayer$get5.limitBitrateByPortal) !== null && _this$_dashPlayer$get3 !== void 0 ? _this$_dashPlayer$get3 : false;
}
get bandwidthEstimate() {
return caculateBandWidth(this._dashPlayer);
}
get name() {
return `DASHPlayer (${this._dashPlayer.getVersion()})`;
}
get supportAutoQuality() {
return true;
}
}
_defineProperty__default["default"](DashPlayer, "_mediaPlayerFactory", dashjs.MediaPlayer());
exports.DashPlayer = DashPlayer;