mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-18 03:18:19 -07:00
reduce traffic from play to feature
This commit is contained in:
parent
7b80b2ea32
commit
58cebe2486
@ -16,12 +16,12 @@
|
||||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.1.121",
|
||||
"_release": "1.1.121",
|
||||
"version": "1.1.125",
|
||||
"_release": "1.1.125",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.1.121",
|
||||
"commit": "5785022dd5fdf3633606d4c84d59f52ffa61251d"
|
||||
"tag": "1.1.125",
|
||||
"commit": "de914c8db94b994ea45746626ba73bfb72a594a0"
|
||||
},
|
||||
"_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git",
|
||||
"_target": "^1.1.51",
|
||||
|
@ -1408,6 +1408,26 @@
|
||||
return self.getJSON(url);
|
||||
};
|
||||
|
||||
self.getPlaybackInfo = function(itemId, options, deviceProfile) {
|
||||
|
||||
var postData = {
|
||||
DeviceProfile: deviceProfile
|
||||
};
|
||||
|
||||
return self.ajax({
|
||||
url: self.getUrl('Items/' + itemId + '/PlaybackInfo', options),
|
||||
type: 'POST',
|
||||
data: JSON.stringify(postData),
|
||||
contentType: "application/json",
|
||||
dataType: "json"
|
||||
});
|
||||
};
|
||||
|
||||
self.getIntros = function(itemId) {
|
||||
|
||||
return self.getJSON(self.getUrl('Users/' + self.getCurrentUserId() + '/Items/' + itemId + '/Intros'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the directory contents of a path on the server
|
||||
*/
|
||||
|
@ -298,7 +298,65 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
function getPlaybackInfo(itemId, options, deviceProfile) {
|
||||
|
||||
return localassetmanager.getLocalItem(apiclientcore.serverId(), stripStart(itemId, localPrefix)).then(function (item) {
|
||||
|
||||
// TODO: This was already done during the sync process, right? If so, remove it
|
||||
var mediaSources = item.Item.MediaSources.map(function (m) {
|
||||
m.SupportsDirectPlay = true;
|
||||
m.SupportsDirectStream = false;
|
||||
m.SupportsTranscoding = false;
|
||||
return m;
|
||||
});
|
||||
|
||||
return {
|
||||
MediaSources: mediaSources
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// "Override" methods
|
||||
|
||||
self.detectBitrate = function () {
|
||||
return Promise.reject();
|
||||
};
|
||||
|
||||
self.reportPlaybackStart = function (options) {
|
||||
|
||||
if (!options) {
|
||||
throw new Error("null options");
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
self.reportPlaybackProgress = function (options) {
|
||||
|
||||
if (!options) {
|
||||
throw new Error("null options");
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
self.reportPlaybackStopped = function (options) {
|
||||
|
||||
if (!options) {
|
||||
throw new Error("null options");
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
self.getIntros = function (itemId) {
|
||||
|
||||
return Promise.resolve({
|
||||
Items: [],
|
||||
TotalRecordCount: 0
|
||||
});
|
||||
};
|
||||
|
||||
self.getUserViews = getUserViews;
|
||||
self.getItems = getItems;
|
||||
self.getItem = getItem;
|
||||
@ -309,6 +367,7 @@
|
||||
self.getSimilarItems = getSimilarItems;
|
||||
self.updateFavoriteStatus = updateFavoriteStatus;
|
||||
self.getScaledImageUrl = getScaledImageUrl;
|
||||
self.getPlaybackInfo = getPlaybackInfo;
|
||||
};
|
||||
|
||||
});
|
@ -14,12 +14,12 @@
|
||||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.4.484",
|
||||
"_release": "1.4.484",
|
||||
"version": "1.4.489",
|
||||
"_release": "1.4.489",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.4.484",
|
||||
"commit": "ed56575477c1115b8583613135206ed49841c70f"
|
||||
"tag": "1.4.489",
|
||||
"commit": "4b7b914b55dba588627036dee142a3358cb1c282"
|
||||
},
|
||||
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
|
||||
"_target": "^1.2.1",
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
function forceRefresh(loading) {
|
||||
|
||||
var elem = document.body;
|
||||
var elem = this.parentNode;
|
||||
|
||||
elem.style.webkitAnimationName = 'repaintChrome';
|
||||
elem.style.webkitAnimationDelay = (loading === true ? '500ms' : '');
|
||||
@ -66,7 +66,7 @@
|
||||
|
||||
if (enableRefreshHack) {
|
||||
|
||||
forceRefresh(true);
|
||||
forceRefresh.call(this, true);
|
||||
dom.addEventListener(this, 'click', forceRefresh, {
|
||||
passive: true
|
||||
});
|
||||
|
@ -1519,7 +1519,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g
|
||||
|
||||
var apiClient = connectionManager.getApiClient(firstItem.ServerId);
|
||||
|
||||
return apiClient.getJSON(apiClient.getUrl('Users/' + apiClient.getCurrentUserId() + '/Items/' + firstItem.Id + '/Intros')).then(function (intros) {
|
||||
return apiClient.getIntros(firstItem.Id).then(function (intros) {
|
||||
|
||||
items = intros.Items.concat(items);
|
||||
currentPlayOptions = options;
|
||||
@ -1895,6 +1895,11 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g
|
||||
playMethod = 'DirectPlay';
|
||||
}
|
||||
|
||||
// Fallback (used for offline items)
|
||||
if (!mediaUrl && mediaSource.SupportsDirectPlay) {
|
||||
mediaUrl = mediaSource.Path;
|
||||
}
|
||||
|
||||
var resultInfo = {
|
||||
url: mediaUrl,
|
||||
mimeType: contentType,
|
||||
@ -2013,10 +2018,6 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g
|
||||
|
||||
function getPlaybackInfo(apiClient, itemId, deviceProfile, maxBitrate, startPosition, mediaSource, audioStreamIndex, subtitleStreamIndex, liveStreamId) {
|
||||
|
||||
var postData = {
|
||||
DeviceProfile: deviceProfile
|
||||
};
|
||||
|
||||
var query = {
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
StartTimeTicks: startPosition || 0
|
||||
@ -2038,14 +2039,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g
|
||||
query.MaxStreamingBitrate = maxBitrate;
|
||||
}
|
||||
|
||||
return apiClient.ajax({
|
||||
url: apiClient.getUrl('Items/' + itemId + '/PlaybackInfo', query),
|
||||
type: 'POST',
|
||||
data: JSON.stringify(postData),
|
||||
contentType: "application/json",
|
||||
dataType: "json"
|
||||
|
||||
});
|
||||
return apiClient.getPlaybackInfo(itemId, query, deviceProfile);
|
||||
}
|
||||
|
||||
function getOptimalMediaSource(apiClient, item, versions) {
|
||||
@ -2081,7 +2075,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g
|
||||
return s.SupportsTranscoding;
|
||||
})[0];
|
||||
|
||||
return optimalVersion;
|
||||
return optimalVersion || versions[0];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"HeaderRemoteControl": "Remote Control",
|
||||
"Disconnect": "Disconnect",
|
||||
"EnableDisplayMirroring": "Enable display mirroring",
|
||||
"HeaderSelectPlayer": "Select Player",
|
||||
"Disconnect": "\u0410\u0436\u044b\u0440\u0430\u0442\u0443",
|
||||
"EnableDisplayMirroring": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443\u0434\u0456\u04a3 \u0442\u0435\u043b\u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u049b\u043e\u0441\u0443",
|
||||
"HeaderSelectPlayer": "\u041e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u0443",
|
||||
"MessageUnlockAppWithPurchaseOrSupporter": "\u041e\u0441\u044b \u049b\u04b1\u0440\u0430\u043c\u0434\u0430\u0441\u0442\u044b \u0431\u0456\u0440 \u0436\u043e\u043b\u0493\u044b \u0441\u0430\u0442\u044b\u043f \u0430\u043b\u0443, \u043d\u0435\u043c\u0435\u0441\u0435 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 Emby Premiere \u0436\u0430\u0437\u044b\u043b\u044b\u043c\u044b \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u04b1\u0440\u0441\u0430\u0443\u0434\u0430\u043d \u0431\u043e\u0441\u0430\u0442\u0443.",
|
||||
"MessageUnlockAppWithSupporter": "\u041e\u0441\u044b \u049b\u04b1\u0440\u0430\u043c\u0434\u0430\u0441\u0442\u044b \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 Emby Premiere \u0436\u0430\u0437\u044b\u043b\u044b\u043c\u044b \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u04b1\u0440\u0441\u0430\u0443\u0434\u0430\u043d \u0431\u043e\u0441\u0430\u0442\u0443.",
|
||||
"MessageToValidateSupporter": "\u0415\u0433\u0435\u0440 \u0441\u0456\u0437\u0434\u0435 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 Emby Premiere \u0436\u0430\u0437\u044b\u043b\u044b\u043c\u044b \u0431\u043e\u043b\u0441\u0430, Emby Server \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d\u0434\u0430\u0493\u044b Emby Premiere \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u044b\u043f \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d\u0456\u043d\u0435 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437. \u0411\u04b1\u043b \u0431\u0430\u0441\u0442\u044b \u043c\u04d9\u0437\u0456\u0440\u0434\u0435 Emby Premiere \u0434\u0435\u0433\u0435\u043d\u0434\u0456 \u043d\u04b1\u049b\u044b\u043f \u049b\u0430\u0442\u044b\u043d\u0430\u0443\u043b\u044b.",
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"HeaderRemoteControl": "Remote Control",
|
||||
"Disconnect": "Disconnect",
|
||||
"EnableDisplayMirroring": "Enable display mirroring",
|
||||
"HeaderSelectPlayer": "Select Player",
|
||||
"Disconnect": "\u0420\u0430\u0437\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f",
|
||||
"EnableDisplayMirroring": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
|
||||
"HeaderSelectPlayer": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044f",
|
||||
"MessageUnlockAppWithPurchaseOrSupporter": "\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0439 \u043e\u043f\u043b\u0430\u0442\u044b, \u0438\u043b\u0438 \u0441 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 Emby Premiere .",
|
||||
"MessageUnlockAppWithSupporter": "\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 Emby Premiere.",
|
||||
"MessageToValidateSupporter": "\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 Emby Premiere, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e Emby Premiere \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0432 \u0432\u0430\u0448\u0435\u0439 \u041f\u0430\u043d\u0435\u043b\u0438 Emby Server, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e \u0449\u0435\u043b\u0447\u043a\u0443 \u043f\u043e Emby Premiere \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u043c\u0435\u043d\u044e.",
|
||||
@ -361,7 +361,7 @@
|
||||
"MessageDidYouKnowCinemaMode": "\u0417\u043d\u0430\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b, \u0447\u0442\u043e \u0441 Emby Premiere \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u043c\u0438 \u0420\u0435\u0436\u0438\u043c\u0443 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430?",
|
||||
"MessageDidYouKnowCinemaMode2": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u0434\u0430\u0441\u0442 \u0432\u0430\u043c \u044d\u0444\u0444\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e \u0437\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043b\u0430 \u0441 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0430\u043c\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c\u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434 \u0444\u0438\u043b\u044c\u043c\u043e\u043c.",
|
||||
"HeaderPlayMyMedia": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043c\u043e\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
|
||||
"HeaderDiscoverEmbyPremiere": "\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 Emby Premiere",
|
||||
"HeaderDiscoverEmbyPremiere": "\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0434\u043b\u044f \u0441\u0435\u0431\u044f Emby Premiere",
|
||||
"Items": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b",
|
||||
"OneChannel": "\u041e\u0434\u0438\u043d \u043a\u0430\u043d\u0430\u043b",
|
||||
"ConfirmRemoveDownload": "\u0418\u0437\u044a\u044f\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443?",
|
||||
|
@ -229,7 +229,7 @@
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="fldQuality selectContainer hide">';
|
||||
html += '<select is="emby-select" id="selectQuality" data-mini="true" required="required" label="' + globalize.translate('sharedcomponents#LabelQuality') + '">';
|
||||
html += '<select is="emby-select" id="selectQuality" required="required" label="' + globalize.translate('sharedcomponents#LabelQuality') + '">';
|
||||
html += '</select>';
|
||||
html += '<div class="fieldDescription qualityDescription"></div>';
|
||||
html += '</div>';
|
||||
@ -479,7 +479,10 @@
|
||||
fldQuality.classList.remove('hide');
|
||||
}
|
||||
if (selectQuality) {
|
||||
selectQuality.setAttribute('required', 'required');
|
||||
//selectQuality.setAttribute('required', 'required');
|
||||
|
||||
// This is a hack due to what appears to be a edge bug but it shoudln't matter as the list always has selectable items
|
||||
selectQuality.removeAttribute('required');
|
||||
}
|
||||
} else {
|
||||
if (fldQuality) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.6.17",
|
||||
"version": "0.6.18",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
@ -16,11 +16,11 @@
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"_release": "0.6.17",
|
||||
"_release": "0.6.18",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.6.17",
|
||||
"commit": "51624f2b19db3d1e205188d541d0e379275eef2a"
|
||||
"tag": "v0.6.18",
|
||||
"commit": "69a7a73cbc5fa2a9022c0eef8ebb603de699c4a8"
|
||||
},
|
||||
"_source": "https://github.com/dailymotion/hls.js.git",
|
||||
"_target": "^0.6.11",
|
||||
|
28
dashboard-ui/bower_components/hlsjs/API.md
vendored
28
dashboard-ui/bower_components/hlsjs/API.md
vendored
@ -185,7 +185,10 @@ Configuration parameters could be provided to hls.js upon instantiation of `Hls`
|
||||
maxBufferSize: 60*1000*1000,
|
||||
maxBufferHole: 0.5,
|
||||
maxSeekHole: 2,
|
||||
seekHoleNudgeDuration: 0.01,
|
||||
lowBufferWatchdogPeriod: 0.5,
|
||||
highBufferWatchdogPeriod: 3,
|
||||
nudgeOffset: 0.1,
|
||||
nudgeMaxRetry : 3,
|
||||
maxFragLookUpTolerance: 0.2,
|
||||
liveSyncDurationCount: 3,
|
||||
liveMaxLatencyDurationCount: 10,
|
||||
@ -317,10 +320,27 @@ In case no quality level with this criteria can be found (lets say for example t
|
||||
|
||||
max video loading delay used in automatic start level selection : in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level + the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` )
|
||||
|
||||
#### ```seekHoleNudgeDuration```
|
||||
(default 0.01s)
|
||||
#### ```lowBufferWatchdogPeriod```
|
||||
(default 0.5s)
|
||||
|
||||
In case playback is still stalling although a seek over buffer hole just occured, hls.js will seek to next buffer start + (number of consecutive stalls * `seekHoleNudgeDuration`) to try to restore playback.
|
||||
if media element is expected to play and if currentTime has not moved for more than ```lowBufferWatchdogPeriod``` and if there are less than `maxBufferHole` seconds buffered upfront, hls.js will try to nudge playhead to recover playback
|
||||
|
||||
#### ```highBufferWatchdogPeriod```
|
||||
(default 3s)
|
||||
|
||||
if media element is expected to play and if currentTime has not moved for more than ```highBufferWatchdogPeriod``` and if there are more than `maxBufferHole` seconds buffered upfront, hls.js will try to nudge playhead to recover playback
|
||||
|
||||
|
||||
#### ```nudgeOffset```
|
||||
(default 0.1s)
|
||||
|
||||
In case playback continues to stall after first playhead nudging, currentTime will be nudged evenmore following nudgeOffset to try to restore playback.
|
||||
media.currentTime += (nb nudge retry -1)*nudgeOffset
|
||||
|
||||
#### ```nudgeMaxRetry```
|
||||
(default 3)
|
||||
|
||||
Max nb of nudge retries before hls.js raise a fatal BUFFER_STALLED_ERROR
|
||||
|
||||
#### `maxFragLookUpTolerance`
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.6.17",
|
||||
"version": "0.6.18",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
|
@ -78,9 +78,10 @@ design idea is pretty simple :
|
||||
- trigger BUFFER_APPENDING on FRAG_PARSING_DATA
|
||||
- once FRAG_PARSED is received an all segments have been appended (BUFFER_APPENDED) then buffer controller will recheck whether it needs to buffer more data.
|
||||
- **monitor current playback quality level** (buffer controller maintains a map between media position and quality level)
|
||||
- **monitor playback progress** : if playhead is not moving anymore although it should (video metadata is known and video is not ended, nor paused, nor in seeking state) and if we have less than 400ms buffered upfront, and if there is a new buffer range available upfront, less than config.maxSeekHole from currentTime, then hls.js will **jump over the buffer hole** and seek to the beginning of this new buffered range, to "unstuck" the playback.
|
||||
400 ms is a "magic number" that has been set to overcome browsers not always stopping playback at the exact end of a buffered range.
|
||||
- **monitor playback progress** : if playhead is not moving for more than `config.lowBufferWatchdogPeriod` although it should (video metadata is known and video is not ended, nor paused, nor in seeking state) and if we have less than 500ms buffered upfront, and if there is a new buffer range available upfront, less than `config.maxSeekHole` from currentTime, then hls.js will **jump over the buffer hole** and seek to the beginning of this new buffered range, to "unstuck" the playback.
|
||||
500 ms is a "magic number" that has been set to overcome browsers not always stopping playback at the exact end of a buffered range.
|
||||
these holes in media buffered are often encountered on stream discontinuity or on quality level switch. holes could be "large" especially if fragments are not starting with a keyframe.
|
||||
if playhead is stuck for more than `config.highBufferWatchdogPeriod` second in a buffered area, hls.js will nudge currentTime until playback recovers (it will retry every seconds, and report a fatal error after config.maxNudgeRetry retries)
|
||||
- convert non-fatal `FRAG_LOAD_ERROR`/`FRAG_LOAD_TIMEOUT`/`KEY_LOAD_ERROR`/`KEY_LOAD_TIMEOUT` error into fatal error when media position is not buffered and max load retry has been reached
|
||||
- stream controller actions are scheduled by a tick timer (invoked every 100ms) and actions are controlled by a state machine.
|
||||
- [src/controller/timeline-controller.js][]
|
||||
@ -253,4 +254,5 @@ design idea is pretty simple :
|
||||
- ```BUFFER_STALLED_ERROR``` is raised by [src/controller/stream-controller.js][] if playback is stalling because of buffer underrun
|
||||
- ```BUFFER_FULL_ERROR``` is raised by [src/controller/buffer-controller.js][] if sourcebuffer is full
|
||||
- ```BUFFER_SEEK_OVER_HOLE``` is raised by [src/controller/stream-controller.js][] when hls.js seeks over a buffer hole after playback stalls
|
||||
- ```BUFFER_NUDGE_ON_STALL``` is raised by [src/controller/stream-controller.js][] when hls.js nudge currentTime (when playback is stuck for more than 1s in a buffered area)
|
||||
- ```INTERNAL_EXCEPTION``` is raised by [src/event-handler.js][] when a runtime exception is triggered by an internal Hls event handler. this error is non-fatal.
|
||||
|
File diff suppressed because one or more lines are too long
10
dashboard-ui/bower_components/hlsjs/package.json
vendored
10
dashboard-ui/bower_components/hlsjs/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.6.17",
|
||||
"version": "0.6.18",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
@ -27,7 +27,7 @@
|
||||
"watch": "watchify --debug -s Hls src/index.js -t [babelify] -o dist/hls.js",
|
||||
"pretest": "npm run lint",
|
||||
"test": "mocha --compilers js:babel-register --recursive tests/unit",
|
||||
"testfunc": "mocha --compilers js:babel-register --recursive tests/functional/auto --timeout 40000",
|
||||
"testfunc": "mocha --compilers js:babel-register tests/functional/auto/hlsjs.js --timeout 40000",
|
||||
"lint": "jshint src/",
|
||||
"serve": "http-server -p 8000 .",
|
||||
"open": "opener http://localhost:8000/demo/",
|
||||
@ -36,15 +36,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"arraybuffer-equal": "^1.0.4",
|
||||
"babel-cli": "^6.18.0",
|
||||
"babel-cli": "^6.22.1",
|
||||
"babel-preset-es2015": "^6.18.0",
|
||||
"babel-register": "^6.18.0",
|
||||
"babelify": "^7.2.0",
|
||||
"browserify": "^13.1.1",
|
||||
"browserify": "^13.2.0",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"browserify-versionify": "^1.0.6",
|
||||
"bundle-collapser": "^1.2.1",
|
||||
"chromedriver": "^2.26.1",
|
||||
"chromedriver": "^2.27.1",
|
||||
"deep-strict-equal": "^0.2.0",
|
||||
"exorcist": "^0.4.0",
|
||||
"http-server": "^0.9.0",
|
||||
|
@ -164,7 +164,7 @@
|
||||
|
||||
|
||||
|
||||
@media all and (max-width: 440px) {
|
||||
@media all and (max-width: 400px) {
|
||||
|
||||
.playlist .listItemMediaInfo {
|
||||
display: none !important;
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
var html = '';
|
||||
|
||||
var isConnectMode = AppInfo.isNativeApp ? true : false;
|
||||
var isConnectMode = Dashboard.isConnectMode();
|
||||
var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null;
|
||||
|
||||
var href = configPage && !isConnectMode ?
|
||||
|
@ -1011,7 +1011,7 @@
|
||||
ticks *= value;
|
||||
|
||||
var item = currentItem;
|
||||
if (item && item.Chapters && item.Chapters[0].ImageTag) {
|
||||
if (item && item.Chapters && item.Chapters.length && item.Chapters[0].ImageTag) {
|
||||
var html = getChapterBubbleHtml(connectionManager.getApiClient(item.ServerId), item, item.Chapters, ticks);
|
||||
|
||||
if (html) {
|
||||
|
Loading…
Reference in New Issue
Block a user