rx-player 4.0.0-beta.1 → 4.0.0-beta.2
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 +40 -0
- 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/eme/load_session.js +1 -1
- 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/config.d.ts +2 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
- 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/playback_observer.js +1 -0
- package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
- package/dist/_esm5.processed/core/api/public_api.js +232 -35
- package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
- package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
- package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
- package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
- package/dist/_esm5.processed/core/api/utils.js +20 -0
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
- package/dist/_esm5.processed/core/init/types.d.ts +9 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
- package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
- package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
- 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.d.ts +3 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
- package/dist/_esm5.processed/default_config.d.ts +25 -0
- package/dist/_esm5.processed/default_config.js +27 -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/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
- package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
- package/dist/_esm5.processed/manifest/adaptation.js +76 -1
- package/dist/_esm5.processed/manifest/manifest.js +1 -1
- package/dist/_esm5.processed/manifest/period.js +2 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
- package/dist/_esm5.processed/manifest/representation.js +21 -0
- package/dist/_esm5.processed/manifest/utils.js +1 -3
- 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 +13 -3
- package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
- 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/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
- package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +4709 -4218
- package/dist/rx-player.min.js +1 -1
- package/package.json +42 -36
- package/scripts/build/generate_build.js +1 -1
- package/scripts/fast_demo_build.js +4 -3
- package/scripts/generate_full_demo.js +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +7 -1
- package/src/compat/eme/load_session.ts +1 -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 +7 -4
- package/src/core/adaptive/buffer_based_chooser.ts +144 -26
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/network_analyzer.ts +9 -4
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/render.ts +1 -1
- package/src/core/api/playback_observer.ts +1 -0
- package/src/core/api/public_api.ts +277 -44
- package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
- package/src/core/api/track_management/track_dispatcher.ts +37 -14
- package/src/core/api/track_management/tracks_store.ts +77 -167
- package/src/core/api/utils.ts +26 -0
- package/src/core/decrypt/session_events_listener.ts +6 -1
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
- package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
- package/src/core/init/directfile_content_initializer.ts +1 -0
- package/src/core/init/media_source_content_initializer.ts +52 -9
- package/src/core/init/types.ts +9 -1
- package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
- package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
- package/src/core/init/utils/rebuffering_controller.ts +114 -3
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/types.ts +16 -4
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
- package/src/core/stream/period/period_stream.ts +2 -1
- package/src/core/stream/representation/representation_stream.ts +34 -22
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
- package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
- package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
- package/src/default_config.ts +29 -2
- 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/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
- package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
- package/src/manifest/__tests__/manifest.test.ts +7 -7
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +89 -1
- package/src/manifest/manifest.ts +1 -1
- package/src/manifest/period.ts +4 -2
- package/src/manifest/representation.ts +67 -1
- package/src/manifest/utils.ts +1 -3
- 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 +16 -1
- package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/typings/globals.d.ts +20 -20
- package/src/utils/is_null_or_undefined.ts +1 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
- 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
|
@@ -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 &&
|
|
@@ -126,6 +126,12 @@ function estimateStarvationModeBitrate(pendingRequests, playbackInfo, currentRep
|
|
|
126
126
|
}
|
|
127
127
|
var concernedRequest = concernedRequests[0];
|
|
128
128
|
var now = performance.now();
|
|
129
|
+
var minimumRequestTime = concernedRequest.content.segment.duration * 1.5;
|
|
130
|
+
minimumRequestTime = Math.min(minimumRequestTime, 3000);
|
|
131
|
+
minimumRequestTime = Math.max(minimumRequestTime, 12000);
|
|
132
|
+
if (now - concernedRequest.requestTimestamp < minimumRequestTime) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
129
135
|
var lastProgressEvent = concernedRequest.progress.length > 0 ?
|
|
130
136
|
concernedRequest.progress[concernedRequest.progress.length - 1] :
|
|
131
137
|
undefined;
|
|
@@ -138,7 +144,7 @@ function estimateStarvationModeBitrate(pendingRequests, playbackInfo, currentRep
|
|
|
138
144
|
// Calculate estimated time spent rebuffering if we continue doing that request.
|
|
139
145
|
var expectedRebufferingTime = remainingTime -
|
|
140
146
|
(realBufferGap / speed);
|
|
141
|
-
if (expectedRebufferingTime >
|
|
147
|
+
if (expectedRebufferingTime > 2500) {
|
|
142
148
|
return bandwidthEstimate;
|
|
143
149
|
}
|
|
144
150
|
}
|
|
@@ -320,12 +326,9 @@ var NetworkAnalyzer = /** @class */ (function () {
|
|
|
320
326
|
if (currentRepresentation === null) {
|
|
321
327
|
return true;
|
|
322
328
|
}
|
|
323
|
-
else if (bitrate
|
|
329
|
+
else if (bitrate >= currentRepresentation.bitrate) {
|
|
324
330
|
return false;
|
|
325
331
|
}
|
|
326
|
-
else if (bitrate > currentRepresentation.bitrate) {
|
|
327
|
-
return !this._inStarvationMode;
|
|
328
|
-
}
|
|
329
332
|
return shouldDirectlySwitchToLowBitrate(playbackInfo, currentRequests, this._lowLatencyMode);
|
|
330
333
|
};
|
|
331
334
|
return NetworkAnalyzer;
|
|
@@ -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";
|
|
@@ -114,6 +114,7 @@ var PlaybackObserver = /** @class */ (function () {
|
|
|
114
114
|
*/
|
|
115
115
|
PlaybackObserver.prototype.setCurrentTime = function (time) {
|
|
116
116
|
this._internalSeeksIncoming.push(time);
|
|
117
|
+
log.info("API: Seeking internally", time);
|
|
117
118
|
this._mediaElement.currentTime = time;
|
|
118
119
|
};
|
|
119
120
|
/**
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { IErrorCode, IErrorType } from "../../errors";
|
|
17
17
|
import Manifest, { Adaptation, Representation } from "../../manifest";
|
|
18
|
-
import { IAudioRepresentation, IAudioTrack, IAudioTrackSetting, IAvailableAudioTrack, IAvailableTextTrack, IAvailableVideoTrack, IBrokenRepresentationsLockContext, IConstructorOptions, IKeySystemConfigurationOutput, ILoadVideoOptions, ILockedAudioRepresentationsSettings, ILockedVideoRepresentationsSettings, ITrackUpdateEventPayload, IPeriod, IPeriodChangeEvent, IPlayerError, IPlayerState, IPositionUpdate, IStreamEvent, ITextTrack, IVideoRepresentation, ITextTrackSetting, IVideoTrack, IVideoTrackSetting } from "../../public_types";
|
|
18
|
+
import { IAudioRepresentation, IAudioTrack, IAudioTrackSetting, IAvailableAudioTrack, IAvailableTextTrack, IAvailableVideoTrack, IBrokenRepresentationsLockContext, IConstructorOptions, IKeySystemConfigurationOutput, ILoadVideoOptions, ILockedAudioRepresentationsSettings, ILockedVideoRepresentationsSettings, ITrackUpdateEventPayload, IRepresentationListUpdateContext, IPeriod, IPeriodChangeEvent, IPlayerError, IPlayerState, IPositionUpdate, IStreamEvent, ITextTrack, IVideoRepresentation, ITextTrackSetting, IVideoTrack, IVideoTrackSetting } from "../../public_types";
|
|
19
19
|
import EventEmitter, { IListener } from "../../utils/event_emitter";
|
|
20
20
|
import Logger from "../../utils/logger";
|
|
21
21
|
import { IBufferedChunk, IBufferType } from "../segment_buffers";
|
|
@@ -95,6 +95,10 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
95
95
|
* It should refer to the last content being played.
|
|
96
96
|
*/
|
|
97
97
|
private _priv_reloadingMetadata;
|
|
98
|
+
/**
|
|
99
|
+
* Store last value of autoPlay, from the last load or reload.
|
|
100
|
+
*/
|
|
101
|
+
private _priv_lastAutoPlay;
|
|
98
102
|
/** All possible Error types emitted by the RxPlayer. */
|
|
99
103
|
static get ErrorTypes(): Record<IErrorType, IErrorType>;
|
|
100
104
|
/** All possible Error codes emitted by the RxPlayer. */
|
|
@@ -178,6 +182,26 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
178
182
|
* @returns {string} - The current Player's state
|
|
179
183
|
*/
|
|
180
184
|
getPlayerState(): string;
|
|
185
|
+
/**
|
|
186
|
+
* Returns true if a content is loaded.
|
|
187
|
+
* @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
|
|
188
|
+
*/
|
|
189
|
+
isContentLoaded(): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Returns true if the player is buffering.
|
|
192
|
+
* @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
|
|
193
|
+
*/
|
|
194
|
+
isBuffering(): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Returns the play/pause status of the player :
|
|
197
|
+
* - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
|
|
198
|
+
* for when loading is over,
|
|
199
|
+
* - in other states, returns the `<video>` element .paused value,
|
|
200
|
+
* - if the player is disposed, returns `true`.
|
|
201
|
+
* @returns {Boolean} - `true` if the player is paused or will be after loading,
|
|
202
|
+
* `false` otherwise.
|
|
203
|
+
*/
|
|
204
|
+
isPaused(): boolean;
|
|
181
205
|
/**
|
|
182
206
|
* Returns true if both:
|
|
183
207
|
* - a content is loaded
|
|
@@ -250,6 +274,12 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
250
274
|
* @returns {Number}
|
|
251
275
|
*/
|
|
252
276
|
getPosition(): number;
|
|
277
|
+
/**
|
|
278
|
+
* Returns the last stored content position, in seconds.
|
|
279
|
+
*
|
|
280
|
+
* @returns {number|undefined}
|
|
281
|
+
*/
|
|
282
|
+
getLastStoredContentPosition(): number | undefined;
|
|
253
283
|
/**
|
|
254
284
|
* Returns the current playback rate at which the video plays.
|
|
255
285
|
* @returns {Number}
|
|
@@ -630,6 +660,26 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
630
660
|
*/
|
|
631
661
|
private _priv_initializeMediaElementTracksStore;
|
|
632
662
|
private _priv_callTracksStoreGetterSetter;
|
|
663
|
+
/**
|
|
664
|
+
* Method to call when some event lead to a high for possibility that the
|
|
665
|
+
* available tracks for the given type have changed.
|
|
666
|
+
* Send the corresponding `available*Tracks` change event with the last
|
|
667
|
+
* available tracks.
|
|
668
|
+
*
|
|
669
|
+
* @param {string} trackType
|
|
670
|
+
* @param {Object|undefined} [oPeriodRef] - optional period object used by the
|
|
671
|
+
* `tracksStore` API, allows to optimize the method by bypassing this step.
|
|
672
|
+
*/
|
|
673
|
+
private _priv_onAvailableTracksMayHaveChanged;
|
|
674
|
+
/**
|
|
675
|
+
* Method to call when a fatal error lead to the stopping of the current
|
|
676
|
+
* content.
|
|
677
|
+
*
|
|
678
|
+
* @param {*} err - The error encountered.
|
|
679
|
+
* @param {Object} contentInfos - The `IPublicApiContentInfos` object linked
|
|
680
|
+
* to the content for which the error was received.
|
|
681
|
+
*/
|
|
682
|
+
private _priv_onFatalError;
|
|
633
683
|
}
|
|
634
684
|
/** Every events sent by the RxPlayer's public API. */
|
|
635
685
|
interface IPublicAPIEvent {
|
|
@@ -647,9 +697,12 @@ interface IPublicAPIEvent {
|
|
|
647
697
|
availableAudioTracksChange: IAvailableAudioTrack[];
|
|
648
698
|
availableTextTracksChange: IAvailableTextTrack[];
|
|
649
699
|
availableVideoTracksChange: IAvailableVideoTrack[];
|
|
700
|
+
play: null;
|
|
701
|
+
pause: null;
|
|
650
702
|
newAvailablePeriods: IPeriod[];
|
|
651
703
|
brokenRepresentationsLock: IBrokenRepresentationsLockContext;
|
|
652
704
|
trackUpdate: ITrackUpdateEventPayload;
|
|
705
|
+
representationListUpdate: IRepresentationListUpdateContext;
|
|
653
706
|
seeking: null;
|
|
654
707
|
seeked: null;
|
|
655
708
|
streamEvent: IStreamEvent;
|
|
@@ -50,6 +50,8 @@ import config from "../../config";
|
|
|
50
50
|
import { ErrorCodes, ErrorTypes, formatError, MediaError, } from "../../errors";
|
|
51
51
|
import features from "../../features";
|
|
52
52
|
import log from "../../log";
|
|
53
|
+
import arrayFind from "../../utils/array_find";
|
|
54
|
+
import arrayIncludes from "../../utils/array_includes";
|
|
53
55
|
import assert from "../../utils/assert";
|
|
54
56
|
import assertUnreachable from "../../utils/assert_unreachable";
|
|
55
57
|
import EventEmitter from "../../utils/event_emitter";
|
|
@@ -64,7 +66,7 @@ import MediaSourceContentInitializer from "../init/media_source_content_initiali
|
|
|
64
66
|
import { checkReloadOptions, parseConstructorOptions, parseLoadVideoOptions, } from "./option_utils";
|
|
65
67
|
import PlaybackObserver from "./playback_observer";
|
|
66
68
|
import TracksStore from "./track_management/tracks_store";
|
|
67
|
-
import { constructPlayerStateReference, emitSeekEvents, isLoadedState, } from "./utils";
|
|
69
|
+
import { constructPlayerStateReference, emitPlayPauseEvents, emitSeekEvents, isLoadedState, } from "./utils";
|
|
68
70
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
69
71
|
var generateContentId = idGenerator();
|
|
70
72
|
var getPictureOnPictureStateRef = events.getPictureOnPictureStateRef, getVideoVisibilityRef = events.getVideoVisibilityRef, getElementResolutionRef = events.getElementResolutionRef, getScreenResolutionRef = events.getScreenResolutionRef;
|
|
@@ -86,7 +88,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
86
88
|
// Workaround to support Firefox autoplay on FF 42.
|
|
87
89
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
88
90
|
videoElement.preload = "auto";
|
|
89
|
-
_this.version = /* PLAYER_VERSION */ "4.0.0-beta.
|
|
91
|
+
_this.version = /* PLAYER_VERSION */ "4.0.0-beta.2";
|
|
90
92
|
_this.log = log;
|
|
91
93
|
_this.state = "STOPPED";
|
|
92
94
|
_this.videoElement = videoElement;
|
|
@@ -114,6 +116,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
114
116
|
_this._priv_contentEventsMemory = {};
|
|
115
117
|
_this._priv_setPlayerState("STOPPED" /* PLAYER_STATES.STOPPED */);
|
|
116
118
|
_this._priv_reloadingMetadata = {};
|
|
119
|
+
_this._priv_lastAutoPlay = false;
|
|
117
120
|
return _this;
|
|
118
121
|
}
|
|
119
122
|
Object.defineProperty(Player, "ErrorTypes", {
|
|
@@ -211,6 +214,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
211
214
|
log.info("API: Calling loadvideo", options.url, options.transport);
|
|
212
215
|
this._priv_reloadingMetadata = { options: options };
|
|
213
216
|
this._priv_initializeContentPlayback(options);
|
|
217
|
+
this._priv_lastAutoPlay = options.autoPlay;
|
|
214
218
|
};
|
|
215
219
|
/**
|
|
216
220
|
* Reload the last loaded content.
|
|
@@ -386,23 +390,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
386
390
|
};
|
|
387
391
|
// Bind events
|
|
388
392
|
initializer.addEventListener("error", function (error) {
|
|
389
|
-
|
|
390
|
-
defaultCode: "NONE",
|
|
391
|
-
defaultReason: "An unknown error stopped content playback.",
|
|
392
|
-
});
|
|
393
|
-
formattedError.fatal = true;
|
|
394
|
-
contentInfos.currentContentCanceller.cancel();
|
|
395
|
-
_this._priv_cleanUpCurrentContentState();
|
|
396
|
-
_this._priv_currentError = formattedError;
|
|
397
|
-
log.error("API: The player stopped because of an error", error instanceof Error ? error : "");
|
|
398
|
-
_this._priv_setPlayerState("STOPPED" /* PLAYER_STATES.STOPPED */);
|
|
399
|
-
// TODO This condition is here because the eventual callback called when the
|
|
400
|
-
// player state is updated can launch a new content, thus the error will not
|
|
401
|
-
// be here anymore, in which case triggering the "error" event is unwanted.
|
|
402
|
-
// This is very ugly though, and we should probable have a better solution
|
|
403
|
-
if (_this._priv_currentError === formattedError) {
|
|
404
|
-
_this.trigger("error", formattedError);
|
|
405
|
-
}
|
|
393
|
+
_this._priv_onFatalError(error, contentInfos);
|
|
406
394
|
});
|
|
407
395
|
initializer.addEventListener("warning", function (error) {
|
|
408
396
|
var formattedError = formatError(error, {
|
|
@@ -412,11 +400,12 @@ var Player = /** @class */ (function (_super) {
|
|
|
412
400
|
log.warn("API: Sending warning:", formattedError);
|
|
413
401
|
_this.trigger("warning", formattedError);
|
|
414
402
|
});
|
|
415
|
-
initializer.addEventListener("reloadingMediaSource", function () {
|
|
403
|
+
initializer.addEventListener("reloadingMediaSource", function (payload) {
|
|
416
404
|
contentInfos.segmentBuffersStore = null;
|
|
417
405
|
if (contentInfos.tracksStore !== null) {
|
|
418
406
|
contentInfos.tracksStore.resetPeriodObjects();
|
|
419
407
|
}
|
|
408
|
+
_this._priv_lastAutoPlay = payload.autoPlay;
|
|
420
409
|
});
|
|
421
410
|
initializer.addEventListener("inbandEvents", function (inbandEvents) {
|
|
422
411
|
return _this.trigger("inbandEvents", inbandEvents);
|
|
@@ -500,6 +489,48 @@ var Player = /** @class */ (function (_super) {
|
|
|
500
489
|
break;
|
|
501
490
|
}
|
|
502
491
|
};
|
|
492
|
+
/**
|
|
493
|
+
* `TaskCanceller` allowing to stop emitting `"play"` and `"pause"`
|
|
494
|
+
* events.
|
|
495
|
+
* `null` when such events are not emitted currently.
|
|
496
|
+
*/
|
|
497
|
+
var playPauseEventsCanceller = null;
|
|
498
|
+
/**
|
|
499
|
+
* Callback emitting `"play"` and `"pause`" events once the content is
|
|
500
|
+
* loaded, starting from the state indicated in argument.
|
|
501
|
+
* @param {boolean} willAutoPlay - If `false`, we're currently paused.
|
|
502
|
+
*/
|
|
503
|
+
var triggerPlayPauseEventsWhenReady = function (willAutoPlay) {
|
|
504
|
+
if (playPauseEventsCanceller !== null) {
|
|
505
|
+
playPauseEventsCanceller.cancel(); // cancel previous logic
|
|
506
|
+
playPauseEventsCanceller = null;
|
|
507
|
+
}
|
|
508
|
+
playerStateRef.onUpdate(function (val, stopListeningToStateUpdates) {
|
|
509
|
+
if (!isLoadedState(val)) {
|
|
510
|
+
return; // content not loaded yet: no event
|
|
511
|
+
}
|
|
512
|
+
stopListeningToStateUpdates();
|
|
513
|
+
if (playPauseEventsCanceller !== null) {
|
|
514
|
+
playPauseEventsCanceller.cancel();
|
|
515
|
+
}
|
|
516
|
+
playPauseEventsCanceller = new TaskCanceller();
|
|
517
|
+
playPauseEventsCanceller.linkToSignal(currentContentCanceller.signal);
|
|
518
|
+
if (willAutoPlay !== !videoElement.paused) {
|
|
519
|
+
// paused status is not at the expected value on load: emit event
|
|
520
|
+
if (videoElement.paused) {
|
|
521
|
+
_this.trigger("pause", null);
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
_this.trigger("play", null);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
emitPlayPauseEvents(videoElement, function () { return _this.trigger("play", null); }, function () { return _this.trigger("pause", null); }, currentContentCanceller.signal);
|
|
528
|
+
}, { emitCurrentValue: false, clearSignal: currentContentCanceller.signal });
|
|
529
|
+
};
|
|
530
|
+
triggerPlayPauseEventsWhenReady(autoPlay);
|
|
531
|
+
initializer.addEventListener("reloadingMediaSource", function (payload) {
|
|
532
|
+
triggerPlayPauseEventsWhenReady(payload.autoPlay);
|
|
533
|
+
});
|
|
503
534
|
/**
|
|
504
535
|
* `TaskCanceller` allowing to stop emitting `"seeking"` and `"seeked"`
|
|
505
536
|
* events.
|
|
@@ -569,6 +600,40 @@ var Player = /** @class */ (function (_super) {
|
|
|
569
600
|
Player.prototype.getPlayerState = function () {
|
|
570
601
|
return this.state;
|
|
571
602
|
};
|
|
603
|
+
/**
|
|
604
|
+
* Returns true if a content is loaded.
|
|
605
|
+
* @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
|
|
606
|
+
*/
|
|
607
|
+
Player.prototype.isContentLoaded = function () {
|
|
608
|
+
return !arrayIncludes(["LOADING", "RELOADING", "STOPPED"], this.state);
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Returns true if the player is buffering.
|
|
612
|
+
* @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
|
|
613
|
+
*/
|
|
614
|
+
Player.prototype.isBuffering = function () {
|
|
615
|
+
return arrayIncludes(["BUFFERING", "SEEKING", "LOADING", "RELOADING"], this.state);
|
|
616
|
+
};
|
|
617
|
+
/**
|
|
618
|
+
* Returns the play/pause status of the player :
|
|
619
|
+
* - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
|
|
620
|
+
* for when loading is over,
|
|
621
|
+
* - in other states, returns the `<video>` element .paused value,
|
|
622
|
+
* - if the player is disposed, returns `true`.
|
|
623
|
+
* @returns {Boolean} - `true` if the player is paused or will be after loading,
|
|
624
|
+
* `false` otherwise.
|
|
625
|
+
*/
|
|
626
|
+
Player.prototype.isPaused = function () {
|
|
627
|
+
if (this.videoElement) {
|
|
628
|
+
if (arrayIncludes(["LOADING", "RELOADING"], this.state)) {
|
|
629
|
+
return !this._priv_lastAutoPlay;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
return this.videoElement.paused;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return true;
|
|
636
|
+
};
|
|
572
637
|
/**
|
|
573
638
|
* Returns true if both:
|
|
574
639
|
* - a content is loaded
|
|
@@ -709,6 +774,14 @@ var Player = /** @class */ (function (_super) {
|
|
|
709
774
|
}
|
|
710
775
|
return this.videoElement.currentTime;
|
|
711
776
|
};
|
|
777
|
+
/**
|
|
778
|
+
* Returns the last stored content position, in seconds.
|
|
779
|
+
*
|
|
780
|
+
* @returns {number|undefined}
|
|
781
|
+
*/
|
|
782
|
+
Player.prototype.getLastStoredContentPosition = function () {
|
|
783
|
+
return this._priv_reloadingMetadata.reloadPosition;
|
|
784
|
+
};
|
|
712
785
|
/**
|
|
713
786
|
* Returns the current playback rate at which the video plays.
|
|
714
787
|
* @returns {Number}
|
|
@@ -909,6 +982,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
909
982
|
if (positionWanted === undefined) {
|
|
910
983
|
throw new Error("invalid time given");
|
|
911
984
|
}
|
|
985
|
+
log.info("API: API Seek to", positionWanted);
|
|
912
986
|
this.videoElement.currentTime = positionWanted;
|
|
913
987
|
return positionWanted;
|
|
914
988
|
};
|
|
@@ -1555,20 +1629,32 @@ var Player = /** @class */ (function (_super) {
|
|
|
1555
1629
|
return; // Event for another content
|
|
1556
1630
|
}
|
|
1557
1631
|
contentInfos.manifest = manifest;
|
|
1558
|
-
var cancelSignal = contentInfos.currentContentCanceller.signal;
|
|
1559
1632
|
this._priv_reloadingMetadata.manifest = manifest;
|
|
1560
|
-
|
|
1633
|
+
var tracksStore = new TracksStore({
|
|
1561
1634
|
preferTrickModeTracks: this._priv_preferTrickModeTracks,
|
|
1562
1635
|
defaultAudioTrackSwitchingMode: contentInfos.defaultAudioTrackSwitchingMode,
|
|
1563
1636
|
});
|
|
1564
|
-
contentInfos.tracksStore
|
|
1637
|
+
contentInfos.tracksStore = tracksStore;
|
|
1638
|
+
tracksStore.addEventListener("newAvailablePeriods", function (p) {
|
|
1565
1639
|
_this.trigger("newAvailablePeriods", p);
|
|
1566
1640
|
});
|
|
1567
|
-
|
|
1641
|
+
tracksStore.addEventListener("brokenRepresentationsLock", function (e) {
|
|
1568
1642
|
_this.trigger("brokenRepresentationsLock", e);
|
|
1569
1643
|
});
|
|
1570
|
-
|
|
1644
|
+
tracksStore.addEventListener("trackUpdate", function (e) {
|
|
1645
|
+
var _a, _b;
|
|
1571
1646
|
_this.trigger("trackUpdate", e);
|
|
1647
|
+
var currentPeriod = (_b = (_a = _this._priv_contentInfos) === null || _a === void 0 ? void 0 : _a.currentPeriod) !== null && _b !== void 0 ? _b : undefined;
|
|
1648
|
+
if (e.reason === "no-playable-representation" &&
|
|
1649
|
+
e.period.id === (currentPeriod === null || currentPeriod === void 0 ? void 0 : currentPeriod.id)) {
|
|
1650
|
+
_this._priv_onAvailableTracksMayHaveChanged(e.trackType);
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1653
|
+
contentInfos.tracksStore.addEventListener("warning", function (err) {
|
|
1654
|
+
_this.trigger("warning", err);
|
|
1655
|
+
});
|
|
1656
|
+
contentInfos.tracksStore.addEventListener("error", function (err) {
|
|
1657
|
+
_this._priv_onFatalError(err, contentInfos);
|
|
1572
1658
|
});
|
|
1573
1659
|
contentInfos.tracksStore.updatePeriodList(manifest);
|
|
1574
1660
|
manifest.addEventListener("manifestUpdate", function (updates) {
|
|
@@ -1578,8 +1664,8 @@ var Player = /** @class */ (function (_super) {
|
|
|
1578
1664
|
contentInfos.tracksStore.updatePeriodList(manifest);
|
|
1579
1665
|
}
|
|
1580
1666
|
var currentPeriod = (_b = (_a = _this._priv_contentInfos) === null || _a === void 0 ? void 0 : _a.currentPeriod) !== null && _b !== void 0 ? _b : undefined;
|
|
1581
|
-
var
|
|
1582
|
-
if (currentPeriod === undefined || isNullOrUndefined(
|
|
1667
|
+
var currTracksStore = (_c = _this._priv_contentInfos) === null || _c === void 0 ? void 0 : _c.tracksStore;
|
|
1668
|
+
if (currentPeriod === undefined || isNullOrUndefined(currTracksStore)) {
|
|
1583
1669
|
return;
|
|
1584
1670
|
}
|
|
1585
1671
|
for (var _i = 0, _d = updates.updatedPeriods; _i < _d.length; _i++) {
|
|
@@ -1588,21 +1674,64 @@ var Player = /** @class */ (function (_super) {
|
|
|
1588
1674
|
if (update.result.addedAdaptations.length > 0 ||
|
|
1589
1675
|
update.result.removedAdaptations.length > 0) {
|
|
1590
1676
|
// We might have new (or less) tracks, send events just to be sure
|
|
1591
|
-
var periodRef =
|
|
1677
|
+
var periodRef = currTracksStore.getPeriodObjectFromPeriod(currentPeriod);
|
|
1592
1678
|
if (periodRef === undefined) {
|
|
1593
1679
|
return;
|
|
1594
1680
|
}
|
|
1595
|
-
|
|
1596
|
-
_this.
|
|
1597
|
-
|
|
1598
|
-
_this._priv_triggerEventIfNotStopped("availableTextTracksChange", textTracks !== null && textTracks !== void 0 ? textTracks : [], cancelSignal);
|
|
1599
|
-
var videoTracks = tracksStore.getAvailableVideoTracks(periodRef);
|
|
1600
|
-
_this._priv_triggerEventIfNotStopped("availableVideoTracksChange", videoTracks !== null && videoTracks !== void 0 ? videoTracks : [], cancelSignal);
|
|
1681
|
+
_this._priv_onAvailableTracksMayHaveChanged("audio");
|
|
1682
|
+
_this._priv_onAvailableTracksMayHaveChanged("text");
|
|
1683
|
+
_this._priv_onAvailableTracksMayHaveChanged("video");
|
|
1601
1684
|
}
|
|
1602
1685
|
}
|
|
1603
1686
|
return;
|
|
1604
1687
|
}
|
|
1605
1688
|
}, contentInfos.currentContentCanceller.signal);
|
|
1689
|
+
manifest.addEventListener("decipherabilityUpdate", function (elts) {
|
|
1690
|
+
/**
|
|
1691
|
+
* Array of tuples only including once the Period/Track combination, and
|
|
1692
|
+
* only when it concerns the currently-selected track.
|
|
1693
|
+
*/
|
|
1694
|
+
var periodsAndTrackTypes = elts.reduce(function (acc, elt) {
|
|
1695
|
+
var _a, _b, _c;
|
|
1696
|
+
var isFound = arrayFind(acc, function (x) { return x[0].id === elt.period.id &&
|
|
1697
|
+
x[1] === elt.adaptation.type; }) === undefined;
|
|
1698
|
+
if (!isFound) {
|
|
1699
|
+
// Only consider the currently-selected tracks.
|
|
1700
|
+
// NOTE: Maybe there's room for optimizations? Unclear.
|
|
1701
|
+
var tStore = contentInfos.tracksStore;
|
|
1702
|
+
if (tStore === null) {
|
|
1703
|
+
return acc;
|
|
1704
|
+
}
|
|
1705
|
+
var isCurrent = false;
|
|
1706
|
+
var periodRef = tStore.getPeriodObjectFromPeriod(elt.period);
|
|
1707
|
+
if (periodRef === undefined) {
|
|
1708
|
+
return acc;
|
|
1709
|
+
}
|
|
1710
|
+
switch (elt.adaptation.type) {
|
|
1711
|
+
case "audio":
|
|
1712
|
+
isCurrent = ((_a = tStore
|
|
1713
|
+
.getChosenAudioTrack(periodRef)) === null || _a === void 0 ? void 0 : _a.id) === elt.adaptation.id;
|
|
1714
|
+
break;
|
|
1715
|
+
case "video":
|
|
1716
|
+
isCurrent = ((_b = tStore
|
|
1717
|
+
.getChosenVideoTrack(periodRef)) === null || _b === void 0 ? void 0 : _b.id) === elt.adaptation.id;
|
|
1718
|
+
break;
|
|
1719
|
+
case "text":
|
|
1720
|
+
isCurrent = ((_c = tStore
|
|
1721
|
+
.getChosenTextTrack(periodRef)) === null || _c === void 0 ? void 0 : _c.id) === elt.adaptation.id;
|
|
1722
|
+
break;
|
|
1723
|
+
}
|
|
1724
|
+
if (isCurrent) {
|
|
1725
|
+
acc.push([elt.period, elt.adaptation.type]);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
return acc;
|
|
1729
|
+
}, []);
|
|
1730
|
+
for (var _i = 0, periodsAndTrackTypes_1 = periodsAndTrackTypes; _i < periodsAndTrackTypes_1.length; _i++) {
|
|
1731
|
+
var _a = periodsAndTrackTypes_1[_i], period = _a[0], trackType = _a[1];
|
|
1732
|
+
_this._priv_triggerEventIfNotStopped("representationListUpdate", { period: period, trackType: trackType, reason: "decipherability-update" }, contentInfos.currentContentCanceller.signal);
|
|
1733
|
+
}
|
|
1734
|
+
}, contentInfos.currentContentCanceller.signal);
|
|
1606
1735
|
};
|
|
1607
1736
|
/**
|
|
1608
1737
|
* Triggered each times the current Period Changed.
|
|
@@ -1962,7 +2091,75 @@ var Player = /** @class */ (function (_super) {
|
|
|
1962
2091
|
}
|
|
1963
2092
|
return cb(tracksStore, periodRef);
|
|
1964
2093
|
};
|
|
2094
|
+
/**
|
|
2095
|
+
* Method to call when some event lead to a high for possibility that the
|
|
2096
|
+
* available tracks for the given type have changed.
|
|
2097
|
+
* Send the corresponding `available*Tracks` change event with the last
|
|
2098
|
+
* available tracks.
|
|
2099
|
+
*
|
|
2100
|
+
* @param {string} trackType
|
|
2101
|
+
* @param {Object|undefined} [oPeriodRef] - optional period object used by the
|
|
2102
|
+
* `tracksStore` API, allows to optimize the method by bypassing this step.
|
|
2103
|
+
*/
|
|
2104
|
+
Player.prototype._priv_onAvailableTracksMayHaveChanged = function (trackType, oPeriodRef) {
|
|
2105
|
+
var contentInfos = this._priv_contentInfos;
|
|
2106
|
+
if (contentInfos === null) {
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
var currentPeriod = contentInfos.currentPeriod, tracksStore = contentInfos.tracksStore, currentContentCanceller = contentInfos.currentContentCanceller;
|
|
2110
|
+
var cancelSignal = currentContentCanceller.signal;
|
|
2111
|
+
if (isNullOrUndefined(currentPeriod) || tracksStore === null) {
|
|
2112
|
+
return;
|
|
2113
|
+
}
|
|
2114
|
+
var periodRef = oPeriodRef !== null && oPeriodRef !== void 0 ? oPeriodRef : tracksStore.getPeriodObjectFromPeriod(currentPeriod);
|
|
2115
|
+
if (periodRef === undefined) {
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
switch (trackType) {
|
|
2119
|
+
case "video":
|
|
2120
|
+
var videoTracks = tracksStore.getAvailableVideoTracks(periodRef);
|
|
2121
|
+
this._priv_triggerEventIfNotStopped("availableVideoTracksChange", videoTracks !== null && videoTracks !== void 0 ? videoTracks : [], cancelSignal);
|
|
2122
|
+
break;
|
|
2123
|
+
case "audio":
|
|
2124
|
+
var audioTracks = tracksStore.getAvailableAudioTracks(periodRef);
|
|
2125
|
+
this._priv_triggerEventIfNotStopped("availableAudioTracksChange", audioTracks !== null && audioTracks !== void 0 ? audioTracks : [], cancelSignal);
|
|
2126
|
+
break;
|
|
2127
|
+
case "text":
|
|
2128
|
+
var textTracks = tracksStore.getAvailableTextTracks(periodRef);
|
|
2129
|
+
this._priv_triggerEventIfNotStopped("availableTextTracksChange", textTracks !== null && textTracks !== void 0 ? textTracks : [], cancelSignal);
|
|
2130
|
+
break;
|
|
2131
|
+
default:
|
|
2132
|
+
assertUnreachable(trackType);
|
|
2133
|
+
}
|
|
2134
|
+
};
|
|
2135
|
+
/**
|
|
2136
|
+
* Method to call when a fatal error lead to the stopping of the current
|
|
2137
|
+
* content.
|
|
2138
|
+
*
|
|
2139
|
+
* @param {*} err - The error encountered.
|
|
2140
|
+
* @param {Object} contentInfos - The `IPublicApiContentInfos` object linked
|
|
2141
|
+
* to the content for which the error was received.
|
|
2142
|
+
*/
|
|
2143
|
+
Player.prototype._priv_onFatalError = function (err, contentInfos) {
|
|
2144
|
+
var formattedError = formatError(err, {
|
|
2145
|
+
defaultCode: "NONE",
|
|
2146
|
+
defaultReason: "An unknown error stopped content playback.",
|
|
2147
|
+
});
|
|
2148
|
+
formattedError.fatal = true;
|
|
2149
|
+
contentInfos.currentContentCanceller.cancel();
|
|
2150
|
+
this._priv_cleanUpCurrentContentState();
|
|
2151
|
+
this._priv_currentError = formattedError;
|
|
2152
|
+
log.error("API: The player stopped because of an error", formattedError);
|
|
2153
|
+
this._priv_setPlayerState("STOPPED" /* PLAYER_STATES.STOPPED */);
|
|
2154
|
+
// TODO This condition is here because the eventual callback called when the
|
|
2155
|
+
// player state is updated can launch a new content, thus the error will not
|
|
2156
|
+
// be here anymore, in which case triggering the "error" event is unwanted.
|
|
2157
|
+
// This is very ugly though, and we should probable have a better solution
|
|
2158
|
+
if (this._priv_currentError === formattedError) {
|
|
2159
|
+
this.trigger("error", formattedError);
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
1965
2162
|
return Player;
|
|
1966
2163
|
}(EventEmitter));
|
|
1967
|
-
Player.version = /* PLAYER_VERSION */ "4.0.0-beta.
|
|
2164
|
+
Player.version = /* PLAYER_VERSION */ "4.0.0-beta.2";
|
|
1968
2165
|
export default Player;
|
|
@@ -102,7 +102,14 @@ function createTextTracks(textTracks) {
|
|
|
102
102
|
"_" +
|
|
103
103
|
occurences.toString();
|
|
104
104
|
languagesOccurences[language] = occurences + 1;
|
|
105
|
-
|
|
105
|
+
// Safari seems to be indicating that the subtitles track is a forced
|
|
106
|
+
// subtitles track by setting the `kind` attribute to `"forced"`.
|
|
107
|
+
// As of now (2023-04-04), this is not standard.
|
|
108
|
+
// @see https://github.com/whatwg/html/issues/4472
|
|
109
|
+
var forced = textTrack.kind === "forced" ?
|
|
110
|
+
true :
|
|
111
|
+
undefined;
|
|
112
|
+
var track = { language: textTrack.language, forced: forced, label: textTrack.label, id: id, normalized: normalizeLanguage(textTrack.language),
|
|
106
113
|
closedCaption: textTrack.kind === "captions" };
|
|
107
114
|
newTextTracks.push({ track: track, nativeTrack: textTrack });
|
|
108
115
|
}
|
|
@@ -293,6 +300,8 @@ var MediaElementTracksStore = /** @class */ (function (_super) {
|
|
|
293
300
|
return this._textTracks.map(function (_a) {
|
|
294
301
|
var track = _a.track, nativeTrack = _a.nativeTrack;
|
|
295
302
|
return { id: track.id,
|
|
303
|
+
label: track.label,
|
|
304
|
+
forced: track.forced,
|
|
296
305
|
language: track.language,
|
|
297
306
|
normalized: track.normalized,
|
|
298
307
|
closedCaption: track.closedCaption,
|