rx-player 3.30.1-dev.2023032800 → 3.31.0-dev.2023052200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -2
- package/CONTRIBUTING.md +48 -168
- package/FILES.md +40 -92
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
- package/dist/_esm5.processed/compat/browser_detection.js +7 -2
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +1 -2
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +105 -24
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
- package/dist/_esm5.processed/core/api/debug/render.js +1 -1
- package/dist/_esm5.processed/core/api/public_api.js +2 -2
- package/dist/_esm5.processed/core/api/tracks_management/media_element_track_choice_manager.js +10 -1
- package/dist/_esm5.processed/core/api/tracks_management/track_choice_manager.js +20 -117
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +28 -3
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +2 -2
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.js +29 -18
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +1 -1
- package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +6 -2
- package/dist/_esm5.processed/errors/index.d.ts +2 -2
- package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
- package/dist/_esm5.processed/errors/media_error.js +18 -5
- package/dist/_esm5.processed/manifest/adaptation.d.ts +17 -2
- package/dist/_esm5.processed/manifest/adaptation.js +67 -1
- package/dist/_esm5.processed/manifest/manifest.d.ts +1 -1
- package/dist/_esm5.processed/manifest/manifest.js +3 -3
- package/dist/_esm5.processed/manifest/period.js +1 -1
- package/dist/_esm5.processed/manifest/representation.d.ts +11 -1
- package/dist/_esm5.processed/manifest/representation.js +16 -0
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
- package/dist/_esm5.processed/public_types.d.ts +6 -5
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
- package/dist/rx-player.js +3086 -3024
- package/dist/rx-player.min.js +1 -1
- package/package.json +25 -26
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +7 -1
- package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
- package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
- package/src/core/adaptive/adaptive_representation_selector.ts +1 -2
- package/src/core/adaptive/buffer_based_chooser.ts +143 -25
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/render.ts +1 -1
- package/src/core/api/public_api.ts +2 -2
- package/src/core/api/tracks_management/media_element_track_choice_manager.ts +17 -8
- package/src/core/api/tracks_management/track_choice_manager.ts +20 -132
- package/src/core/init/media_source_content_initializer.ts +32 -4
- package/src/core/init/utils/media_source_duration_updater.ts +31 -19
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +2 -1
- package/src/core/stream/period/period_stream.ts +2 -1
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
- package/src/core/stream/representation/utils/push_init_segment.ts +7 -1
- package/src/errors/__tests__/media_error.test.ts +6 -6
- package/src/errors/index.ts +4 -1
- package/src/errors/media_error.ts +67 -1
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +77 -2
- package/src/manifest/manifest.ts +5 -3
- package/src/manifest/period.ts +2 -1
- package/src/manifest/representation.ts +23 -1
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
- package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
- package/src/public_types.ts +8 -3
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/typings/globals.d.ts +21 -21
- package/scripts/doc-generator/construct_table_of_contents.js +0 -76
- package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
- package/scripts/doc-generator/create_documentation.js +0 -331
- package/scripts/doc-generator/create_documentation_page.js +0 -209
- package/scripts/doc-generator/create_page.js +0 -210
- package/scripts/doc-generator/generate_header_html.js +0 -147
- package/scripts/doc-generator/generate_page_html.js +0 -115
- package/scripts/doc-generator/generate_page_list_html.js +0 -92
- package/scripts/doc-generator/generate_sidebar_html.js +0 -85
- package/scripts/doc-generator/get_search_data_for_content.js +0 -137
- package/scripts/doc-generator/index.js +0 -34
- package/scripts/doc-generator/parse_doc_configs.js +0 -327
- package/scripts/doc-generator/scripts/lunr.js +0 -10
- package/scripts/doc-generator/scripts/script.js +0 -451
- package/scripts/doc-generator/styles/code.css +0 -99
- package/scripts/doc-generator/styles/style.css +0 -835
- package/scripts/doc-generator/utils.js +0 -74
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.31.0-dev.2023052200
|
|
@@ -37,4 +37,6 @@ declare let isWebOs2021: boolean;
|
|
|
37
37
|
declare let isWebOs2022: boolean;
|
|
38
38
|
/** `true` for Panasonic devices. */
|
|
39
39
|
declare let isPanasonic: boolean;
|
|
40
|
-
|
|
40
|
+
/** `true` for the PlayStation 5 game console. */
|
|
41
|
+
declare let isPlayStation5: boolean;
|
|
42
|
+
export { isEdgeChromium, isIE11, isIEOrEdge, isFirefox, isPanasonic, isPlayStation5, isSafariDesktop, isSafariMobile, isSamsungBrowser, isTizen, isWebOs, isWebOs2021, isWebOs2022, };
|
|
@@ -38,6 +38,8 @@ var isWebOs2021 = false;
|
|
|
38
38
|
var isWebOs2022 = false;
|
|
39
39
|
/** `true` for Panasonic devices. */
|
|
40
40
|
var isPanasonic = false;
|
|
41
|
+
/** `true` for the PlayStation 5 game console. */
|
|
42
|
+
var isPlayStation5 = false;
|
|
41
43
|
((function findCurrentBrowser() {
|
|
42
44
|
var _a, _b;
|
|
43
45
|
if (isNode) {
|
|
@@ -74,7 +76,10 @@ var isPanasonic = false;
|
|
|
74
76
|
if (/SamsungBrowser/.test(navigator.userAgent)) {
|
|
75
77
|
isSamsungBrowser = true;
|
|
76
78
|
}
|
|
77
|
-
if (
|
|
79
|
+
if (navigator.userAgent.indexOf("PlayStation 5") !== -1) {
|
|
80
|
+
isPlayStation5 = true;
|
|
81
|
+
}
|
|
82
|
+
else if (/Tizen/.test(navigator.userAgent)) {
|
|
78
83
|
isTizen = true;
|
|
79
84
|
// Inspired form: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
80
85
|
// Note: even that page doesn't correspond to what we've actually seen in the
|
|
@@ -95,4 +100,4 @@ var isPanasonic = false;
|
|
|
95
100
|
isPanasonic = true;
|
|
96
101
|
}
|
|
97
102
|
})());
|
|
98
|
-
export { isEdgeChromium, isIE11, isIEOrEdge, isFirefox, isPanasonic, isSafariDesktop, isSafariMobile, isSamsungBrowser, isTizen, isWebOs, isWebOs2021, isWebOs2022, };
|
|
103
|
+
export { isEdgeChromium, isIE11, isIEOrEdge, isFirefox, isPanasonic, isPlayStation5, isSafariDesktop, isSafariMobile, isSamsungBrowser, isTizen, isWebOs, isWebOs2021, isWebOs2022, };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Some platforms have issues when the `MediaSource`'s `duration` property
|
|
3
|
+
* is set to a very high value (playback freezes) but not when setting it
|
|
4
|
+
* to `Infinity`, which is what the HTML spec as of now (2023-05-15) recommends
|
|
5
|
+
* for live contents.
|
|
6
|
+
*
|
|
7
|
+
* However setting the `MediaSource`'s `duration` property to `Infinity` seems
|
|
8
|
+
* more risky, considering all platforms we now support, than setting it at a
|
|
9
|
+
* relatively high ~2**32 value which is what we do generally.
|
|
10
|
+
*
|
|
11
|
+
* Moreover, setting it to `Infinity` require us to use another MSE API,
|
|
12
|
+
* `setLiveSeekableRange` to properly allow seeking. We're used to MSE issues so
|
|
13
|
+
* I'm not too confident of using another MSE API for all platforms directly.
|
|
14
|
+
*
|
|
15
|
+
* So this methods just return `true` based on a whitelist of platform for which
|
|
16
|
+
* it has been detected that high `duration` values cause issues but setting it
|
|
17
|
+
* to Infinity AND playing with `setLiveSeekableRange` does not.
|
|
18
|
+
*
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
21
|
+
export default function hasIssuesWithHighMediaSourceDuration(): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isPlayStation5 } from "./browser_detection";
|
|
2
|
+
/**
|
|
3
|
+
* Some platforms have issues when the `MediaSource`'s `duration` property
|
|
4
|
+
* is set to a very high value (playback freezes) but not when setting it
|
|
5
|
+
* to `Infinity`, which is what the HTML spec as of now (2023-05-15) recommends
|
|
6
|
+
* for live contents.
|
|
7
|
+
*
|
|
8
|
+
* However setting the `MediaSource`'s `duration` property to `Infinity` seems
|
|
9
|
+
* more risky, considering all platforms we now support, than setting it at a
|
|
10
|
+
* relatively high ~2**32 value which is what we do generally.
|
|
11
|
+
*
|
|
12
|
+
* Moreover, setting it to `Infinity` require us to use another MSE API,
|
|
13
|
+
* `setLiveSeekableRange` to properly allow seeking. We're used to MSE issues so
|
|
14
|
+
* I'm not too confident of using another MSE API for all platforms directly.
|
|
15
|
+
*
|
|
16
|
+
* So this methods just return `true` based on a whitelist of platform for which
|
|
17
|
+
* it has been detected that high `duration` values cause issues but setting it
|
|
18
|
+
* to Infinity AND playing with `setLiveSeekableRange` does not.
|
|
19
|
+
*
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
export default function hasIssuesWithHighMediaSourceDuration() {
|
|
23
|
+
// For now only seen on the Webkit present in the PlayStation 5, for which the
|
|
24
|
+
// alternative is known to work.
|
|
25
|
+
return isPlayStation5;
|
|
26
|
+
}
|
|
@@ -210,8 +210,7 @@ function getEstimateReference(_a, stopAllEstimates) {
|
|
|
210
210
|
var timeRanges = val.buffered;
|
|
211
211
|
var bufferGap = getLeftSizeOfRange(timeRanges, position.last);
|
|
212
212
|
var representation = val.content.representation;
|
|
213
|
-
var
|
|
214
|
-
var currentScore = scoreData === null || scoreData === void 0 ? void 0 : scoreData[0];
|
|
213
|
+
var currentScore = scoreCalculator.getEstimate(representation);
|
|
215
214
|
var currentBitrate = representation.bitrate;
|
|
216
215
|
var observation = { bufferGap: bufferGap, currentBitrate: currentBitrate, currentScore: currentScore, speed: speed };
|
|
217
216
|
currentBufferBasedEstimate = bufferBasedChooser.getEstimate(observation);
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { IRepresentationMaintainabilityScore } from "./utils/representation_score_calculator";
|
|
16
17
|
/**
|
|
17
18
|
* Choose a bitrate based on the currently available buffer.
|
|
18
19
|
*
|
|
@@ -24,11 +25,27 @@
|
|
|
24
25
|
* "maintanable" or not.
|
|
25
26
|
* If so, we may switch to a better quality, or conversely to a worse quality.
|
|
26
27
|
*
|
|
28
|
+
* It also rely on mechanisms to avoid fluctuating too much between qualities.
|
|
29
|
+
*
|
|
27
30
|
* @class BufferBasedChooser
|
|
28
31
|
*/
|
|
29
32
|
export default class BufferBasedChooser {
|
|
30
33
|
private _levelsMap;
|
|
31
34
|
private _bitrates;
|
|
35
|
+
/**
|
|
36
|
+
* Laast timestamp, in terms of `performance.now`, at which the current
|
|
37
|
+
* quality was seen as too high by this algorithm.
|
|
38
|
+
* Begins at `undefined`.
|
|
39
|
+
*/
|
|
40
|
+
private _lastUnsuitableQualityTimestamp;
|
|
41
|
+
/**
|
|
42
|
+
* After lowering in quality, we forbid raising during a set amount of time.
|
|
43
|
+
* This amount is adaptive may continue to raise if it seems that quality
|
|
44
|
+
* is switching too much between low and high qualities.
|
|
45
|
+
*
|
|
46
|
+
* `_blockRaiseDelay` represents this time in milliseconds.
|
|
47
|
+
*/
|
|
48
|
+
private _blockRaiseDelay;
|
|
32
49
|
/**
|
|
33
50
|
* @param {Array.<number>} bitrates
|
|
34
51
|
*/
|
|
@@ -50,7 +67,7 @@ export interface IBufferBasedChooserPlaybackObservation {
|
|
|
50
67
|
/** The bitrate of the currently downloaded segments, in bps. */
|
|
51
68
|
currentBitrate?: number | undefined;
|
|
52
69
|
/** The "maintainability score" of the currently downloaded segments. */
|
|
53
|
-
currentScore?:
|
|
70
|
+
currentScore?: IRepresentationMaintainabilityScore | undefined;
|
|
54
71
|
/** Playback rate wanted (e.g. `1` is regular playback, `2` is double speed etc.). */
|
|
55
72
|
speed: number;
|
|
56
73
|
}
|
|
@@ -16,6 +16,45 @@
|
|
|
16
16
|
import log from "../../log";
|
|
17
17
|
import arrayFindIndex from "../../utils/array_find_index";
|
|
18
18
|
import getBufferLevels from "./utils/get_buffer_levels";
|
|
19
|
+
/**
|
|
20
|
+
* Minimum amount of time, in milliseconds, during which we are blocked from
|
|
21
|
+
* raising in quality after it had been considered as too high.
|
|
22
|
+
*/
|
|
23
|
+
var MINIMUM_BLOCK_RAISE_DELAY = 6000;
|
|
24
|
+
/**
|
|
25
|
+
* Maximum amount of time, in milliseconds, during which we are blocked from
|
|
26
|
+
* raising in quality after it had been considered as too high.
|
|
27
|
+
*/
|
|
28
|
+
var MAXIMUM_BLOCK_RAISE_DELAY = 15000;
|
|
29
|
+
/**
|
|
30
|
+
* Amount of time, in milliseconds, with which the blocking time in raising
|
|
31
|
+
* the quality will be incremented if the current quality estimate is seen
|
|
32
|
+
* as too unstable.
|
|
33
|
+
*/
|
|
34
|
+
var RAISE_BLOCKING_DELAY_INCREMENT = 3000;
|
|
35
|
+
/**
|
|
36
|
+
* Amount of time, in milliseconds, with which the blocking time in raising
|
|
37
|
+
* the quality will be dcremented if the current quality estimate is seen
|
|
38
|
+
* as relatively stable, until `MINIMUM_BLOCK_RAISE_DELAY` is reached.
|
|
39
|
+
*/
|
|
40
|
+
var RAISE_BLOCKING_DELAY_DECREMENT = 1000;
|
|
41
|
+
/**
|
|
42
|
+
* Amount of time, in milliseconds, after the "raise blocking delay" currently
|
|
43
|
+
* in place (during which it is forbidden to raise up in quality), during which
|
|
44
|
+
* we might want to raise the "raise blocking delay" if the last chosen quality
|
|
45
|
+
* seems unsuitable.
|
|
46
|
+
*
|
|
47
|
+
* For example, let's consider that the current raise blocking delay is at
|
|
48
|
+
* `4000`, or 4 seconds, and that this `STABILITY_CHECK_DELAY` is at `5000`, or
|
|
49
|
+
* 5 seconds.
|
|
50
|
+
* Here it means that if the estimated quality is found to be unsuitable less
|
|
51
|
+
* than 4+5 = 9 seconds after it last was, we will increment the raise blocking
|
|
52
|
+
* delay by `RAISE_BLOCKING_DELAY_INCREMENT` (unless `MAXIMUM_BLOCK_RAISE_DELAY`
|
|
53
|
+
* is reached).
|
|
54
|
+
* Else, if takes more than 9 seconds, the raise blocking delay might be
|
|
55
|
+
* decremented.
|
|
56
|
+
*/
|
|
57
|
+
var STABILITY_CHECK_DELAY = 9000;
|
|
19
58
|
/**
|
|
20
59
|
* Choose a bitrate based on the currently available buffer.
|
|
21
60
|
*
|
|
@@ -27,6 +66,8 @@ import getBufferLevels from "./utils/get_buffer_levels";
|
|
|
27
66
|
* "maintanable" or not.
|
|
28
67
|
* If so, we may switch to a better quality, or conversely to a worse quality.
|
|
29
68
|
*
|
|
69
|
+
* It also rely on mechanisms to avoid fluctuating too much between qualities.
|
|
70
|
+
*
|
|
30
71
|
* @class BufferBasedChooser
|
|
31
72
|
*/
|
|
32
73
|
var BufferBasedChooser = /** @class */ (function () {
|
|
@@ -34,8 +75,13 @@ var BufferBasedChooser = /** @class */ (function () {
|
|
|
34
75
|
* @param {Array.<number>} bitrates
|
|
35
76
|
*/
|
|
36
77
|
function BufferBasedChooser(bitrates) {
|
|
37
|
-
this._levelsMap = getBufferLevels(bitrates)
|
|
78
|
+
this._levelsMap = getBufferLevels(bitrates).map(function (bl) {
|
|
79
|
+
return bl + 4; // Add some buffer security as it will be used conjointly with
|
|
80
|
+
// other algorithms anyway
|
|
81
|
+
});
|
|
38
82
|
this._bitrates = bitrates;
|
|
83
|
+
this._lastUnsuitableQualityTimestamp = undefined;
|
|
84
|
+
this._blockRaiseDelay = MINIMUM_BLOCK_RAISE_DELAY;
|
|
39
85
|
log.debug("ABR: Steps for buffer based chooser.", this._levelsMap.map(function (l, i) { return "bufferLevel: ".concat(l, ", bitrate: ").concat(bitrates[i]); })
|
|
40
86
|
.join(" ,"));
|
|
41
87
|
}
|
|
@@ -50,40 +96,75 @@ var BufferBasedChooser = /** @class */ (function () {
|
|
|
50
96
|
if (currentBitrate == null) {
|
|
51
97
|
return bitrates[0];
|
|
52
98
|
}
|
|
53
|
-
var currentBitrateIndex =
|
|
99
|
+
var currentBitrateIndex = -1;
|
|
100
|
+
for (var i = 0; i < bitrates.length; i++) {
|
|
101
|
+
// There could be bitrate duplicates. Only take the last one to simplify
|
|
102
|
+
var bitrate = bitrates[i];
|
|
103
|
+
if (bitrate === currentBitrate) {
|
|
104
|
+
currentBitrateIndex = i;
|
|
105
|
+
}
|
|
106
|
+
else if (bitrate > currentBitrate) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
54
110
|
if (currentBitrateIndex < 0 || bitrates.length !== bufferLevels.length) {
|
|
55
111
|
log.error("ABR: Current Bitrate not found in the calculated levels");
|
|
56
112
|
return bitrates[0];
|
|
57
113
|
}
|
|
58
114
|
var scaledScore;
|
|
59
115
|
if (currentScore !== undefined) {
|
|
60
|
-
scaledScore = speed === 0 ? currentScore : (currentScore / speed);
|
|
116
|
+
scaledScore = speed === 0 ? currentScore.score : (currentScore.score / speed);
|
|
61
117
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
118
|
+
var actualBufferGap = isFinite(bufferGap) ?
|
|
119
|
+
bufferGap :
|
|
120
|
+
0;
|
|
121
|
+
var now = performance.now();
|
|
122
|
+
if (actualBufferGap < bufferLevels[currentBitrateIndex] ||
|
|
123
|
+
(scaledScore !== undefined && scaledScore < 1 &&
|
|
124
|
+
(currentScore === null || currentScore === void 0 ? void 0 : currentScore.confidenceLevel) === 1 /* ScoreConfidenceLevel.HIGH */)) {
|
|
125
|
+
var timeSincePrev = this._lastUnsuitableQualityTimestamp === undefined ?
|
|
126
|
+
-1 :
|
|
127
|
+
now - this._lastUnsuitableQualityTimestamp;
|
|
128
|
+
if (timeSincePrev < this._blockRaiseDelay + STABILITY_CHECK_DELAY) {
|
|
129
|
+
var newDelay = this._blockRaiseDelay + RAISE_BLOCKING_DELAY_INCREMENT;
|
|
130
|
+
this._blockRaiseDelay = Math.min(newDelay, MAXIMUM_BLOCK_RAISE_DELAY);
|
|
131
|
+
log.debug("ABR: Incrementing blocking raise in BufferBasedChooser due " +
|
|
132
|
+
"to unstable quality", this._blockRaiseDelay);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
var newDelay = this._blockRaiseDelay - RAISE_BLOCKING_DELAY_DECREMENT;
|
|
136
|
+
this._blockRaiseDelay = Math.max(MINIMUM_BLOCK_RAISE_DELAY, newDelay);
|
|
137
|
+
log.debug("ABR: Lowering quality in BufferBasedChooser", this._blockRaiseDelay);
|
|
138
|
+
}
|
|
139
|
+
this._lastUnsuitableQualityTimestamp = now;
|
|
140
|
+
// Security if multiple bitrates are equal, we now take the first one
|
|
141
|
+
var baseIndex = arrayFindIndex(bitrates, function (b) { return b === currentBitrate; });
|
|
142
|
+
for (var i = baseIndex - 1; i >= 0; i--) {
|
|
143
|
+
if (actualBufferGap >= bufferLevels[i]) {
|
|
144
|
+
return bitrates[i];
|
|
75
145
|
}
|
|
76
146
|
}
|
|
147
|
+
return bitrates[0];
|
|
77
148
|
}
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
149
|
+
if ((this._lastUnsuitableQualityTimestamp !== undefined &&
|
|
150
|
+
now - this._lastUnsuitableQualityTimestamp < this._blockRaiseDelay) ||
|
|
151
|
+
scaledScore === undefined || scaledScore < 1.15 ||
|
|
152
|
+
(currentScore === null || currentScore === void 0 ? void 0 : currentScore.confidenceLevel) !== 1 /* ScoreConfidenceLevel.HIGH */) {
|
|
153
|
+
return currentBitrate;
|
|
154
|
+
}
|
|
155
|
+
var currentBufferLevel = bufferLevels[currentBitrateIndex];
|
|
156
|
+
var nextIndex = (function () {
|
|
157
|
+
for (var i = currentBitrateIndex + 1; i < bufferLevels.length; i++) {
|
|
158
|
+
if (bufferLevels[i] > currentBufferLevel) {
|
|
159
|
+
return i;
|
|
85
160
|
}
|
|
86
|
-
|
|
161
|
+
}
|
|
162
|
+
})();
|
|
163
|
+
if (nextIndex !== undefined) {
|
|
164
|
+
var nextBufferLevel = bufferLevels[nextIndex];
|
|
165
|
+
if (bufferGap >= nextBufferLevel) {
|
|
166
|
+
log.debug("ABR: Raising quality in BufferBasedChooser", bitrates[nextIndex]);
|
|
167
|
+
return bitrates[nextIndex];
|
|
87
168
|
}
|
|
88
169
|
}
|
|
89
170
|
return currentBitrate;
|
|
@@ -127,10 +127,10 @@ var GuessBasedChooser = /** @class */ (function () {
|
|
|
127
127
|
* @returns {boolean}
|
|
128
128
|
*/
|
|
129
129
|
GuessBasedChooser.prototype._canGuessHigher = function (bufferGap, speed, _a) {
|
|
130
|
-
var score = _a
|
|
130
|
+
var score = _a.score, confidenceLevel = _a.confidenceLevel;
|
|
131
131
|
return isFinite(bufferGap) && bufferGap >= 2.5 &&
|
|
132
132
|
performance.now() > this._blockGuessesUntil &&
|
|
133
|
-
|
|
133
|
+
confidenceLevel === 1 /* ScoreConfidenceLevel.HIGH */ &&
|
|
134
134
|
score / speed > 1.01;
|
|
135
135
|
};
|
|
136
136
|
/**
|
|
@@ -143,10 +143,10 @@ var GuessBasedChooser = /** @class */ (function () {
|
|
|
143
143
|
* @returns {boolean}
|
|
144
144
|
*/
|
|
145
145
|
GuessBasedChooser.prototype._shouldStopGuess = function (lastGuess, scoreData, bufferGap, requests) {
|
|
146
|
-
if (scoreData !== undefined && scoreData
|
|
146
|
+
if (scoreData !== undefined && scoreData.score < 1.01) {
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
|
-
else if ((scoreData === undefined || scoreData
|
|
149
|
+
else if ((scoreData === undefined || scoreData.score < 1.2) && bufferGap < 0.6) {
|
|
150
150
|
return true;
|
|
151
151
|
}
|
|
152
152
|
var guessedRepresentationRequests = requests.filter(function (req) {
|
|
@@ -175,8 +175,8 @@ var GuessBasedChooser = /** @class */ (function () {
|
|
|
175
175
|
};
|
|
176
176
|
GuessBasedChooser.prototype._isLastGuessValidated = function (lastGuess, incomingBestBitrate, scoreData) {
|
|
177
177
|
if (scoreData !== undefined &&
|
|
178
|
-
scoreData
|
|
179
|
-
scoreData
|
|
178
|
+
scoreData.confidenceLevel === 1 /* ScoreConfidenceLevel.HIGH */ &&
|
|
179
|
+
scoreData.score > 1.5) {
|
|
180
180
|
return true;
|
|
181
181
|
}
|
|
182
182
|
return incomingBestBitrate >= lastGuess.bitrate &&
|
|
@@ -14,6 +14,24 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { Representation } from "../../../manifest";
|
|
17
|
+
/**
|
|
18
|
+
* Object representing a maintainability score as calculated by the
|
|
19
|
+
* `RepresentationScoreCalculator`.
|
|
20
|
+
*/
|
|
21
|
+
export interface IRepresentationMaintainabilityScore {
|
|
22
|
+
/**
|
|
23
|
+
* Weighted mean of dividing the loaded segment's duration by the time to make
|
|
24
|
+
* their request.
|
|
25
|
+
*/
|
|
26
|
+
score: number;
|
|
27
|
+
/**
|
|
28
|
+
* The confidence we have on the calculated `score` in reflecting a useful
|
|
29
|
+
* maintainability hint for the concerned Representation.
|
|
30
|
+
*
|
|
31
|
+
* Basically, the more segments have been loaded, the higher the confidence.
|
|
32
|
+
*/
|
|
33
|
+
confidenceLevel: ScoreConfidenceLevel;
|
|
34
|
+
}
|
|
17
35
|
/**
|
|
18
36
|
* Calculate the "maintainability score" of a given Representation:
|
|
19
37
|
* - A score higher than 1 means that the Representation can theorically
|
|
@@ -62,7 +80,7 @@ export default class RepresentationScoreCalculator {
|
|
|
62
80
|
* @param {Representation} representation
|
|
63
81
|
* @returns {number|undefined}
|
|
64
82
|
*/
|
|
65
|
-
getEstimate(representation: Representation):
|
|
83
|
+
getEstimate(representation: Representation): IRepresentationMaintainabilityScore | undefined;
|
|
66
84
|
/**
|
|
67
85
|
* Returns last Representation which had reached a score superior to 1.
|
|
68
86
|
* This Representation is the last known one which could be maintained.
|
|
@@ -96,7 +96,7 @@ var RepresentationScoreCalculator = /** @class */ (function () {
|
|
|
96
96
|
var confidenceLevel = loadedSegments >= 5 &&
|
|
97
97
|
loadedDuration >= 10 ? 1 /* ScoreConfidenceLevel.HIGH */ :
|
|
98
98
|
0 /* ScoreConfidenceLevel.LOW */;
|
|
99
|
-
return
|
|
99
|
+
return { score: estimate, confidenceLevel: confidenceLevel };
|
|
100
100
|
};
|
|
101
101
|
/**
|
|
102
102
|
* Returns last Representation which had reached a score superior to 1.
|
|
@@ -21,7 +21,7 @@ export default function renderDebugElement(parentElt, instance, cancelSignal) {
|
|
|
21
21
|
debugWrapperElt.style.backgroundColor = "#00000099";
|
|
22
22
|
debugWrapperElt.style.padding = "7px";
|
|
23
23
|
debugWrapperElt.style.fontSize = "13px";
|
|
24
|
-
debugWrapperElt.style.fontFamily = "mono";
|
|
24
|
+
debugWrapperElt.style.fontFamily = "mono, monospace";
|
|
25
25
|
debugWrapperElt.style.color = "white";
|
|
26
26
|
debugWrapperElt.style.display = "inline-block";
|
|
27
27
|
debugWrapperElt.style.bottom = "0px";
|
|
@@ -89,7 +89,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
89
89
|
// Workaround to support Firefox autoplay on FF 42.
|
|
90
90
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
91
91
|
videoElement.preload = "auto";
|
|
92
|
-
_this.version = /* PLAYER_VERSION */ "3.
|
|
92
|
+
_this.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
|
|
93
93
|
_this.log = log;
|
|
94
94
|
_this.state = "STOPPED";
|
|
95
95
|
_this.videoElement = videoElement;
|
|
@@ -2340,5 +2340,5 @@ var Player = /** @class */ (function (_super) {
|
|
|
2340
2340
|
};
|
|
2341
2341
|
return Player;
|
|
2342
2342
|
}(EventEmitter));
|
|
2343
|
-
Player.version = /* PLAYER_VERSION */ "3.
|
|
2343
|
+
Player.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
|
|
2344
2344
|
export default Player;
|
package/dist/_esm5.processed/core/api/tracks_management/media_element_track_choice_manager.js
CHANGED
|
@@ -101,7 +101,14 @@ function createTextTracks(textTracks) {
|
|
|
101
101
|
"_" +
|
|
102
102
|
occurences.toString();
|
|
103
103
|
languagesOccurences[language] = occurences + 1;
|
|
104
|
-
|
|
104
|
+
// Safari seems to be indicating that the subtitles track is a forced
|
|
105
|
+
// subtitles track by setting the `kind` attribute to `"forced"`.
|
|
106
|
+
// As of now (2023-04-04), this is not standard.
|
|
107
|
+
// @see https://github.com/whatwg/html/issues/4472
|
|
108
|
+
var forced = textTrack.kind === "forced" ?
|
|
109
|
+
true :
|
|
110
|
+
undefined;
|
|
111
|
+
var track = { language: textTrack.language, forced: forced, label: textTrack.label, id: id, normalized: normalizeLanguage(textTrack.language),
|
|
105
112
|
closedCaption: textTrack.kind === "captions" };
|
|
106
113
|
newTextTracks.push({ track: track, nativeTrack: textTrack });
|
|
107
114
|
}
|
|
@@ -337,6 +344,8 @@ var MediaElementTrackChoiceManager = /** @class */ (function (_super) {
|
|
|
337
344
|
return this._textTracks.map(function (_a) {
|
|
338
345
|
var track = _a.track, nativeTrack = _a.nativeTrack;
|
|
339
346
|
return { id: track.id,
|
|
347
|
+
label: track.label,
|
|
348
|
+
forced: track.forced,
|
|
340
349
|
language: track.language,
|
|
341
350
|
normalized: track.normalized,
|
|
342
351
|
closedCaption: track.closedCaption,
|
|
@@ -22,6 +22,7 @@ import arrayFind from "../../../utils/array_find";
|
|
|
22
22
|
import arrayIncludes from "../../../utils/array_includes";
|
|
23
23
|
import isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
24
24
|
import normalizeLanguage from "../../../utils/languages";
|
|
25
|
+
import objectAssign from "../../../utils/object_assign";
|
|
25
26
|
import SortedList from "../../../utils/sorted_list";
|
|
26
27
|
import takeFirstSet from "../../../utils/take_first_set";
|
|
27
28
|
/**
|
|
@@ -426,18 +427,7 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
426
427
|
if (isNullOrUndefined(chosenTrack)) {
|
|
427
428
|
return null;
|
|
428
429
|
}
|
|
429
|
-
|
|
430
|
-
language: takeFirstSet(chosenTrack.language, ""),
|
|
431
|
-
normalized: takeFirstSet(chosenTrack.normalizedLanguage, ""),
|
|
432
|
-
audioDescription: chosenTrack.isAudioDescription === true,
|
|
433
|
-
id: chosenTrack.id,
|
|
434
|
-
representations: chosenTrack.representations.map(parseAudioRepresentation),
|
|
435
|
-
label: chosenTrack.label,
|
|
436
|
-
};
|
|
437
|
-
if (chosenTrack.isDub === true) {
|
|
438
|
-
audioTrack.dub = true;
|
|
439
|
-
}
|
|
440
|
-
return audioTrack;
|
|
430
|
+
return chosenTrack.toAudioTrack();
|
|
441
431
|
};
|
|
442
432
|
/**
|
|
443
433
|
* Returns an object describing the chosen text track for the given text
|
|
@@ -460,17 +450,7 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
460
450
|
if (isNullOrUndefined(chosenTextAdaptation)) {
|
|
461
451
|
return null;
|
|
462
452
|
}
|
|
463
|
-
|
|
464
|
-
language: takeFirstSet(chosenTextAdaptation.language, ""),
|
|
465
|
-
normalized: takeFirstSet(chosenTextAdaptation.normalizedLanguage, ""),
|
|
466
|
-
closedCaption: chosenTextAdaptation.isClosedCaption === true,
|
|
467
|
-
id: chosenTextAdaptation.id,
|
|
468
|
-
label: chosenTextAdaptation.label,
|
|
469
|
-
};
|
|
470
|
-
if (chosenTextAdaptation.isForcedSubtitles !== undefined) {
|
|
471
|
-
formatted.forced = chosenTextAdaptation.isForcedSubtitles;
|
|
472
|
-
}
|
|
473
|
-
return formatted;
|
|
453
|
+
return chosenTextAdaptation.toTextTrack();
|
|
474
454
|
};
|
|
475
455
|
/**
|
|
476
456
|
* Returns an object describing the chosen video track for the given video
|
|
@@ -494,32 +474,7 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
494
474
|
return null;
|
|
495
475
|
}
|
|
496
476
|
var currAdaptation = chosenVideoAdaptation.adaptation;
|
|
497
|
-
|
|
498
|
-
currAdaptation.trickModeTracks.map(function (trickModeAdaptation) {
|
|
499
|
-
var representations = trickModeAdaptation.representations
|
|
500
|
-
.map(parseVideoRepresentation);
|
|
501
|
-
var trickMode = { id: trickModeAdaptation.id, representations: representations, isTrickModeTrack: true };
|
|
502
|
-
if (trickModeAdaptation.isSignInterpreted === true) {
|
|
503
|
-
trickMode.signInterpreted = true;
|
|
504
|
-
}
|
|
505
|
-
return trickMode;
|
|
506
|
-
}) :
|
|
507
|
-
undefined;
|
|
508
|
-
var videoTrack = {
|
|
509
|
-
id: currAdaptation.id,
|
|
510
|
-
representations: currAdaptation.representations.map(parseVideoRepresentation),
|
|
511
|
-
label: currAdaptation.label,
|
|
512
|
-
};
|
|
513
|
-
if (currAdaptation.isSignInterpreted === true) {
|
|
514
|
-
videoTrack.signInterpreted = true;
|
|
515
|
-
}
|
|
516
|
-
if (currAdaptation.isTrickModeTrack === true) {
|
|
517
|
-
videoTrack.isTrickModeTrack = true;
|
|
518
|
-
}
|
|
519
|
-
if (trickModeTracks !== undefined) {
|
|
520
|
-
videoTrack.trickModeTracks = trickModeTracks;
|
|
521
|
-
}
|
|
522
|
-
return videoTrack;
|
|
477
|
+
return currAdaptation.toVideoTrack();
|
|
523
478
|
};
|
|
524
479
|
/**
|
|
525
480
|
* Returns all available audio tracks for a given Period, as an array of
|
|
@@ -540,20 +495,9 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
540
495
|
null;
|
|
541
496
|
return audioInfos.adaptations
|
|
542
497
|
.map(function (adaptation) {
|
|
543
|
-
var
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
audioDescription: adaptation.isAudioDescription === true,
|
|
547
|
-
id: adaptation.id,
|
|
548
|
-
active: currentId === null ? false :
|
|
549
|
-
currentId === adaptation.id,
|
|
550
|
-
representations: adaptation.representations.map(parseAudioRepresentation),
|
|
551
|
-
label: adaptation.label,
|
|
552
|
-
};
|
|
553
|
-
if (adaptation.isDub === true) {
|
|
554
|
-
formatted.dub = true;
|
|
555
|
-
}
|
|
556
|
-
return formatted;
|
|
498
|
+
var active = currentId === null ? false :
|
|
499
|
+
currentId === adaptation.id;
|
|
500
|
+
return objectAssign(adaptation.toAudioTrack(), { active: active });
|
|
557
501
|
});
|
|
558
502
|
};
|
|
559
503
|
/**
|
|
@@ -576,19 +520,9 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
576
520
|
null;
|
|
577
521
|
return textInfos.adaptations
|
|
578
522
|
.map(function (adaptation) {
|
|
579
|
-
var
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
closedCaption: adaptation.isClosedCaption === true,
|
|
583
|
-
id: adaptation.id,
|
|
584
|
-
active: currentId === null ? false :
|
|
585
|
-
currentId === adaptation.id,
|
|
586
|
-
label: adaptation.label,
|
|
587
|
-
};
|
|
588
|
-
if (adaptation.isForcedSubtitles !== undefined) {
|
|
589
|
-
formatted.forced = adaptation.isForcedSubtitles;
|
|
590
|
-
}
|
|
591
|
-
return formatted;
|
|
523
|
+
var active = currentId === null ? false :
|
|
524
|
+
currentId === adaptation.id;
|
|
525
|
+
return objectAssign(adaptation.toTextTrack(), { active: active });
|
|
592
526
|
});
|
|
593
527
|
};
|
|
594
528
|
/**
|
|
@@ -611,34 +545,21 @@ var TrackChoiceManager = /** @class */ (function () {
|
|
|
611
545
|
(_a = chosenVideoAdaptation === null || chosenVideoAdaptation === void 0 ? void 0 : chosenVideoAdaptation.adaptation.id) !== null && _a !== void 0 ? _a : undefined;
|
|
612
546
|
return videoInfos.adaptations
|
|
613
547
|
.map(function (adaptation) {
|
|
614
|
-
var
|
|
615
|
-
adaptation.
|
|
548
|
+
var active = currentId === null ? false :
|
|
549
|
+
currentId === adaptation.id;
|
|
550
|
+
var track = adaptation.toVideoTrack();
|
|
551
|
+
var trickModeTracks = track.trickModeTracks !== undefined ?
|
|
552
|
+
track.trickModeTracks.map(function (trickModeAdaptation) {
|
|
616
553
|
var isActive = currentId === null ? false :
|
|
617
554
|
currentId === trickModeAdaptation.id;
|
|
618
|
-
|
|
619
|
-
.map(parseVideoRepresentation);
|
|
620
|
-
var trickMode = { id: trickModeAdaptation.id, representations: representations, isTrickModeTrack: true,
|
|
621
|
-
active: isActive };
|
|
622
|
-
if (trickModeAdaptation.isSignInterpreted === true) {
|
|
623
|
-
trickMode.signInterpreted = true;
|
|
624
|
-
}
|
|
625
|
-
return trickMode;
|
|
555
|
+
return objectAssign(trickModeAdaptation, { active: isActive });
|
|
626
556
|
}) :
|
|
627
|
-
|
|
628
|
-
var
|
|
629
|
-
id: adaptation.id,
|
|
630
|
-
active: currentId === null ? false :
|
|
631
|
-
currentId === adaptation.id,
|
|
632
|
-
representations: adaptation.representations.map(parseVideoRepresentation),
|
|
633
|
-
label: adaptation.label,
|
|
634
|
-
};
|
|
635
|
-
if (adaptation.isSignInterpreted === true) {
|
|
636
|
-
formatted.signInterpreted = true;
|
|
637
|
-
}
|
|
557
|
+
[];
|
|
558
|
+
var availableTrack = objectAssign(track, { active: active });
|
|
638
559
|
if (trickModeTracks !== undefined) {
|
|
639
|
-
|
|
560
|
+
availableTrack.trickModeTracks = trickModeTracks;
|
|
640
561
|
}
|
|
641
|
-
return
|
|
562
|
+
return availableTrack;
|
|
642
563
|
});
|
|
643
564
|
};
|
|
644
565
|
/**
|
|
@@ -1058,24 +979,6 @@ function getPeriodItem(periods, period) {
|
|
|
1058
979
|
}
|
|
1059
980
|
}
|
|
1060
981
|
}
|
|
1061
|
-
/**
|
|
1062
|
-
* Parse video Representation into a IVideoRepresentation.
|
|
1063
|
-
* @param {Object} representation
|
|
1064
|
-
* @returns {Object}
|
|
1065
|
-
*/
|
|
1066
|
-
function parseVideoRepresentation(_a) {
|
|
1067
|
-
var id = _a.id, bitrate = _a.bitrate, frameRate = _a.frameRate, width = _a.width, height = _a.height, codec = _a.codec, hdrInfo = _a.hdrInfo;
|
|
1068
|
-
return { id: id, bitrate: bitrate, frameRate: frameRate, width: width, height: height, codec: codec, hdrInfo: hdrInfo };
|
|
1069
|
-
}
|
|
1070
|
-
/**
|
|
1071
|
-
* Parse audio Representation into a ITMAudioRepresentation.
|
|
1072
|
-
* @param {Object} representation
|
|
1073
|
-
* @returns {Object}
|
|
1074
|
-
*/
|
|
1075
|
-
function parseAudioRepresentation(_a) {
|
|
1076
|
-
var id = _a.id, bitrate = _a.bitrate, codec = _a.codec;
|
|
1077
|
-
return { id: id, bitrate: bitrate, codec: codec };
|
|
1078
|
-
}
|
|
1079
982
|
function getRightVideoTrack(adaptation, isTrickModeEnabled) {
|
|
1080
983
|
var _a;
|
|
1081
984
|
if (isTrickModeEnabled &&
|