mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update shared components
This commit is contained in:
parent
fb269362ff
commit
71811cb9e3
221 changed files with 32936 additions and 101 deletions
|
@ -63,6 +63,7 @@ class BufferController extends EventHandler {
|
|||
ms.removeEventListener('sourceclose', this.onmsc);
|
||||
// unlink MediaSource from video tag
|
||||
this.media.src = '';
|
||||
this.media.removeAttribute('src');
|
||||
this.mediaSource = null;
|
||||
this.media = null;
|
||||
this.pendingTracks = null;
|
||||
|
@ -280,9 +281,9 @@ class BufferController extends EventHandler {
|
|||
}
|
||||
} else {
|
||||
// QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
|
||||
// let's stop appending any segments, and report BUFFER_FULL error
|
||||
// let's stop appending any segments, and report BUFFER_FULL_ERROR error
|
||||
segments = [];
|
||||
event.details = ErrorDetails.BUFFER_FULL;
|
||||
event.details = ErrorDetails.BUFFER_FULL_ERROR;
|
||||
hls.trigger(Event.ERROR,event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,8 +196,11 @@ class StreamController extends EventHandler {
|
|||
if (levelDetails.live) {
|
||||
// check if requested position is within seekable boundaries :
|
||||
//logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${this.media.seeking}`);
|
||||
if (bufferEnd < Math.max(start,end-config.liveMaxLatencyDurationCount*levelDetails.targetduration)) {
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - config.liveSyncDurationCount * levelDetails.targetduration);
|
||||
let maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount*levelDetails.targetduration;
|
||||
|
||||
if (bufferEnd < Math.max(start, end - maxLatency)) {
|
||||
let targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration;
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - targetLatency);
|
||||
logger.log(`buffer end: ${bufferEnd} is located too far from the end of live sliding playlist, media position will be reseted to: ${this.seekAfterBuffered.toFixed(3)}`);
|
||||
bufferEnd = this.seekAfterBuffered;
|
||||
}
|
||||
|
@ -433,7 +436,7 @@ class StreamController extends EventHandler {
|
|||
if ((pos + maxHoleDuration) >= start && pos < end) {
|
||||
// play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length
|
||||
bufferStart = start;
|
||||
bufferEnd = end + maxHoleDuration;
|
||||
bufferEnd = end;
|
||||
bufferLen = bufferEnd - pos;
|
||||
} else if ((pos + maxHoleDuration) < start) {
|
||||
bufferStartNext = start;
|
||||
|
@ -444,11 +447,14 @@ class StreamController extends EventHandler {
|
|||
}
|
||||
|
||||
getBufferRange(position) {
|
||||
var i, range;
|
||||
for (i = this.bufferRange.length - 1; i >=0; i--) {
|
||||
range = this.bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
var i, range,
|
||||
bufferRange = this.bufferRange;
|
||||
if (bufferRange) {
|
||||
for (i = bufferRange.length - 1; i >=0; i--) {
|
||||
range = bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -770,7 +776,8 @@ class StreamController extends EventHandler {
|
|||
if (this.startFragRequested === false) {
|
||||
// if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)
|
||||
if (newDetails.live) {
|
||||
this.startPosition = Math.max(0, sliding + duration - this.config.liveSyncDurationCount * newDetails.targetduration);
|
||||
let targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration;
|
||||
this.startPosition = Math.max(0, sliding + duration - targetLatency);
|
||||
}
|
||||
this.nextLoadPosition = this.startPosition;
|
||||
}
|
||||
|
@ -1014,7 +1021,7 @@ class StreamController extends EventHandler {
|
|||
logger.warn(`mediaController: ${data.details} while loading frag,switch to ${data.fatal ? 'ERROR' : 'IDLE'} state ...`);
|
||||
this.state = data.fatal ? State.ERROR : State.IDLE;
|
||||
break;
|
||||
case ErrorDetails.BUFFER_FULL:
|
||||
case ErrorDetails.BUFFER_FULL_ERROR:
|
||||
// trigger a smooth level switch to empty buffers
|
||||
// also reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
|
||||
this.config.maxMaxBufferLength/=2;
|
||||
|
@ -1060,7 +1067,7 @@ _checkBuffer() {
|
|||
}
|
||||
var bufferInfo = this.bufferInfo(currentTime,0),
|
||||
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2),
|
||||
jumpThreshold = 0.2,
|
||||
jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end
|
||||
playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime;
|
||||
|
||||
if (this.stalled && playheadMoving) {
|
||||
|
@ -1083,16 +1090,17 @@ _checkBuffer() {
|
|||
}
|
||||
// if we are below threshold, try to jump if next buffer range is close
|
||||
if(bufferInfo.len <= jumpThreshold) {
|
||||
// no buffer available @ currentTime, check if next buffer is close (more than 5ms diff but within a config.maxSeekHole second range)
|
||||
// no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range)
|
||||
var nextBufferStart = bufferInfo.nextStart, delta = nextBufferStart-currentTime;
|
||||
if(nextBufferStart &&
|
||||
(delta < this.config.maxSeekHole) &&
|
||||
(delta > 0.005) &&
|
||||
(delta > 0) &&
|
||||
!media.seeking) {
|
||||
// next buffer is close ! adjust currentTime to nextBufferStart
|
||||
// this will ensure effective video decoding
|
||||
logger.log(`adjust currentTime from ${media.currentTime} to next buffered @ ${nextBufferStart}`);
|
||||
media.currentTime = nextBufferStart;
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -40,6 +40,8 @@ export const ErrorDetails = {
|
|||
BUFFER_APPENDING_ERROR: 'bufferAppendingError',
|
||||
// Identifier for a buffer stalled error event
|
||||
BUFFER_STALLED_ERROR: 'bufferStalledError',
|
||||
// Identifier for a buffer full error event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError'
|
||||
// Identifier for a buffer full event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError',
|
||||
// Identifier for a buffer seek over hole event
|
||||
BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole'
|
||||
};
|
||||
|
|
11
dashboard-ui/bower_components/hls.js/src/hls.js
vendored
11
dashboard-ui/bower_components/hls.js/src/hls.js
vendored
|
@ -47,6 +47,8 @@ class Hls {
|
|||
maxSeekHole: 2,
|
||||
liveSyncDurationCount:3,
|
||||
liveMaxLatencyDurationCount: Infinity,
|
||||
liveSyncDuration: undefined,
|
||||
liveMaxLatencyDuration: undefined,
|
||||
maxMaxBufferLength: 600,
|
||||
enableWorker: true,
|
||||
enableSoftwareAES: true,
|
||||
|
@ -84,6 +86,11 @@ class Hls {
|
|||
|
||||
constructor(config = {}) {
|
||||
var defaultConfig = Hls.DefaultConfig;
|
||||
|
||||
if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) {
|
||||
throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration');
|
||||
}
|
||||
|
||||
for (var prop in defaultConfig) {
|
||||
if (prop in config) { continue; }
|
||||
config[prop] = defaultConfig[prop];
|
||||
|
@ -93,6 +100,10 @@ class Hls {
|
|||
throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"');
|
||||
}
|
||||
|
||||
if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) {
|
||||
throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"');
|
||||
}
|
||||
|
||||
enableLogs(config.debug);
|
||||
this.config = config;
|
||||
// observer setup
|
||||
|
|
|
@ -38,12 +38,16 @@ class FragmentLoader extends EventHandler {
|
|||
}
|
||||
|
||||
loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event});
|
||||
}
|
||||
|
||||
loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag});
|
||||
}
|
||||
|
||||
|
|
|
@ -49,12 +49,16 @@ class KeyLoader extends EventHandler {
|
|||
}
|
||||
|
||||
loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event});
|
||||
}
|
||||
|
||||
loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag});
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class PlaylistLoader extends EventHandler {
|
|||
this.url = url;
|
||||
this.id = id1;
|
||||
this.id2 = id2;
|
||||
if(this.id === undefined) {
|
||||
if(this.id === null) {
|
||||
retry = config.manifestLoadingMaxRetry;
|
||||
timeout = config.manifestLoadingTimeOut;
|
||||
retryDelay = config.manifestLoadingRetryDelay;
|
||||
|
@ -265,7 +265,9 @@ class PlaylistLoader extends EventHandler {
|
|||
details = ErrorDetails.LEVEL_LOAD_ERROR;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2});
|
||||
}
|
||||
|
||||
|
@ -278,8 +280,10 @@ class PlaylistLoader extends EventHandler {
|
|||
details = ErrorDetails.LEVEL_LOAD_TIMEOUT;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2});
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ var URLHelper = {
|
|||
baseURL = baseURLQuerySplit[1];
|
||||
}
|
||||
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.-]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLProtocol = baseURLDomainSplit[3];
|
||||
var baseURLDomain = baseURLDomainSplit[1];
|
||||
var baseURLPath = baseURLDomainSplit[5];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue