rx-player 3.31.0-dev.2023052200 → 3.31.0

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 CHANGED
@@ -1,9 +1,11 @@
1
1
  # Changelog
2
2
 
3
- ## v3.31.0-dev.2023052200 (2023-05-22)
3
+ ## v3.31.0 (2023-06-14)
4
4
 
5
5
  ### Features
6
6
 
7
+ - Add `isContentLoaded`, `isBuffering`, `isPaused`, and `getLastStoredContentPosition` methods [#1248]
8
+ - Add `play` and `paused` events [#1253]
7
9
  - Add `trackInfo` property to some `MediaError` to expose information on the track that caused the error [#1241]
8
10
 
9
11
  ### Bug fixes
@@ -12,13 +14,11 @@
12
14
  - Return actual ending duration through the `getVideoDuration` method when playing dynamic contents whose future end is already known [#1235]
13
15
  - DASH/WASM: actually reject the `DASH_WASM.initialize`'s Promise if it fails [#1238]
14
16
  - On the PlayStation 5, set `Infinity` MediaSource duration for live contents to prevent playback issues [#1250]
15
- - DASH/WASM: actually reject the DASH_WASM.initialize's Promise if it fails [#1238]
16
17
 
17
18
  ### Other improvements
18
19
 
19
20
  - adaptive: Perform various adaptive tweaks to avoid switching too much between qualities in some conditions [#1237]
20
21
  - Directfile: Detect "forced" subtitles on Safari when playing directfile contents (such as HLS) [#1239]
21
- - DRM: Reload when playback is unexpectedly frozen with encrypted but only decipherable data in the buffer [#1236]
22
22
  - Improve `"direct"` `audioTrackSwitchingMode` compatibility by re-seeking [#1246]
23
23
  - The `DEBUG_ELEMENT` feature now uses the `monospace` fallback font as a default for a better rendering on apple devices
24
24
  - doc: externalize documentation-generator code
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.31.0-dev.2023052200
1
+ 3.31.0
@@ -105,6 +105,10 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
105
105
  * It should refer to the last content being played.
106
106
  */
107
107
  private _priv_reloadingMetadata;
108
+ /**
109
+ * Store last value of autoPlay, from the last load or reload.
110
+ */
111
+ private _priv_lastAutoPlay;
108
112
  /** All possible Error types emitted by the RxPlayer. */
109
113
  static get ErrorTypes(): Record<IErrorType, IErrorType>;
110
114
  /** All possible Error codes emitted by the RxPlayer. */
@@ -217,6 +221,26 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
217
221
  * @returns {string} - The current Player's state
218
222
  */
219
223
  getPlayerState(): string;
224
+ /**
225
+ * Returns true if a content is loaded.
226
+ * @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
227
+ */
228
+ isContentLoaded(): boolean;
229
+ /**
230
+ * Returns true if the player is buffering.
231
+ * @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
232
+ */
233
+ isBuffering(): boolean;
234
+ /**
235
+ * Returns the play/pause status of the player :
236
+ * - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
237
+ * for when loading is over,
238
+ * - in other states, returns the `<video>` element .paused value,
239
+ * - if the player is disposed, returns `true`.
240
+ * @returns {Boolean} - `true` if the player is paused or will be after loading,
241
+ * `false` otherwise.
242
+ */
243
+ isPaused(): boolean;
220
244
  /**
221
245
  * Returns true if both:
222
246
  * - a content is loaded
@@ -303,6 +327,12 @@ declare class Player extends EventEmitter<IPublicAPIEvent> {
303
327
  * @returns {Number}
304
328
  */
305
329
  getPosition(): number;
330
+ /**
331
+ * Returns the last stored content position, in seconds.
332
+ *
333
+ * @returns {number|undefined}
334
+ */
335
+ getLastStoredContentPosition(): number | undefined;
306
336
  /**
307
337
  * Returns the current playback rate at which the video plays.
308
338
  * @returns {Number}
@@ -832,6 +862,8 @@ interface IPublicAPIEvent {
832
862
  availableTextTracksChange: IAvailableTextTrack[];
833
863
  availableVideoTracksChange: IAvailableVideoTrack[];
834
864
  decipherabilityUpdate: IDecipherabilityUpdateContent[];
865
+ play: null;
866
+ pause: null;
835
867
  seeking: null;
836
868
  seeked: null;
837
869
  streamEvent: IStreamEvent;
@@ -51,6 +51,7 @@ import { ErrorCodes, ErrorTypes, formatError, MediaError, } from "../../errors";
51
51
  import features from "../../features";
52
52
  import log from "../../log";
53
53
  import areArraysOfNumbersEqual from "../../utils/are_arrays_of_numbers_equal";
54
+ import arrayIncludes from "../../utils/array_includes";
54
55
  import assert from "../../utils/assert";
55
56
  import EventEmitter from "../../utils/event_emitter";
56
57
  import idGenerator from "../../utils/id_generator";
@@ -65,7 +66,7 @@ import MediaSourceContentInitializer from "../init/media_source_content_initiali
65
66
  import { checkReloadOptions, parseConstructorOptions, parseLoadVideoOptions, } from "./option_utils";
66
67
  import PlaybackObserver from "./playback_observer";
67
68
  import TrackChoiceManager from "./tracks_management/track_choice_manager";
68
- import { constructPlayerStateReference, emitSeekEvents, isLoadedState, } from "./utils";
69
+ import { constructPlayerStateReference, emitPlayPauseEvents, emitSeekEvents, isLoadedState, } from "./utils";
69
70
  /* eslint-disable @typescript-eslint/naming-convention */
70
71
  var generateContentId = idGenerator();
71
72
  var getPageActivityRef = events.getPageActivityRef, getPictureOnPictureStateRef = events.getPictureOnPictureStateRef, getVideoVisibilityRef = events.getVideoVisibilityRef, getVideoWidthRef = events.getVideoWidthRef, onFullscreenChange = events.onFullscreenChange, onTextTrackAdded = events.onTextTrackAdded, onTextTrackRemoved = events.onTextTrackRemoved;
@@ -89,7 +90,7 @@ var Player = /** @class */ (function (_super) {
89
90
  // Workaround to support Firefox autoplay on FF 42.
90
91
  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
91
92
  videoElement.preload = "auto";
92
- _this.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
93
+ _this.version = /* PLAYER_VERSION */ "3.31.0";
93
94
  _this.log = log;
94
95
  _this.state = "STOPPED";
95
96
  _this.videoElement = videoElement;
@@ -172,6 +173,7 @@ var Player = /** @class */ (function (_super) {
172
173
  _this._priv_preferredTextTracks = preferredTextTracks;
173
174
  _this._priv_preferredVideoTracks = preferredVideoTracks;
174
175
  _this._priv_reloadingMetadata = {};
176
+ _this._priv_lastAutoPlay = false;
175
177
  return _this;
176
178
  }
177
179
  Object.defineProperty(Player, "ErrorTypes", {
@@ -269,6 +271,7 @@ var Player = /** @class */ (function (_super) {
269
271
  log.info("API: Calling loadvideo", options.url, options.transport);
270
272
  this._priv_reloadingMetadata = { options: options };
271
273
  this._priv_initializeContentPlayback(options);
274
+ this._priv_lastAutoPlay = options.autoPlay;
272
275
  };
273
276
  /**
274
277
  * Reload the last loaded content.
@@ -485,11 +488,12 @@ var Player = /** @class */ (function (_super) {
485
488
  log.warn("API: Sending warning:", formattedError);
486
489
  _this.trigger("warning", formattedError);
487
490
  });
488
- initializer.addEventListener("reloadingMediaSource", function () {
491
+ initializer.addEventListener("reloadingMediaSource", function (payload) {
489
492
  contentInfos.segmentBuffersStore = null;
490
493
  if (contentInfos.trackChoiceManager !== null) {
491
494
  contentInfos.trackChoiceManager.resetPeriods();
492
495
  }
496
+ _this._priv_lastAutoPlay = payload.autoPlay;
493
497
  });
494
498
  initializer.addEventListener("inbandEvents", function (inbandEvents) {
495
499
  return _this.trigger("inbandEvents", inbandEvents);
@@ -591,6 +595,48 @@ var Player = /** @class */ (function (_super) {
591
595
  break;
592
596
  }
593
597
  };
598
+ /**
599
+ * `TaskCanceller` allowing to stop emitting `"play"` and `"pause"`
600
+ * events.
601
+ * `null` when such events are not emitted currently.
602
+ */
603
+ var playPauseEventsCanceller = null;
604
+ /**
605
+ * Callback emitting `"play"` and `"pause`" events once the content is
606
+ * loaded, starting from the state indicated in argument.
607
+ * @param {boolean} willAutoPlay - If `false`, we're currently paused.
608
+ */
609
+ var triggerPlayPauseEventsWhenReady = function (willAutoPlay) {
610
+ if (playPauseEventsCanceller !== null) {
611
+ playPauseEventsCanceller.cancel(); // cancel previous logic
612
+ playPauseEventsCanceller = null;
613
+ }
614
+ playerStateRef.onUpdate(function (val, stopListeningToStateUpdates) {
615
+ if (!isLoadedState(val)) {
616
+ return; // content not loaded yet: no event
617
+ }
618
+ stopListeningToStateUpdates();
619
+ if (playPauseEventsCanceller !== null) {
620
+ playPauseEventsCanceller.cancel();
621
+ }
622
+ playPauseEventsCanceller = new TaskCanceller();
623
+ playPauseEventsCanceller.linkToSignal(currentContentCanceller.signal);
624
+ if (willAutoPlay !== !videoElement.paused) {
625
+ // paused status is not at the expected value on load: emit event
626
+ if (videoElement.paused) {
627
+ _this.trigger("pause", null);
628
+ }
629
+ else {
630
+ _this.trigger("play", null);
631
+ }
632
+ }
633
+ emitPlayPauseEvents(videoElement, function () { return _this.trigger("play", null); }, function () { return _this.trigger("pause", null); }, currentContentCanceller.signal);
634
+ }, { emitCurrentValue: false, clearSignal: currentContentCanceller.signal });
635
+ };
636
+ triggerPlayPauseEventsWhenReady(autoPlay);
637
+ initializer.addEventListener("reloadingMediaSource", function (payload) {
638
+ triggerPlayPauseEventsWhenReady(payload.autoPlay);
639
+ });
594
640
  /**
595
641
  * `TaskCanceller` allowing to stop emitting `"seeking"` and `"seeked"`
596
642
  * events.
@@ -732,6 +778,40 @@ var Player = /** @class */ (function (_super) {
732
778
  Player.prototype.getPlayerState = function () {
733
779
  return this.state;
734
780
  };
781
+ /**
782
+ * Returns true if a content is loaded.
783
+ * @returns {Boolean} - `true` if a content is loaded, `false` otherwise.
784
+ */
785
+ Player.prototype.isContentLoaded = function () {
786
+ return !arrayIncludes(["LOADING", "RELOADING", "STOPPED"], this.state);
787
+ };
788
+ /**
789
+ * Returns true if the player is buffering.
790
+ * @returns {Boolean} - `true` if the player is buffering, `false` otherwise.
791
+ */
792
+ Player.prototype.isBuffering = function () {
793
+ return arrayIncludes(["BUFFERING", "SEEKING", "LOADING", "RELOADING"], this.state);
794
+ };
795
+ /**
796
+ * Returns the play/pause status of the player :
797
+ * - when `LOADING` or `RELOADING`, returns the scheduled play/pause condition
798
+ * for when loading is over,
799
+ * - in other states, returns the `<video>` element .paused value,
800
+ * - if the player is disposed, returns `true`.
801
+ * @returns {Boolean} - `true` if the player is paused or will be after loading,
802
+ * `false` otherwise.
803
+ */
804
+ Player.prototype.isPaused = function () {
805
+ if (this.videoElement) {
806
+ if (arrayIncludes(["LOADING", "RELOADING"], this.state)) {
807
+ return !this._priv_lastAutoPlay;
808
+ }
809
+ else {
810
+ return this.videoElement.paused;
811
+ }
812
+ }
813
+ return true;
814
+ };
735
815
  /**
736
816
  * Returns true if both:
737
817
  * - a content is loaded
@@ -897,6 +977,14 @@ var Player = /** @class */ (function (_super) {
897
977
  }
898
978
  return this.videoElement.currentTime;
899
979
  };
980
+ /**
981
+ * Returns the last stored content position, in seconds.
982
+ *
983
+ * @returns {number|undefined}
984
+ */
985
+ Player.prototype.getLastStoredContentPosition = function () {
986
+ return this._priv_reloadingMetadata.reloadPosition;
987
+ };
900
988
  /**
901
989
  * Returns the current playback rate at which the video plays.
902
990
  * @returns {Number}
@@ -2340,5 +2428,5 @@ var Player = /** @class */ (function (_super) {
2340
2428
  };
2341
2429
  return Player;
2342
2430
  }(EventEmitter));
2343
- Player.version = /* PLAYER_VERSION */ "3.31.0-dev.2023052200";
2431
+ Player.version = /* PLAYER_VERSION */ "3.31.0";
2344
2432
  export default Player;
@@ -30,6 +30,16 @@ import { IPlaybackObservation, IReadOnlyPlaybackObserver } from "./playback_obse
30
30
  * remove all listeners this function has registered.
31
31
  */
32
32
  export declare function emitSeekEvents(mediaElement: HTMLMediaElement | null, playbackObserver: IReadOnlyPlaybackObserver<IPlaybackObservation>, onSeeking: () => void, onSeeked: () => void, cancelSignal: CancellationSignal): void;
33
+ /**
34
+ * @param {HTMLMediaElement} mediaElement
35
+ * @param {function} onPlay - Callback called when a play operation has started
36
+ * on `mediaElement`.
37
+ * @param {function} onPause - Callback called when a pause operation has
38
+ * started on `mediaElement`.
39
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
40
+ * remove all listeners this function has registered.
41
+ */
42
+ export declare function emitPlayPauseEvents(mediaElement: HTMLMediaElement | null, onPlay: () => void, onPause: () => void, cancelSignal: CancellationSignal): void;
33
43
  /** Player state dictionnary. */
34
44
  export declare const enum PLAYER_STATES {
35
45
  STOPPED = "STOPPED",
@@ -49,6 +49,26 @@ export function emitSeekEvents(mediaElement, playbackObserver, onSeeking, onSeek
49
49
  }
50
50
  }, { includeLastObservation: true, clearSignal: cancelSignal });
51
51
  }
52
+ /**
53
+ * @param {HTMLMediaElement} mediaElement
54
+ * @param {function} onPlay - Callback called when a play operation has started
55
+ * on `mediaElement`.
56
+ * @param {function} onPause - Callback called when a pause operation has
57
+ * started on `mediaElement`.
58
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
59
+ * remove all listeners this function has registered.
60
+ */
61
+ export function emitPlayPauseEvents(mediaElement, onPlay, onPause, cancelSignal) {
62
+ if (cancelSignal.isCancelled() || mediaElement === null) {
63
+ return;
64
+ }
65
+ mediaElement.addEventListener("play", onPlay);
66
+ mediaElement.addEventListener("pause", onPause);
67
+ cancelSignal.register(function () {
68
+ mediaElement.removeEventListener("play", onPlay);
69
+ mediaElement.removeEventListener("pause", onPause);
70
+ });
71
+ }
52
72
  export function constructPlayerStateReference(initializer, mediaElement, playbackObserver, cancelSignal) {
53
73
  var playerStateRef = createSharedReference("LOADING" /* PLAYER_STATES.LOADING */, cancelSignal);
54
74
  initializer.addEventListener("loaded", function () {
@@ -130,7 +130,13 @@ export default function SessionEventsListener(session, keySystemOptions, keySyst
130
130
  log.info("DRM: No license given, skipping session.update");
131
131
  }
132
132
  else {
133
- return updateSessionWithMessage(session, licenseObject);
133
+ try {
134
+ return updateSessionWithMessage(session, licenseObject);
135
+ }
136
+ catch (err) {
137
+ manualCanceller.cancel();
138
+ callbacks.onError(err);
139
+ }
134
140
  }
135
141
  })
136
142
  .catch(function (err) {
@@ -249,7 +249,7 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
249
249
  if (initCanceller.isUsed()) {
250
250
  return;
251
251
  }
252
- triggerEvent("reloadingMediaSource", null);
252
+ triggerEvent("reloadingMediaSource", reloadOrder);
253
253
  if (initCanceller.isUsed()) {
254
254
  return;
255
255
  }
@@ -95,7 +95,15 @@ export interface IContentInitializerEvents {
95
95
  * Event sent when we're starting attach a new MediaSource to the media element
96
96
  * (after removing the previous one).
97
97
  */
98
- reloadingMediaSource: null;
98
+ reloadingMediaSource: {
99
+ /** The position we're reloading at, in seconds. */
100
+ position: number;
101
+ /**
102
+ * If `true`, we'll play directly after finishing the reloading operation.
103
+ * If `false`, we'll be paused after it.
104
+ */
105
+ autoPlay: boolean;
106
+ };
99
107
  /** Event sent after the player stalled. */
100
108
  stalled: IStallingSituation;
101
109
  /** Event sent when the player goes out of a stalling situation. */