@vindral/web-sdk 4.5.1 → 4.6.0-2-g8124b200
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/BZhOPJKq.js +154 -0
- package/BdMchGeH.js +169 -0
- package/{BdFcdkj1.js → BlnnMVOY.js} +26 -22
- package/{D7vM_Gpt.js → Bmh5ZR37.js} +12 -12
- package/{DeYmk5AL.js → Btob1dQR.js} +1 -1
- package/C6y28igI.js +101 -0
- package/CEhUHEp2.js +123 -0
- package/{ci2nH0xq.js → CQewxOcB.js} +1506 -1465
- package/{BRKrFfT9.js → CXR7H5F_.js} +45 -22
- package/{C2-H3s2r.js → CcCOP7K4.js} +299 -298
- package/{BsJtUY1Z.js → DMGwVGGt.js} +2 -2
- package/{B7hT-BKr.js → DSw1XhvD.js} +1 -6
- package/DugdsSO5.js +7 -0
- package/api-client.js +1 -1
- package/cast-sender.d.ts +50 -3
- package/cast-sender.js +1 -1
- package/core.d.ts +141 -7
- package/core.js +3 -3
- package/legacy.d.ts +151 -7
- package/legacy.es.js +4469 -3649
- package/legacy.umd.js +172 -85
- package/package.json +1 -1
- package/player.d.ts +106 -8
- package/player.js +3 -3
- package/react.d.ts +106 -8
- package/{C3YYzwmQ.js → tY-Iy2bb.js} +3708 -3086
- package/vindral-player-component.js +2 -2
- package/Bt-ONXfO.js +0 -59
- package/C01DcfYu.js +0 -118
- package/Cug44nXk.js +0 -149
- package/FYiEDBC4.js +0 -50
- /package/{Ddby8xU_.js → Ct8GqCxq.js} +0 -0
- /package/{RxoWWyzp.js → DXFoVWQM.js} +0 -0
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
|
|
@@ -253,13 +264,36 @@ interface Options {
|
|
|
253
264
|
*/
|
|
254
265
|
mseOpusEnabled?: boolean;
|
|
255
266
|
/**
|
|
256
|
-
*
|
|
267
|
+
* Keep playback running while the page is in the background. Enabled by default.
|
|
268
|
+
* When disabled, the session disconnects while hidden and reconnects when visible.
|
|
257
269
|
*
|
|
258
|
-
*
|
|
270
|
+
* Browser media policies still apply; iOS Safari pauses hidden video regardless.
|
|
271
|
+
* Call `play()` again from a user gesture or media-control action to resume.
|
|
259
272
|
*
|
|
260
|
-
*
|
|
273
|
+
* When enabled, hidden sessions that are muted outside Picture-in-Picture or browser-paused
|
|
274
|
+
* are disconnected after the inactivity timeout; an explicit `pause()` disconnects at once.
|
|
275
|
+
*/
|
|
276
|
+
backgroundPlayEnabled?: boolean;
|
|
277
|
+
/**
|
|
278
|
+
* @deprecated Use `backgroundPlayEnabled` instead.
|
|
279
|
+
*
|
|
280
|
+
* Legacy alias kept for backwards compatibility.
|
|
261
281
|
*/
|
|
262
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;
|
|
263
297
|
/**
|
|
264
298
|
* Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
|
|
265
299
|
* the viewers bandwidth and thus avoiding buffering events. This also disables the
|
|
@@ -374,6 +408,9 @@ interface Options {
|
|
|
374
408
|
* This enables platform media features such as fullscreen and picture-in-picture
|
|
375
409
|
* for non-MSE playback by routing the canvas output through a `<video>` element.
|
|
376
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
|
+
*
|
|
377
414
|
* Disabled by default.
|
|
378
415
|
*/
|
|
379
416
|
streamToMediaElementEnabled?: boolean;
|
|
@@ -827,6 +864,13 @@ interface JitterModuleStatistics {
|
|
|
827
864
|
audioJitter: JitterStatistics | undefined;
|
|
828
865
|
videoJitter: JitterStatistics | undefined;
|
|
829
866
|
}
|
|
867
|
+
type DecoyState = "detached" | "attached" | "playing" | "blocked";
|
|
868
|
+
interface MediaSessionModuleStatistics {
|
|
869
|
+
mediaSessionSupported: boolean;
|
|
870
|
+
mediaSessionOwner: boolean;
|
|
871
|
+
mediaSessionPlaybackState: MediaSessionPlaybackState;
|
|
872
|
+
decoyState?: DecoyState;
|
|
873
|
+
}
|
|
830
874
|
interface MseModuleStatistics {
|
|
831
875
|
quotaErrorCount: number;
|
|
832
876
|
mediaSourceOpenTime: number;
|
|
@@ -938,8 +982,10 @@ interface SyncModuleStatistics {
|
|
|
938
982
|
interface VideoPlayerStatistics {
|
|
939
983
|
renderedFrameCount: number;
|
|
940
984
|
rendererDroppedFrameCount: number;
|
|
985
|
+
/** The platform's own view of the audio context, which a mute reading cannot tell apart. */
|
|
986
|
+
audioContextState?: AudioContextState | "none";
|
|
941
987
|
}
|
|
942
|
-
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;
|
|
943
989
|
type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAgentInformation"]> & {
|
|
944
990
|
/**
|
|
945
991
|
* Version of the @vindral/web-sdk being used.
|
|
@@ -991,6 +1037,8 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
991
1037
|
streamToMediaElementEnabled?: boolean;
|
|
992
1038
|
/** @deprecated */
|
|
993
1039
|
iosMediaElementEnabled?: boolean;
|
|
1040
|
+
/** Whether the element carrying the audio is paused right now, on the sinks that have one. */
|
|
1041
|
+
mediaElementPaused?: boolean;
|
|
994
1042
|
/**
|
|
995
1043
|
* Average bitrate for the entire session in bits/second.
|
|
996
1044
|
*/
|
|
@@ -1015,8 +1063,10 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
1015
1063
|
declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
1016
1064
|
#private;
|
|
1017
1065
|
private static MAX_POOL_SIZE;
|
|
1018
|
-
private static DISCONNECT_TIMEOUT;
|
|
1019
1066
|
private static REMOVE_CUE_THRESHOLD;
|
|
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;
|
|
1020
1070
|
/**
|
|
1021
1071
|
* Picture in picture
|
|
1022
1072
|
*/
|
|
@@ -1059,6 +1109,10 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1059
1109
|
private offscreenCanvasElement?;
|
|
1060
1110
|
private webCodecsRenditionSupport;
|
|
1061
1111
|
private hasCalledConnect;
|
|
1112
|
+
private hasRequestedAudioSession;
|
|
1113
|
+
private isUserPaused;
|
|
1114
|
+
/** Only the sinks that carry the audio report this, so a paused element here means silence. */
|
|
1115
|
+
private isMediaElementPaused;
|
|
1062
1116
|
private latestEmittedLanguages;
|
|
1063
1117
|
private wakeLock;
|
|
1064
1118
|
private pool;
|
|
@@ -1073,7 +1127,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1073
1127
|
private readonly unextractableSamplesWarned;
|
|
1074
1128
|
private sizes;
|
|
1075
1129
|
private isSuspended;
|
|
1076
|
-
private
|
|
1130
|
+
private inactivityDisconnectInterval;
|
|
1131
|
+
private visiblePauseTimeout;
|
|
1077
1132
|
private offscreenSubtitleInterval?;
|
|
1078
1133
|
constructor(options: Options);
|
|
1079
1134
|
/**
|
|
@@ -1375,6 +1430,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1375
1430
|
private isSupportedVideoCodecProfile;
|
|
1376
1431
|
private supportedAudioCodecs;
|
|
1377
1432
|
private initializeDecodingModule;
|
|
1433
|
+
private capturesCanvasOnWebKit;
|
|
1434
|
+
private connectWebKitVideoOutput;
|
|
1378
1435
|
/**
|
|
1379
1436
|
* Set up a polling interval that forwards subtitle cues to the decoder worker
|
|
1380
1437
|
* when OffscreenCanvas rendering is active. This is needed because the canvas modules'
|
|
@@ -1406,6 +1463,12 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1406
1463
|
* Pauses the stream. Call .play() to resume playback again.
|
|
1407
1464
|
*/
|
|
1408
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;
|
|
1409
1472
|
private registerDebugInstance;
|
|
1410
1473
|
/**
|
|
1411
1474
|
*
|
|
@@ -1436,8 +1499,24 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1436
1499
|
*/
|
|
1437
1500
|
getStatistics: () => Statistics;
|
|
1438
1501
|
private resetModules;
|
|
1502
|
+
private disconnectForInactivePage;
|
|
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;
|
|
1513
|
+
private clearInactivityDisconnect;
|
|
1514
|
+
private isHiddenWithBackgroundPlayback;
|
|
1515
|
+
private isVideoOnScreen;
|
|
1516
|
+
private isHiddenWithBackgroundPlayDisabled;
|
|
1439
1517
|
private suspend;
|
|
1440
1518
|
private unsuspend;
|
|
1519
|
+
private resumeModules;
|
|
1441
1520
|
private getRuntimeInfo;
|
|
1442
1521
|
private getPlaybackBufferState;
|
|
1443
1522
|
private onMediaElementBufferState;
|
|
@@ -1451,6 +1530,20 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1451
1530
|
private get targetSubscription();
|
|
1452
1531
|
private timeToFirstFrame;
|
|
1453
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;
|
|
1454
1547
|
private willUseMediaSource;
|
|
1455
1548
|
private shouldUseWebCodecs;
|
|
1456
1549
|
private isWebCodecsVideoAvailable;
|
|
@@ -1461,6 +1554,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1461
1554
|
* is the optimal rendering path for WebCodecs (worker renders VideoFrames directly).
|
|
1462
1555
|
*/
|
|
1463
1556
|
private shouldUseOffscreenCanvas;
|
|
1557
|
+
private isBackgroundPlayEnabled;
|
|
1558
|
+
private shouldAllowBackgroundPlayback;
|
|
1464
1559
|
}
|
|
1465
1560
|
interface TelemetryModuleStatistics {
|
|
1466
1561
|
/**
|
|
@@ -1613,7 +1708,8 @@ interface PublicVindralEvents {
|
|
|
1613
1708
|
* Is emitted during connection whether the channel is live or not.
|
|
1614
1709
|
*
|
|
1615
1710
|
* If the channel is not live, the Vindral instance will try to reconnect until the `reconnectHandler`
|
|
1616
|
-
* determines that no more retries should be made.
|
|
1711
|
+
* determines that no more retries should be made. Each attempt also emits a non-fatal `error` with
|
|
1712
|
+
* the code `channel_not_live`.
|
|
1617
1713
|
*
|
|
1618
1714
|
* Note: If the web-sdk is instantiated at the same time as you are starting the stream it is possible
|
|
1619
1715
|
* that this emits false until the started state has propagated through the system.
|
|
@@ -1916,7 +2012,9 @@ export declare class Controller extends HTMLElement {
|
|
|
1916
2012
|
"burst-enabled",
|
|
1917
2013
|
"mse-enabled",
|
|
1918
2014
|
"mse-opus-enabled",
|
|
2015
|
+
"background-play-enabled",
|
|
1919
2016
|
"ios-background-play-enabled",
|
|
2017
|
+
"media-session-enabled",
|
|
1920
2018
|
"ios-wake-lock-enabled",
|
|
1921
2019
|
"stream-to-media-element-enabled",
|
|
1922
2020
|
"ios-media-element-enabled",
|
|
@@ -2033,7 +2131,7 @@ export declare class PlayButton extends VindralButton {
|
|
|
2033
2131
|
*/
|
|
2034
2132
|
export declare class Player extends HTMLElement {
|
|
2035
2133
|
#private;
|
|
2036
|
-
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" | "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")[];
|
|
2037
2135
|
constructor();
|
|
2038
2136
|
connectedCallback(): void;
|
|
2039
2137
|
disconnectedCallback(): void;
|
package/player.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./
|
|
2
|
-
import "./
|
|
3
|
-
import { t } from "./
|
|
1
|
+
import { t as e } from "./CcCOP7K4.js";
|
|
2
|
+
import "./tY-Iy2bb.js";
|
|
3
|
+
import { t } from "./CQewxOcB.js";
|
|
4
4
|
export { t as registerComponents, e as registerDebugComponents };
|
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
|
|
@@ -255,13 +266,36 @@ interface Options {
|
|
|
255
266
|
*/
|
|
256
267
|
mseOpusEnabled?: boolean;
|
|
257
268
|
/**
|
|
258
|
-
*
|
|
269
|
+
* Keep playback running while the page is in the background. Enabled by default.
|
|
270
|
+
* When disabled, the session disconnects while hidden and reconnects when visible.
|
|
259
271
|
*
|
|
260
|
-
*
|
|
272
|
+
* Browser media policies still apply; iOS Safari pauses hidden video regardless.
|
|
273
|
+
* Call `play()` again from a user gesture or media-control action to resume.
|
|
261
274
|
*
|
|
262
|
-
*
|
|
275
|
+
* When enabled, hidden sessions that are muted outside Picture-in-Picture or browser-paused
|
|
276
|
+
* are disconnected after the inactivity timeout; an explicit `pause()` disconnects at once.
|
|
277
|
+
*/
|
|
278
|
+
backgroundPlayEnabled?: boolean;
|
|
279
|
+
/**
|
|
280
|
+
* @deprecated Use `backgroundPlayEnabled` instead.
|
|
281
|
+
*
|
|
282
|
+
* Legacy alias kept for backwards compatibility.
|
|
263
283
|
*/
|
|
264
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;
|
|
265
299
|
/**
|
|
266
300
|
* Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
|
|
267
301
|
* the viewers bandwidth and thus avoiding buffering events. This also disables the
|
|
@@ -376,6 +410,9 @@ interface Options {
|
|
|
376
410
|
* This enables platform media features such as fullscreen and picture-in-picture
|
|
377
411
|
* for non-MSE playback by routing the canvas output through a `<video>` element.
|
|
378
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
|
+
*
|
|
379
416
|
* Disabled by default.
|
|
380
417
|
*/
|
|
381
418
|
streamToMediaElementEnabled?: boolean;
|
|
@@ -829,6 +866,13 @@ interface JitterModuleStatistics {
|
|
|
829
866
|
audioJitter: JitterStatistics | undefined;
|
|
830
867
|
videoJitter: JitterStatistics | undefined;
|
|
831
868
|
}
|
|
869
|
+
type DecoyState = "detached" | "attached" | "playing" | "blocked";
|
|
870
|
+
interface MediaSessionModuleStatistics {
|
|
871
|
+
mediaSessionSupported: boolean;
|
|
872
|
+
mediaSessionOwner: boolean;
|
|
873
|
+
mediaSessionPlaybackState: MediaSessionPlaybackState;
|
|
874
|
+
decoyState?: DecoyState;
|
|
875
|
+
}
|
|
832
876
|
interface MseModuleStatistics {
|
|
833
877
|
quotaErrorCount: number;
|
|
834
878
|
mediaSourceOpenTime: number;
|
|
@@ -940,8 +984,10 @@ interface SyncModuleStatistics {
|
|
|
940
984
|
interface VideoPlayerStatistics {
|
|
941
985
|
renderedFrameCount: number;
|
|
942
986
|
rendererDroppedFrameCount: number;
|
|
987
|
+
/** The platform's own view of the audio context, which a mute reading cannot tell apart. */
|
|
988
|
+
audioContextState?: AudioContextState | "none";
|
|
943
989
|
}
|
|
944
|
-
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;
|
|
945
991
|
type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAgentInformation"]> & {
|
|
946
992
|
/**
|
|
947
993
|
* Version of the @vindral/web-sdk being used.
|
|
@@ -993,6 +1039,8 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
993
1039
|
streamToMediaElementEnabled?: boolean;
|
|
994
1040
|
/** @deprecated */
|
|
995
1041
|
iosMediaElementEnabled?: boolean;
|
|
1042
|
+
/** Whether the element carrying the audio is paused right now, on the sinks that have one. */
|
|
1043
|
+
mediaElementPaused?: boolean;
|
|
996
1044
|
/**
|
|
997
1045
|
* Average bitrate for the entire session in bits/second.
|
|
998
1046
|
*/
|
|
@@ -1017,8 +1065,10 @@ type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["getUserAge
|
|
|
1017
1065
|
declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
1018
1066
|
#private;
|
|
1019
1067
|
private static MAX_POOL_SIZE;
|
|
1020
|
-
private static DISCONNECT_TIMEOUT;
|
|
1021
1068
|
private static REMOVE_CUE_THRESHOLD;
|
|
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;
|
|
1022
1072
|
/**
|
|
1023
1073
|
* Picture in picture
|
|
1024
1074
|
*/
|
|
@@ -1061,6 +1111,10 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1061
1111
|
private offscreenCanvasElement?;
|
|
1062
1112
|
private webCodecsRenditionSupport;
|
|
1063
1113
|
private hasCalledConnect;
|
|
1114
|
+
private hasRequestedAudioSession;
|
|
1115
|
+
private isUserPaused;
|
|
1116
|
+
/** Only the sinks that carry the audio report this, so a paused element here means silence. */
|
|
1117
|
+
private isMediaElementPaused;
|
|
1064
1118
|
private latestEmittedLanguages;
|
|
1065
1119
|
private wakeLock;
|
|
1066
1120
|
private pool;
|
|
@@ -1075,7 +1129,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1075
1129
|
private readonly unextractableSamplesWarned;
|
|
1076
1130
|
private sizes;
|
|
1077
1131
|
private isSuspended;
|
|
1078
|
-
private
|
|
1132
|
+
private inactivityDisconnectInterval;
|
|
1133
|
+
private visiblePauseTimeout;
|
|
1079
1134
|
private offscreenSubtitleInterval?;
|
|
1080
1135
|
constructor(options: Options);
|
|
1081
1136
|
/**
|
|
@@ -1377,6 +1432,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1377
1432
|
private isSupportedVideoCodecProfile;
|
|
1378
1433
|
private supportedAudioCodecs;
|
|
1379
1434
|
private initializeDecodingModule;
|
|
1435
|
+
private capturesCanvasOnWebKit;
|
|
1436
|
+
private connectWebKitVideoOutput;
|
|
1380
1437
|
/**
|
|
1381
1438
|
* Set up a polling interval that forwards subtitle cues to the decoder worker
|
|
1382
1439
|
* when OffscreenCanvas rendering is active. This is needed because the canvas modules'
|
|
@@ -1408,6 +1465,12 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1408
1465
|
* Pauses the stream. Call .play() to resume playback again.
|
|
1409
1466
|
*/
|
|
1410
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;
|
|
1411
1474
|
private registerDebugInstance;
|
|
1412
1475
|
/**
|
|
1413
1476
|
*
|
|
@@ -1438,8 +1501,24 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1438
1501
|
*/
|
|
1439
1502
|
getStatistics: () => Statistics;
|
|
1440
1503
|
private resetModules;
|
|
1504
|
+
private disconnectForInactivePage;
|
|
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;
|
|
1515
|
+
private clearInactivityDisconnect;
|
|
1516
|
+
private isHiddenWithBackgroundPlayback;
|
|
1517
|
+
private isVideoOnScreen;
|
|
1518
|
+
private isHiddenWithBackgroundPlayDisabled;
|
|
1441
1519
|
private suspend;
|
|
1442
1520
|
private unsuspend;
|
|
1521
|
+
private resumeModules;
|
|
1443
1522
|
private getRuntimeInfo;
|
|
1444
1523
|
private getPlaybackBufferState;
|
|
1445
1524
|
private onMediaElementBufferState;
|
|
@@ -1453,6 +1532,20 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1453
1532
|
private get targetSubscription();
|
|
1454
1533
|
private timeToFirstFrame;
|
|
1455
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;
|
|
1456
1549
|
private willUseMediaSource;
|
|
1457
1550
|
private shouldUseWebCodecs;
|
|
1458
1551
|
private isWebCodecsVideoAvailable;
|
|
@@ -1463,6 +1556,8 @@ declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
1463
1556
|
* is the optimal rendering path for WebCodecs (worker renders VideoFrames directly).
|
|
1464
1557
|
*/
|
|
1465
1558
|
private shouldUseOffscreenCanvas;
|
|
1559
|
+
private isBackgroundPlayEnabled;
|
|
1560
|
+
private shouldAllowBackgroundPlayback;
|
|
1466
1561
|
}
|
|
1467
1562
|
interface TelemetryModuleStatistics {
|
|
1468
1563
|
/**
|
|
@@ -1615,7 +1710,8 @@ interface PublicVindralEvents {
|
|
|
1615
1710
|
* Is emitted during connection whether the channel is live or not.
|
|
1616
1711
|
*
|
|
1617
1712
|
* If the channel is not live, the Vindral instance will try to reconnect until the `reconnectHandler`
|
|
1618
|
-
* determines that no more retries should be made.
|
|
1713
|
+
* determines that no more retries should be made. Each attempt also emits a non-fatal `error` with
|
|
1714
|
+
* the code `channel_not_live`.
|
|
1619
1715
|
*
|
|
1620
1716
|
* Note: If the web-sdk is instantiated at the same time as you are starting the stream it is possible
|
|
1621
1717
|
* that this emits false until the started state has propagated through the system.
|
|
@@ -1925,7 +2021,9 @@ declare class Controller extends HTMLElement {
|
|
|
1925
2021
|
"burst-enabled",
|
|
1926
2022
|
"mse-enabled",
|
|
1927
2023
|
"mse-opus-enabled",
|
|
2024
|
+
"background-play-enabled",
|
|
1928
2025
|
"ios-background-play-enabled",
|
|
2026
|
+
"media-session-enabled",
|
|
1929
2027
|
"ios-wake-lock-enabled",
|
|
1930
2028
|
"stream-to-media-element-enabled",
|
|
1931
2029
|
"ios-media-element-enabled",
|
|
@@ -2043,7 +2141,7 @@ declare class PlayButton extends VindralButton {
|
|
|
2043
2141
|
type PlayerAttributes = (typeof Player.observedAttributes)[number];
|
|
2044
2142
|
declare class Player extends HTMLElement {
|
|
2045
2143
|
#private;
|
|
2046
|
-
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" | "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")[];
|
|
2047
2145
|
constructor();
|
|
2048
2146
|
connectedCallback(): void;
|
|
2049
2147
|
disconnectedCallback(): void;
|