@vindral/web-sdk 4.5.1-9-gb7e40eb2c → 4.6.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/{CiWlpwR0.js → BBVSf5AB.js} +2 -2
- package/{DRMUL9n5.js → BT3QQVZE.js} +1 -1
- package/{DZ1kJVLj.js → BV8nX-0b.js} +1032 -1006
- package/{ir89G42i.js → BZPrVRbb.js} +44 -21
- package/BddIq5-p.js +154 -0
- package/{Cj61-Cjf.js → CN8w7_en.js} +3462 -2912
- package/cast-sender.d.ts +28 -0
- package/core.d.ts +115 -1
- package/core.js +3 -3
- package/legacy.d.ts +115 -1
- package/legacy.es.js +4183 -3603
- package/legacy.umd.js +124 -86
- package/package.json +1 -1
- package/player.d.ts +80 -2
- package/player.js +2 -2
- package/react.d.ts +80 -2
- package/vindral-player-component.js +2 -2
- package/CN4egPyY.js +0 -149
package/package.json
CHANGED
package/player.d.ts
CHANGED
|
@@ -174,6 +174,17 @@ interface DrmOptions {
|
|
|
174
174
|
type Media = "audio" | "video" | "audio+video";
|
|
175
175
|
type WebCodecsHardwareAccelerationPreference = "no-preference" | "prefer-hardware" | "prefer-software";
|
|
176
176
|
type DecoderType = "mse" | "webcodecs" | "wasm";
|
|
177
|
+
interface MediaSessionMetadata {
|
|
178
|
+
title?: string;
|
|
179
|
+
artist?: string;
|
|
180
|
+
album?: string;
|
|
181
|
+
/** Fetched by the operating system, so the URLs should not carry credentials. */
|
|
182
|
+
artwork?: Array<{
|
|
183
|
+
src: string;
|
|
184
|
+
sizes?: string;
|
|
185
|
+
type?: string;
|
|
186
|
+
}>;
|
|
187
|
+
}
|
|
177
188
|
interface Options {
|
|
178
189
|
/**
|
|
179
190
|
* URL to use when connecting to the stream
|
|
@@ -269,6 +280,20 @@ interface Options {
|
|
|
269
280
|
* Legacy alias kept for backwards compatibility.
|
|
270
281
|
*/
|
|
271
282
|
iosBackgroundPlayEnabled?: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Show the stream in the browser and OS media controls (notification, lock screen, toolbar) and
|
|
285
|
+
* let play and pause from there reach the SDK. Enabled by default.
|
|
286
|
+
*
|
|
287
|
+
* The SDK takes over `navigator.mediaSession` for the document, so a page with its own Media
|
|
288
|
+
* Session integration should disable this. On canvas playback paths a silent `<audio>` element is
|
|
289
|
+
* added to `document.body` for the controls to attach to.
|
|
290
|
+
*/
|
|
291
|
+
mediaSessionEnabled?: boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Title, artist and artwork for the media controls. Without it the browser derives them from the
|
|
294
|
+
* page. Read once at construction.
|
|
295
|
+
*/
|
|
296
|
+
mediaSessionMetadata?: MediaSessionMetadata;
|
|
272
297
|
/**
|
|
273
298
|
* Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
|
|
274
299
|
* the viewers bandwidth and thus avoiding buffering events. This also disables the
|
|
@@ -383,6 +408,9 @@ interface Options {
|
|
|
383
408
|
* This enables platform media features such as fullscreen and picture-in-picture
|
|
384
409
|
* for non-MSE playback by routing the canvas output through a `<video>` element.
|
|
385
410
|
*
|
|
411
|
+
* On iOS the audio then plays from its own element, so it continues in the background and under
|
|
412
|
+
* lock. After an extended pause from the lock screen, reopening Safari may be required to resume.
|
|
413
|
+
*
|
|
386
414
|
* Disabled by default.
|
|
387
415
|
*/
|
|
388
416
|
streamToMediaElementEnabled?: boolean;
|
|
@@ -836,6 +864,13 @@ interface JitterModuleStatistics {
|
|
|
836
864
|
audioJitter: JitterStatistics | undefined;
|
|
837
865
|
videoJitter: JitterStatistics | undefined;
|
|
838
866
|
}
|
|
867
|
+
type DecoyState = "detached" | "attached" | "playing" | "blocked";
|
|
868
|
+
interface MediaSessionModuleStatistics {
|
|
869
|
+
mediaSessionSupported: boolean;
|
|
870
|
+
mediaSessionOwner: boolean;
|
|
871
|
+
mediaSessionPlaybackState: MediaSessionPlaybackState;
|
|
872
|
+
decoyState?: DecoyState;
|
|
873
|
+
}
|
|
839
874
|
interface MseModuleStatistics {
|
|
840
875
|
quotaErrorCount: number;
|
|
841
876
|
mediaSourceOpenTime: number;
|
|
@@ -947,8 +982,10 @@ interface SyncModuleStatistics {
|
|
|
947
982
|
interface VideoPlayerStatistics {
|
|
948
983
|
renderedFrameCount: number;
|
|
949
984
|
rendererDroppedFrameCount: number;
|
|
985
|
+
/** The platform's own view of the audio context, which a mute reading cannot tell apart. */
|
|
986
|
+
audioContextState?: AudioContextState | "none";
|
|
950
987
|
}
|
|
951
|
-
type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
|
|
988
|
+
type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & Partial<MediaSessionModuleStatistics> & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
|
|
952
989
|
type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAgentInformation"]> & {
|
|
953
990
|
/**
|
|
954
991
|
* Version of the @vindral/web-sdk being used.
|
|
@@ -1000,6 +1037,8 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
1000
1037
|
streamToMediaElementEnabled?: boolean;
|
|
1001
1038
|
/** @deprecated */
|
|
1002
1039
|
iosMediaElementEnabled?: boolean;
|
|
1040
|
+
/** Whether the element carrying the audio is paused right now, on the sinks that have one. */
|
|
1041
|
+
mediaElementPaused?: boolean;
|
|
1003
1042
|
/**
|
|
1004
1043
|
* Average bitrate for the entire session in bits/second.
|
|
1005
1044
|
*/
|
|
@@ -1026,6 +1065,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1026
1065
|
private static MAX_POOL_SIZE;
|
|
1027
1066
|
private static REMOVE_CUE_THRESHOLD;
|
|
1028
1067
|
private static BACKGROUND_INACTIVITY_DISCONNECT_TIMEOUT;
|
|
1068
|
+
/** How long a pause on a visible page may still turn out to be the platform backgrounding us. */
|
|
1069
|
+
private static VISIBLE_PAUSE_DISCONNECT_DELAY;
|
|
1029
1070
|
/**
|
|
1030
1071
|
* Picture in picture
|
|
1031
1072
|
*/
|
|
@@ -1068,7 +1109,10 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1068
1109
|
private offscreenCanvasElement?;
|
|
1069
1110
|
private webCodecsRenditionSupport;
|
|
1070
1111
|
private hasCalledConnect;
|
|
1112
|
+
private hasRequestedAudioSession;
|
|
1071
1113
|
private isUserPaused;
|
|
1114
|
+
/** Only the sinks that carry the audio report this, so a paused element here means silence. */
|
|
1115
|
+
private isMediaElementPaused;
|
|
1072
1116
|
private latestEmittedLanguages;
|
|
1073
1117
|
private wakeLock;
|
|
1074
1118
|
private pool;
|
|
@@ -1084,6 +1128,7 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1084
1128
|
private sizes;
|
|
1085
1129
|
private isSuspended;
|
|
1086
1130
|
private inactivityDisconnectInterval;
|
|
1131
|
+
private visiblePauseTimeout;
|
|
1087
1132
|
private offscreenSubtitleInterval?;
|
|
1088
1133
|
constructor(options: Options);
|
|
1089
1134
|
/**
|
|
@@ -1385,6 +1430,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1385
1430
|
private isSupportedVideoCodecProfile;
|
|
1386
1431
|
private supportedAudioCodecs;
|
|
1387
1432
|
private initializeDecodingModule;
|
|
1433
|
+
private capturesCanvasOnWebKit;
|
|
1434
|
+
private connectWebKitVideoOutput;
|
|
1388
1435
|
/**
|
|
1389
1436
|
* Set up a polling interval that forwards subtitle cues to the decoder worker
|
|
1390
1437
|
* when OffscreenCanvas rendering is active. This is needed because the canvas modules'
|
|
@@ -1416,6 +1463,12 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1416
1463
|
* Pauses the stream. Call .play() to resume playback again.
|
|
1417
1464
|
*/
|
|
1418
1465
|
pause: () => void;
|
|
1466
|
+
/**
|
|
1467
|
+
* A browser-initiated decoy pause means an interruption (another app took the focus, headphones
|
|
1468
|
+
* unplugged), so give the audio up rather than play over it. WebKit holds the decoy on purpose.
|
|
1469
|
+
*/
|
|
1470
|
+
private yieldToInterruption;
|
|
1471
|
+
private fromNativeControls;
|
|
1419
1472
|
private registerDebugInstance;
|
|
1420
1473
|
/**
|
|
1421
1474
|
*
|
|
@@ -1448,8 +1501,18 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1448
1501
|
private resetModules;
|
|
1449
1502
|
private disconnectForInactivePage;
|
|
1450
1503
|
private scheduleInactivityDisconnect;
|
|
1504
|
+
/**
|
|
1505
|
+
* iOS pauses the element a moment before it hides the page, and that pause reaches us while the
|
|
1506
|
+
* page still reports visible. Acting on it at once tears the session down, so every app switch
|
|
1507
|
+
* comes back as a full reconnect. Wait for the hide that follows a platform pause instead.
|
|
1508
|
+
* Nowhere else pauses before hiding, so there a visible pause is the viewer's at once.
|
|
1509
|
+
*/
|
|
1510
|
+
private onVisiblePause;
|
|
1511
|
+
private disconnectForVisiblePause;
|
|
1512
|
+
private clearVisiblePauseDisconnect;
|
|
1451
1513
|
private clearInactivityDisconnect;
|
|
1452
1514
|
private isHiddenWithBackgroundPlayback;
|
|
1515
|
+
private isVideoOnScreen;
|
|
1453
1516
|
private isHiddenWithBackgroundPlayDisabled;
|
|
1454
1517
|
private suspend;
|
|
1455
1518
|
private unsuspend;
|
|
@@ -1467,6 +1530,20 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1467
1530
|
private get targetSubscription();
|
|
1468
1531
|
private timeToFirstFrame;
|
|
1469
1532
|
private resolvedDecoder;
|
|
1533
|
+
/**
|
|
1534
|
+
* On mobile Chromium with WebCodecs audio the play action arrives but no sound comes back until
|
|
1535
|
+
* the page is visible, so a hidden pause is a stop there. Reads the decoder in use.
|
|
1536
|
+
*/
|
|
1537
|
+
private hiddenPauseIsStop;
|
|
1538
|
+
private usesSplitCanvasAudio;
|
|
1539
|
+
private isWebKitCanvasPath;
|
|
1540
|
+
private holdsDecoyWhilePaused;
|
|
1541
|
+
private streamsToMediaElement;
|
|
1542
|
+
/**
|
|
1543
|
+
* Safari 16.4+: a playback audio session keeps Web Audio alive in the background. Document-wide
|
|
1544
|
+
* and not restorable, so it waits for playback to be wanted rather than for construction.
|
|
1545
|
+
*/
|
|
1546
|
+
private requestAudioSessionOnce;
|
|
1470
1547
|
private willUseMediaSource;
|
|
1471
1548
|
private shouldUseWebCodecs;
|
|
1472
1549
|
private isWebCodecsVideoAvailable;
|
|
@@ -1937,6 +2014,7 @@ export declare class Controller extends HTMLElement {
|
|
|
1937
2014
|
"mse-opus-enabled",
|
|
1938
2015
|
"background-play-enabled",
|
|
1939
2016
|
"ios-background-play-enabled",
|
|
2017
|
+
"media-session-enabled",
|
|
1940
2018
|
"ios-wake-lock-enabled",
|
|
1941
2019
|
"stream-to-media-element-enabled",
|
|
1942
2020
|
"ios-media-element-enabled",
|
|
@@ -2053,7 +2131,7 @@ export declare class PlayButton extends VindralButton {
|
|
|
2053
2131
|
*/
|
|
2054
2132
|
export declare class Player extends HTMLElement {
|
|
2055
2133
|
#private;
|
|
2056
|
-
static observedAttributes: readonly ("title" | "offline" | "advanced" | "poster" | "language" | "channels" | "buffering" | "paused" | "volume" | "muted" | "duration" | "user-interacting" | "is-casting" | "cast-available" | "cast-receiver-name" | "ui-locked" | "hide-ui-on-pause" | "is-fullscreen" | "is-fullscreen-fallback" | "rendition-levels" | "rendition-level" | "max-video-bit-rate" | "max-initial-bit-rate" | "abr-enabled" | "size-based-resolution-cap-enabled" | "channel-id" | "channel-group-id" | "pip-available" | "is-pip" | "airplay-available" | "is-airplaying" | "media" | "languages" | "text-tracks" | "text-track" | "needs-user-input-video" | "needs-user-input-audio" | "authentication-token" | "volume-level" | "cast" | "airplay" | "pip" | "fullscreen" | "double-click-fullscreen" | "vu-meter" | "timeshift" | "timeshift-position" | "timeline-markers" | "poster-src" | "debug-panel-open" | "target-buffer-time" | "drift" | "playback-latency" | "connection-state" | "url" | "decoders" | "min-buffer-time" | "max-buffer-time" | "edge-url" | "cast-receiver-id" | "cast-background" | "log-level" | "max-size" | "max-audio-bit-rate" | "burst-enabled" | "mse-enabled" | "mse-opus-enabled" | "background-play-enabled" | "ios-background-play-enabled" | "ios-wake-lock-enabled" | "stream-to-media-element-enabled" | "ios-media-element-enabled" | "telemetry-enabled" | "video-codecs" | "drm-headers" | "drm-queryparams" | "drm-widevine-video-robustness" | "drm-widevine-audio-robustness" | "drm-playready-video-robustness" | "drm-playready-audio-robustness" | "webtransport-enabled" | "webcodecs-hardware-acceleration" | "offscreen-canvas-enabled" | "reconnect-retries" | "auto-instance-enabled" | "advanced-rendition-menu-enabled" | "refresh-poster-enabled" | "stream-poll-enabled")[];
|
|
2134
|
+
static observedAttributes: readonly ("title" | "offline" | "advanced" | "poster" | "language" | "channels" | "buffering" | "paused" | "volume" | "muted" | "duration" | "user-interacting" | "is-casting" | "cast-available" | "cast-receiver-name" | "ui-locked" | "hide-ui-on-pause" | "is-fullscreen" | "is-fullscreen-fallback" | "rendition-levels" | "rendition-level" | "max-video-bit-rate" | "max-initial-bit-rate" | "abr-enabled" | "size-based-resolution-cap-enabled" | "channel-id" | "channel-group-id" | "pip-available" | "is-pip" | "airplay-available" | "is-airplaying" | "media" | "languages" | "text-tracks" | "text-track" | "needs-user-input-video" | "needs-user-input-audio" | "authentication-token" | "volume-level" | "cast" | "airplay" | "pip" | "fullscreen" | "double-click-fullscreen" | "vu-meter" | "timeshift" | "timeshift-position" | "timeline-markers" | "poster-src" | "debug-panel-open" | "target-buffer-time" | "drift" | "playback-latency" | "connection-state" | "url" | "decoders" | "min-buffer-time" | "max-buffer-time" | "edge-url" | "cast-receiver-id" | "cast-background" | "log-level" | "max-size" | "max-audio-bit-rate" | "burst-enabled" | "mse-enabled" | "mse-opus-enabled" | "background-play-enabled" | "ios-background-play-enabled" | "media-session-enabled" | "ios-wake-lock-enabled" | "stream-to-media-element-enabled" | "ios-media-element-enabled" | "telemetry-enabled" | "video-codecs" | "drm-headers" | "drm-queryparams" | "drm-widevine-video-robustness" | "drm-widevine-audio-robustness" | "drm-playready-video-robustness" | "drm-playready-audio-robustness" | "webtransport-enabled" | "webcodecs-hardware-acceleration" | "offscreen-canvas-enabled" | "reconnect-retries" | "auto-instance-enabled" | "advanced-rendition-menu-enabled" | "refresh-poster-enabled" | "stream-poll-enabled")[];
|
|
2057
2135
|
constructor();
|
|
2058
2136
|
connectedCallback(): void;
|
|
2059
2137
|
disconnectedCallback(): void;
|
package/player.js
CHANGED
package/react.d.ts
CHANGED
|
@@ -176,6 +176,17 @@ interface DrmOptions {
|
|
|
176
176
|
type Media = "audio" | "video" | "audio+video";
|
|
177
177
|
type WebCodecsHardwareAccelerationPreference = "no-preference" | "prefer-hardware" | "prefer-software";
|
|
178
178
|
type DecoderType = "mse" | "webcodecs" | "wasm";
|
|
179
|
+
interface MediaSessionMetadata {
|
|
180
|
+
title?: string;
|
|
181
|
+
artist?: string;
|
|
182
|
+
album?: string;
|
|
183
|
+
/** Fetched by the operating system, so the URLs should not carry credentials. */
|
|
184
|
+
artwork?: Array<{
|
|
185
|
+
src: string;
|
|
186
|
+
sizes?: string;
|
|
187
|
+
type?: string;
|
|
188
|
+
}>;
|
|
189
|
+
}
|
|
179
190
|
interface Options {
|
|
180
191
|
/**
|
|
181
192
|
* URL to use when connecting to the stream
|
|
@@ -271,6 +282,20 @@ interface Options {
|
|
|
271
282
|
* Legacy alias kept for backwards compatibility.
|
|
272
283
|
*/
|
|
273
284
|
iosBackgroundPlayEnabled?: boolean;
|
|
285
|
+
/**
|
|
286
|
+
* Show the stream in the browser and OS media controls (notification, lock screen, toolbar) and
|
|
287
|
+
* let play and pause from there reach the SDK. Enabled by default.
|
|
288
|
+
*
|
|
289
|
+
* The SDK takes over `navigator.mediaSession` for the document, so a page with its own Media
|
|
290
|
+
* Session integration should disable this. On canvas playback paths a silent `<audio>` element is
|
|
291
|
+
* added to `document.body` for the controls to attach to.
|
|
292
|
+
*/
|
|
293
|
+
mediaSessionEnabled?: boolean;
|
|
294
|
+
/**
|
|
295
|
+
* Title, artist and artwork for the media controls. Without it the browser derives them from the
|
|
296
|
+
* page. Read once at construction.
|
|
297
|
+
*/
|
|
298
|
+
mediaSessionMetadata?: MediaSessionMetadata;
|
|
274
299
|
/**
|
|
275
300
|
* Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
|
|
276
301
|
* the viewers bandwidth and thus avoiding buffering events. This also disables the
|
|
@@ -385,6 +410,9 @@ interface Options {
|
|
|
385
410
|
* This enables platform media features such as fullscreen and picture-in-picture
|
|
386
411
|
* for non-MSE playback by routing the canvas output through a `<video>` element.
|
|
387
412
|
*
|
|
413
|
+
* On iOS the audio then plays from its own element, so it continues in the background and under
|
|
414
|
+
* lock. After an extended pause from the lock screen, reopening Safari may be required to resume.
|
|
415
|
+
*
|
|
388
416
|
* Disabled by default.
|
|
389
417
|
*/
|
|
390
418
|
streamToMediaElementEnabled?: boolean;
|
|
@@ -838,6 +866,13 @@ interface JitterModuleStatistics {
|
|
|
838
866
|
audioJitter: JitterStatistics | undefined;
|
|
839
867
|
videoJitter: JitterStatistics | undefined;
|
|
840
868
|
}
|
|
869
|
+
type DecoyState = "detached" | "attached" | "playing" | "blocked";
|
|
870
|
+
interface MediaSessionModuleStatistics {
|
|
871
|
+
mediaSessionSupported: boolean;
|
|
872
|
+
mediaSessionOwner: boolean;
|
|
873
|
+
mediaSessionPlaybackState: MediaSessionPlaybackState;
|
|
874
|
+
decoyState?: DecoyState;
|
|
875
|
+
}
|
|
841
876
|
interface MseModuleStatistics {
|
|
842
877
|
quotaErrorCount: number;
|
|
843
878
|
mediaSourceOpenTime: number;
|
|
@@ -949,8 +984,10 @@ interface SyncModuleStatistics {
|
|
|
949
984
|
interface VideoPlayerStatistics {
|
|
950
985
|
renderedFrameCount: number;
|
|
951
986
|
rendererDroppedFrameCount: number;
|
|
987
|
+
/** The platform's own view of the audio context, which a mute reading cannot tell apart. */
|
|
988
|
+
audioContextState?: AudioContextState | "none";
|
|
952
989
|
}
|
|
953
|
-
type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
|
|
990
|
+
type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & Partial<MediaSessionModuleStatistics> & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
|
|
954
991
|
type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAgentInformation"]> & {
|
|
955
992
|
/**
|
|
956
993
|
* Version of the @vindral/web-sdk being used.
|
|
@@ -1002,6 +1039,8 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
1002
1039
|
streamToMediaElementEnabled?: boolean;
|
|
1003
1040
|
/** @deprecated */
|
|
1004
1041
|
iosMediaElementEnabled?: boolean;
|
|
1042
|
+
/** Whether the element carrying the audio is paused right now, on the sinks that have one. */
|
|
1043
|
+
mediaElementPaused?: boolean;
|
|
1005
1044
|
/**
|
|
1006
1045
|
* Average bitrate for the entire session in bits/second.
|
|
1007
1046
|
*/
|
|
@@ -1028,6 +1067,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1028
1067
|
private static MAX_POOL_SIZE;
|
|
1029
1068
|
private static REMOVE_CUE_THRESHOLD;
|
|
1030
1069
|
private static BACKGROUND_INACTIVITY_DISCONNECT_TIMEOUT;
|
|
1070
|
+
/** How long a pause on a visible page may still turn out to be the platform backgrounding us. */
|
|
1071
|
+
private static VISIBLE_PAUSE_DISCONNECT_DELAY;
|
|
1031
1072
|
/**
|
|
1032
1073
|
* Picture in picture
|
|
1033
1074
|
*/
|
|
@@ -1070,7 +1111,10 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1070
1111
|
private offscreenCanvasElement?;
|
|
1071
1112
|
private webCodecsRenditionSupport;
|
|
1072
1113
|
private hasCalledConnect;
|
|
1114
|
+
private hasRequestedAudioSession;
|
|
1073
1115
|
private isUserPaused;
|
|
1116
|
+
/** Only the sinks that carry the audio report this, so a paused element here means silence. */
|
|
1117
|
+
private isMediaElementPaused;
|
|
1074
1118
|
private latestEmittedLanguages;
|
|
1075
1119
|
private wakeLock;
|
|
1076
1120
|
private pool;
|
|
@@ -1086,6 +1130,7 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1086
1130
|
private sizes;
|
|
1087
1131
|
private isSuspended;
|
|
1088
1132
|
private inactivityDisconnectInterval;
|
|
1133
|
+
private visiblePauseTimeout;
|
|
1089
1134
|
private offscreenSubtitleInterval?;
|
|
1090
1135
|
constructor(options: Options);
|
|
1091
1136
|
/**
|
|
@@ -1387,6 +1432,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1387
1432
|
private isSupportedVideoCodecProfile;
|
|
1388
1433
|
private supportedAudioCodecs;
|
|
1389
1434
|
private initializeDecodingModule;
|
|
1435
|
+
private capturesCanvasOnWebKit;
|
|
1436
|
+
private connectWebKitVideoOutput;
|
|
1390
1437
|
/**
|
|
1391
1438
|
* Set up a polling interval that forwards subtitle cues to the decoder worker
|
|
1392
1439
|
* when OffscreenCanvas rendering is active. This is needed because the canvas modules'
|
|
@@ -1418,6 +1465,12 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1418
1465
|
* Pauses the stream. Call .play() to resume playback again.
|
|
1419
1466
|
*/
|
|
1420
1467
|
pause: () => void;
|
|
1468
|
+
/**
|
|
1469
|
+
* A browser-initiated decoy pause means an interruption (another app took the focus, headphones
|
|
1470
|
+
* unplugged), so give the audio up rather than play over it. WebKit holds the decoy on purpose.
|
|
1471
|
+
*/
|
|
1472
|
+
private yieldToInterruption;
|
|
1473
|
+
private fromNativeControls;
|
|
1421
1474
|
private registerDebugInstance;
|
|
1422
1475
|
/**
|
|
1423
1476
|
*
|
|
@@ -1450,8 +1503,18 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1450
1503
|
private resetModules;
|
|
1451
1504
|
private disconnectForInactivePage;
|
|
1452
1505
|
private scheduleInactivityDisconnect;
|
|
1506
|
+
/**
|
|
1507
|
+
* iOS pauses the element a moment before it hides the page, and that pause reaches us while the
|
|
1508
|
+
* page still reports visible. Acting on it at once tears the session down, so every app switch
|
|
1509
|
+
* comes back as a full reconnect. Wait for the hide that follows a platform pause instead.
|
|
1510
|
+
* Nowhere else pauses before hiding, so there a visible pause is the viewer's at once.
|
|
1511
|
+
*/
|
|
1512
|
+
private onVisiblePause;
|
|
1513
|
+
private disconnectForVisiblePause;
|
|
1514
|
+
private clearVisiblePauseDisconnect;
|
|
1453
1515
|
private clearInactivityDisconnect;
|
|
1454
1516
|
private isHiddenWithBackgroundPlayback;
|
|
1517
|
+
private isVideoOnScreen;
|
|
1455
1518
|
private isHiddenWithBackgroundPlayDisabled;
|
|
1456
1519
|
private suspend;
|
|
1457
1520
|
private unsuspend;
|
|
@@ -1469,6 +1532,20 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1469
1532
|
private get targetSubscription();
|
|
1470
1533
|
private timeToFirstFrame;
|
|
1471
1534
|
private resolvedDecoder;
|
|
1535
|
+
/**
|
|
1536
|
+
* On mobile Chromium with WebCodecs audio the play action arrives but no sound comes back until
|
|
1537
|
+
* the page is visible, so a hidden pause is a stop there. Reads the decoder in use.
|
|
1538
|
+
*/
|
|
1539
|
+
private hiddenPauseIsStop;
|
|
1540
|
+
private usesSplitCanvasAudio;
|
|
1541
|
+
private isWebKitCanvasPath;
|
|
1542
|
+
private holdsDecoyWhilePaused;
|
|
1543
|
+
private streamsToMediaElement;
|
|
1544
|
+
/**
|
|
1545
|
+
* Safari 16.4+: a playback audio session keeps Web Audio alive in the background. Document-wide
|
|
1546
|
+
* and not restorable, so it waits for playback to be wanted rather than for construction.
|
|
1547
|
+
*/
|
|
1548
|
+
private requestAudioSessionOnce;
|
|
1472
1549
|
private willUseMediaSource;
|
|
1473
1550
|
private shouldUseWebCodecs;
|
|
1474
1551
|
private isWebCodecsVideoAvailable;
|
|
@@ -1946,6 +2023,7 @@ declare class Controller extends HTMLElement {
|
|
|
1946
2023
|
"mse-opus-enabled",
|
|
1947
2024
|
"background-play-enabled",
|
|
1948
2025
|
"ios-background-play-enabled",
|
|
2026
|
+
"media-session-enabled",
|
|
1949
2027
|
"ios-wake-lock-enabled",
|
|
1950
2028
|
"stream-to-media-element-enabled",
|
|
1951
2029
|
"ios-media-element-enabled",
|
|
@@ -2063,7 +2141,7 @@ declare class PlayButton extends VindralButton {
|
|
|
2063
2141
|
type PlayerAttributes = (typeof Player.observedAttributes)[number];
|
|
2064
2142
|
declare class Player extends HTMLElement {
|
|
2065
2143
|
#private;
|
|
2066
|
-
static observedAttributes: readonly ("title" | "offline" | "advanced" | "poster" | "language" | "channels" | "buffering" | "paused" | "volume" | "muted" | "duration" | "user-interacting" | "is-casting" | "cast-available" | "cast-receiver-name" | "ui-locked" | "hide-ui-on-pause" | "is-fullscreen" | "is-fullscreen-fallback" | "rendition-levels" | "rendition-level" | "max-video-bit-rate" | "max-initial-bit-rate" | "abr-enabled" | "size-based-resolution-cap-enabled" | "channel-id" | "channel-group-id" | "pip-available" | "is-pip" | "airplay-available" | "is-airplaying" | "media" | "languages" | "text-tracks" | "text-track" | "needs-user-input-video" | "needs-user-input-audio" | "authentication-token" | "volume-level" | "cast" | "airplay" | "pip" | "fullscreen" | "double-click-fullscreen" | "vu-meter" | "timeshift" | "timeshift-position" | "timeline-markers" | "poster-src" | "debug-panel-open" | "target-buffer-time" | "drift" | "playback-latency" | "connection-state" | "url" | "decoders" | "min-buffer-time" | "max-buffer-time" | "edge-url" | "cast-receiver-id" | "cast-background" | "log-level" | "max-size" | "max-audio-bit-rate" | "burst-enabled" | "mse-enabled" | "mse-opus-enabled" | "background-play-enabled" | "ios-background-play-enabled" | "ios-wake-lock-enabled" | "stream-to-media-element-enabled" | "ios-media-element-enabled" | "telemetry-enabled" | "video-codecs" | "drm-headers" | "drm-queryparams" | "drm-widevine-video-robustness" | "drm-widevine-audio-robustness" | "drm-playready-video-robustness" | "drm-playready-audio-robustness" | "webtransport-enabled" | "webcodecs-hardware-acceleration" | "offscreen-canvas-enabled" | "reconnect-retries" | "auto-instance-enabled" | "advanced-rendition-menu-enabled" | "refresh-poster-enabled" | "stream-poll-enabled")[];
|
|
2144
|
+
static observedAttributes: readonly ("title" | "offline" | "advanced" | "poster" | "language" | "channels" | "buffering" | "paused" | "volume" | "muted" | "duration" | "user-interacting" | "is-casting" | "cast-available" | "cast-receiver-name" | "ui-locked" | "hide-ui-on-pause" | "is-fullscreen" | "is-fullscreen-fallback" | "rendition-levels" | "rendition-level" | "max-video-bit-rate" | "max-initial-bit-rate" | "abr-enabled" | "size-based-resolution-cap-enabled" | "channel-id" | "channel-group-id" | "pip-available" | "is-pip" | "airplay-available" | "is-airplaying" | "media" | "languages" | "text-tracks" | "text-track" | "needs-user-input-video" | "needs-user-input-audio" | "authentication-token" | "volume-level" | "cast" | "airplay" | "pip" | "fullscreen" | "double-click-fullscreen" | "vu-meter" | "timeshift" | "timeshift-position" | "timeline-markers" | "poster-src" | "debug-panel-open" | "target-buffer-time" | "drift" | "playback-latency" | "connection-state" | "url" | "decoders" | "min-buffer-time" | "max-buffer-time" | "edge-url" | "cast-receiver-id" | "cast-background" | "log-level" | "max-size" | "max-audio-bit-rate" | "burst-enabled" | "mse-enabled" | "mse-opus-enabled" | "background-play-enabled" | "ios-background-play-enabled" | "media-session-enabled" | "ios-wake-lock-enabled" | "stream-to-media-element-enabled" | "ios-media-element-enabled" | "telemetry-enabled" | "video-codecs" | "drm-headers" | "drm-queryparams" | "drm-widevine-video-robustness" | "drm-widevine-audio-robustness" | "drm-playready-video-robustness" | "drm-playready-audio-robustness" | "webtransport-enabled" | "webcodecs-hardware-acceleration" | "offscreen-canvas-enabled" | "reconnect-retries" | "auto-instance-enabled" | "advanced-rendition-menu-enabled" | "refresh-poster-enabled" | "stream-poll-enabled")[];
|
|
2067
2145
|
constructor();
|
|
2068
2146
|
connectedCallback(): void;
|
|
2069
2147
|
disconnectedCallback(): void;
|
package/CN4egPyY.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { n as e, t } from "./BsfwXDui.js";
|
|
2
|
-
import { t as n } from "./DrWNJwZx.js";
|
|
3
|
-
import { t as r } from "./BKeRxR4O.js";
|
|
4
|
-
import { i, n as a, t as o } from "./CbyVl6wP.js";
|
|
5
|
-
//#region ../../libs/web-sdk/src/decoders/PendingSampleMap.ts
|
|
6
|
-
var s = class {
|
|
7
|
-
constructor() {
|
|
8
|
-
e(this, "map", /* @__PURE__ */ new Map());
|
|
9
|
-
}
|
|
10
|
-
enqueue(e, t) {
|
|
11
|
-
let r = this.map.get(e);
|
|
12
|
-
if (r) r.push(t);
|
|
13
|
-
else {
|
|
14
|
-
let r = new n(Infinity);
|
|
15
|
-
r.push(t), this.map.set(e, r);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
dequeue(e) {
|
|
19
|
-
let t = this.map.get(e);
|
|
20
|
-
if (!t) return;
|
|
21
|
-
let n = t.pop();
|
|
22
|
-
return t.isEmpty() && this.map.delete(e), n;
|
|
23
|
-
}
|
|
24
|
-
dequeueWithFallback(e) {
|
|
25
|
-
let t = this.dequeue(e);
|
|
26
|
-
if (t !== void 0) return t;
|
|
27
|
-
for (let [e, t] of this.map) {
|
|
28
|
-
let n = t.pop();
|
|
29
|
-
if (t.isEmpty() && this.map.delete(e), n !== void 0) return n;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
removeLast(e) {
|
|
33
|
-
let t = this.map.get(e);
|
|
34
|
-
t && (t.popLast(), t.isEmpty() && this.map.delete(e));
|
|
35
|
-
}
|
|
36
|
-
clear() {
|
|
37
|
-
this.map.clear();
|
|
38
|
-
}
|
|
39
|
-
}, c, l = globalThis, u = class {
|
|
40
|
-
constructor(c) {
|
|
41
|
-
var l = this;
|
|
42
|
-
e(this, "decodedSamples", []), e(this, "decoder", null), e(this, "logger", void 0), e(this, "initSegments", /* @__PURE__ */ new Map()), e(this, "previousSample", void 0), e(this, "previousCodec", void 0), e(this, "pendingSamples", new s()), e(this, "errors", new n(10)), e(this, "resetDecoderState", () => {
|
|
43
|
-
this.pendingSamples.clear(), this.previousSample = void 0, this.previousCodec = void 0;
|
|
44
|
-
}), e(this, "ensureDecoder", () => ((!this.decoder || this.decoder.state === "closed") && (this.decoder = this.createDecoder()), this.decoder)), e(this, "createDecoder", () => new AudioDecoder({
|
|
45
|
-
output: (e) => {
|
|
46
|
-
let t = this.pendingSamples.dequeueWithFallback(e.timestamp);
|
|
47
|
-
if (!t) {
|
|
48
|
-
e.close();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
let { sample: n, decodeStartTime: i } = t;
|
|
52
|
-
try {
|
|
53
|
-
let t = e.numberOfFrames, a = e.numberOfChannels, o = e.sampleRate, s = e.timestamp, c = e.duration, l = new Float32Array(t * a);
|
|
54
|
-
e.copyTo(l, {
|
|
55
|
-
planeIndex: 0,
|
|
56
|
-
format: "f32"
|
|
57
|
-
});
|
|
58
|
-
let u = Math.round(s * n.timescale / 1e6), d = typeof c == "number" && Number.isFinite(c) ? Math.max(0, Math.round(c * n.timescale / 1e6)) : n.duration, f = r(r({}, n), {}, {
|
|
59
|
-
timestamp: u,
|
|
60
|
-
duration: d,
|
|
61
|
-
type: "audio",
|
|
62
|
-
format: "f32",
|
|
63
|
-
data: l,
|
|
64
|
-
sampleRate: o,
|
|
65
|
-
channels: a,
|
|
66
|
-
statistics: {
|
|
67
|
-
decodeTime: Math.max(performance.now() - i, 0),
|
|
68
|
-
transportTimeFromWorker: 0,
|
|
69
|
-
transportTimeToWorker: 0,
|
|
70
|
-
samplesInBatch: 1
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
this.decodedSamples.push(f);
|
|
74
|
-
} finally {
|
|
75
|
-
e.close();
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
error: (e) => {
|
|
79
|
-
this.logger.error("Decoder error:", e.name, e.message), this.resetDecoderState(), this.errors.push(e);
|
|
80
|
-
}
|
|
81
|
-
})), e(this, "buildCodecString", o), e(this, "getDescription", (e, t) => {
|
|
82
|
-
let n = this.initSegments.get(t.renditionId);
|
|
83
|
-
if (n && n.data.byteLength > 0 && n.codec === e) return n.data;
|
|
84
|
-
if (e === "opus") return a(t.channels, t.sampleRate);
|
|
85
|
-
if (e === "aac") return i(t.channels, t.sampleRate);
|
|
86
|
-
}), e(this, "unload", () => {
|
|
87
|
-
this.decodedSamples = [], this.resetDecoderState(), this.decoder && this.decoder.state !== "closed" && this.decoder.close(), this.decoder = null;
|
|
88
|
-
}), e(this, "initSegment", (e) => {
|
|
89
|
-
this.initSegments.set(e.renditionId, e);
|
|
90
|
-
}), e(this, "enqueue", (e) => {
|
|
91
|
-
var t, n;
|
|
92
|
-
let r = this.ensureDecoder(), i = e.codec, a = ((t = this.previousSample) == null ? void 0 : t.channelId) !== e.channelId, o = ((n = this.previousSample) == null ? void 0 : n.renditionId) !== e.renditionId, s = this.previousCodec !== i;
|
|
93
|
-
if (!this.previousSample || a || o || s) {
|
|
94
|
-
this.previousSample && r.state === "configured" && r.flush().catch((e) => {
|
|
95
|
-
this.logger.warn("Failed to flush before reconfiguration:", e);
|
|
96
|
-
});
|
|
97
|
-
let t = this.buildCodecString(i), n = this.getDescription(i, e), a = {
|
|
98
|
-
codec: t,
|
|
99
|
-
sampleRate: e.sampleRate,
|
|
100
|
-
numberOfChannels: e.channels,
|
|
101
|
-
description: n
|
|
102
|
-
};
|
|
103
|
-
try {
|
|
104
|
-
r.configure(a), this.previousCodec = i;
|
|
105
|
-
} catch (t) {
|
|
106
|
-
this.logger.error(`Failed to configure decoder for ${i} (rendition ${e.renditionId}), dropping sample`, t), this.errors.push(t instanceof Error ? t : /* @__PURE__ */ Error(`Failed to configure decoder for ${i}`)), this.resetDecoderState(), this.ensureDecoder();
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (e.timescale <= 0) {
|
|
111
|
-
this.logger.error(`Invalid timescale ${e.timescale} in sample, dropping sample`);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
this.previousSample = e;
|
|
115
|
-
let c = Math.floor(1e6 * e.timestamp / e.timescale), l = Math.floor(1e6 * e.duration / e.timescale);
|
|
116
|
-
try {
|
|
117
|
-
let t = new EncodedAudioChunk({
|
|
118
|
-
type: "key",
|
|
119
|
-
timestamp: c,
|
|
120
|
-
duration: l > 0 ? l : void 0,
|
|
121
|
-
data: e.data
|
|
122
|
-
});
|
|
123
|
-
this.pendingSamples.enqueue(c, {
|
|
124
|
-
sample: e,
|
|
125
|
-
decodeStartTime: performance.now()
|
|
126
|
-
}), r.decode(t);
|
|
127
|
-
} catch (e) {
|
|
128
|
-
this.logger.error("Failed to decode chunk:", e), this.pendingSamples.removeLast(c), r.state === "closed" && (this.resetDecoderState(), this.ensureDecoder());
|
|
129
|
-
}
|
|
130
|
-
}), e(this, "flush", t(function* () {
|
|
131
|
-
if (l.decoder && l.decoder.state === "configured") try {
|
|
132
|
-
yield l.decoder.flush();
|
|
133
|
-
} catch (e) {
|
|
134
|
-
l.logger.error("Failed to flush decoder:", e), l.resetDecoderState();
|
|
135
|
-
}
|
|
136
|
-
})), e(this, "error", () => this.errors.pop()), e(this, "take", () => this.decodedSamples.shift()), this.logger = c, this.decoder = this.createDecoder();
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
c = u, e(u, "isSupported", () => l.AudioDecoder !== void 0), e(u, "create", function() {
|
|
140
|
-
var e = t(function* (e) {
|
|
141
|
-
if (!c.isSupported()) throw Error("WebCodecs AudioDecoder is not supported in this environment");
|
|
142
|
-
return new c(e);
|
|
143
|
-
});
|
|
144
|
-
return function(t) {
|
|
145
|
-
return e.apply(this, arguments);
|
|
146
|
-
};
|
|
147
|
-
}());
|
|
148
|
-
//#endregion
|
|
149
|
-
export { u as WebCodecsAudioDecoderContext };
|