@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.
@@ -1,7 +1,7 @@
1
1
  import { n as e, t } from "./BsfwXDui.js";
2
- import { M as n, v as r } from "./C01DcfYu.js";
2
+ import { F as n, x as r } from "./CEhUHEp2.js";
3
3
  import { t as i } from "./DrWNJwZx.js";
4
- import { t as a } from "./RxoWWyzp.js";
4
+ import { t as a } from "./DXFoVWQM.js";
5
5
  //#region ../../libs/wasm-decoders/src/opus/wasm/opus.js
6
6
  var o = (function() {
7
7
  var e = typeof document < "u" && document.currentScript ? document.currentScript.src : void 0;
@@ -24,9 +24,4 @@ function i(e, t) {
24
24
  return e.get(n(e, t));
25
25
  }
26
26
  //#endregion
27
- //#region \0@oxc-project+runtime@0.115.0/helpers/classPrivateMethodInitSpec.js
28
- function a(t, n) {
29
- e(t, n), n.add(t);
30
- }
31
- //#endregion
32
- export { t as a, n as i, i as n, r, a as t };
27
+ export { e as a, t as i, r as n, n as r, i as t };
package/DugdsSO5.js ADDED
@@ -0,0 +1,7 @@
1
+ import { a as e } from "./DSw1XhvD.js";
2
+ //#region \0@oxc-project+runtime@0.115.0/helpers/classPrivateMethodInitSpec.js
3
+ function t(t, n) {
4
+ e(t, n), n.add(t);
5
+ }
6
+ //#endregion
7
+ export { t };
package/api-client.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as e } from "./DeYmk5AL.js";
1
+ import { t as e } from "./Btob1dQR.js";
2
2
  export { e as ApiClient };
package/cast-sender.d.ts CHANGED
@@ -98,6 +98,17 @@ interface DrmOptions {
98
98
  type Media = "audio" | "video" | "audio+video";
99
99
  type WebCodecsHardwareAccelerationPreference = "no-preference" | "prefer-hardware" | "prefer-software";
100
100
  type DecoderType = "mse" | "webcodecs" | "wasm";
101
+ interface MediaSessionMetadata {
102
+ title?: string;
103
+ artist?: string;
104
+ album?: string;
105
+ /** Fetched by the operating system, so the URLs should not carry credentials. */
106
+ artwork?: Array<{
107
+ src: string;
108
+ sizes?: string;
109
+ type?: string;
110
+ }>;
111
+ }
101
112
  interface Options {
102
113
  /**
103
114
  * URL to use when connecting to the stream
@@ -177,13 +188,36 @@ interface Options {
177
188
  */
178
189
  mseOpusEnabled?: boolean;
179
190
  /**
180
- * Enable or disable support for playing audio in the background for iOS devices.
191
+ * Keep playback running while the page is in the background. Enabled by default.
192
+ * When disabled, the session disconnects while hidden and reconnects when visible.
181
193
  *
182
- * Is false (disabled) by default.
194
+ * Browser media policies still apply; iOS Safari pauses hidden video regardless.
195
+ * Call `play()` again from a user gesture or media-control action to resume.
183
196
  *
184
- * Note: This may be enabled by default in a future (major) release
197
+ * When enabled, hidden sessions that are muted outside Picture-in-Picture or browser-paused
198
+ * are disconnected after the inactivity timeout; an explicit `pause()` disconnects at once.
199
+ */
200
+ backgroundPlayEnabled?: boolean;
201
+ /**
202
+ * @deprecated Use `backgroundPlayEnabled` instead.
203
+ *
204
+ * Legacy alias kept for backwards compatibility.
185
205
  */
186
206
  iosBackgroundPlayEnabled?: boolean;
207
+ /**
208
+ * Show the stream in the browser and OS media controls (notification, lock screen, toolbar) and
209
+ * let play and pause from there reach the SDK. Enabled by default.
210
+ *
211
+ * The SDK takes over `navigator.mediaSession` for the document, so a page with its own Media
212
+ * Session integration should disable this. On canvas playback paths a silent `<audio>` element is
213
+ * added to `document.body` for the controls to attach to.
214
+ */
215
+ mediaSessionEnabled?: boolean;
216
+ /**
217
+ * Title, artist and artwork for the media controls. Without it the browser derives them from the
218
+ * page. Read once at construction.
219
+ */
220
+ mediaSessionMetadata?: MediaSessionMetadata;
187
221
  /**
188
222
  * Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
189
223
  * the viewers bandwidth and thus avoiding buffering events. This also disables the
@@ -298,6 +332,9 @@ interface Options {
298
332
  * This enables platform media features such as fullscreen and picture-in-picture
299
333
  * for non-MSE playback by routing the canvas output through a `<video>` element.
300
334
  *
335
+ * On iOS the audio then plays from its own element, so it continues in the background and under
336
+ * lock. After an extended pause from the lock screen, reopening Safari may be required to resume.
337
+ *
301
338
  * Disabled by default.
302
339
  */
303
340
  streamToMediaElementEnabled?: boolean;
@@ -386,6 +423,10 @@ export interface CastSenderEvents {
386
423
  * When the remote connection receives a server wallclock time event
387
424
  */
388
425
  "server wallclock time": number;
426
+ /**
427
+ * When receiver availability changes. True when at least one receiver is reachable.
428
+ */
429
+ "devices available": boolean;
389
430
  }
390
431
  /**
391
432
  * Used for initializing the CastSender
@@ -412,6 +453,9 @@ export declare class CastSender extends Emitter<CastSenderEvents> {
412
453
  private state;
413
454
  private config;
414
455
  private unloaded;
456
+ private logger;
457
+ /** Last reported availability, undefined until the Cast API tells us */
458
+ private devicesAvailable;
415
459
  constructor(config: CastConfig);
416
460
  /**
417
461
  * True if the instance is casting right now
@@ -471,6 +515,9 @@ export declare class CastSender extends Emitter<CastSenderEvents> {
471
515
  private send;
472
516
  private onMessage;
473
517
  private onSessionStarted;
518
+ private onCastStateChanged;
519
+ /** Emits on change only, since connecting and connected are all "available" */
520
+ private updateDevicesAvailable;
474
521
  private onSessionStateChanged;
475
522
  private getInstance;
476
523
  private getSession;
package/cast-sender.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as e } from "./BdFcdkj1.js";
1
+ import { t as e } from "./BlnnMVOY.js";
2
2
  export { e as CastSender };
package/core.d.ts CHANGED
@@ -189,6 +189,18 @@ export interface DrmOptions {
189
189
  export type Media = "audio" | "video" | "audio+video";
190
190
  type WebCodecsHardwareAccelerationPreference = "no-preference" | "prefer-hardware" | "prefer-software";
191
191
  type DecoderType = "mse" | "webcodecs" | "wasm";
192
+ /** What the OS media controls show for the stream. Mirrors the `MediaMetadata` fields. */
193
+ export interface MediaSessionMetadata {
194
+ title?: string;
195
+ artist?: string;
196
+ album?: string;
197
+ /** Fetched by the operating system, so the URLs should not carry credentials. */
198
+ artwork?: Array<{
199
+ src: string;
200
+ sizes?: string;
201
+ type?: string;
202
+ }>;
203
+ }
192
204
  /**
193
205
  * Options for the Vindral instance
194
206
  *
@@ -272,13 +284,36 @@ export interface Options {
272
284
  */
273
285
  mseOpusEnabled?: boolean;
274
286
  /**
275
- * Enable or disable support for playing audio in the background for iOS devices.
287
+ * Keep playback running while the page is in the background. Enabled by default.
288
+ * When disabled, the session disconnects while hidden and reconnects when visible.
289
+ *
290
+ * Browser media policies still apply; iOS Safari pauses hidden video regardless.
291
+ * Call `play()` again from a user gesture or media-control action to resume.
276
292
  *
277
- * Is false (disabled) by default.
293
+ * When enabled, hidden sessions that are muted outside Picture-in-Picture or browser-paused
294
+ * are disconnected after the inactivity timeout; an explicit `pause()` disconnects at once.
295
+ */
296
+ backgroundPlayEnabled?: boolean;
297
+ /**
298
+ * @deprecated Use `backgroundPlayEnabled` instead.
278
299
  *
279
- * Note: This may be enabled by default in a future (major) release
300
+ * Legacy alias kept for backwards compatibility.
280
301
  */
281
302
  iosBackgroundPlayEnabled?: boolean;
303
+ /**
304
+ * Show the stream in the browser and OS media controls (notification, lock screen, toolbar) and
305
+ * let play and pause from there reach the SDK. Enabled by default.
306
+ *
307
+ * The SDK takes over `navigator.mediaSession` for the document, so a page with its own Media
308
+ * Session integration should disable this. On canvas playback paths a silent `<audio>` element is
309
+ * added to `document.body` for the controls to attach to.
310
+ */
311
+ mediaSessionEnabled?: boolean;
312
+ /**
313
+ * Title, artist and artwork for the media controls. Without it the browser derives them from the
314
+ * page. Read once at construction.
315
+ */
316
+ mediaSessionMetadata?: MediaSessionMetadata;
282
317
  /**
283
318
  * Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
284
319
  * the viewers bandwidth and thus avoiding buffering events. This also disables the
@@ -393,6 +428,9 @@ export interface Options {
393
428
  * This enables platform media features such as fullscreen and picture-in-picture
394
429
  * for non-MSE playback by routing the canvas output through a `<video>` element.
395
430
  *
431
+ * On iOS the audio then plays from its own element, so it continues in the background and under
432
+ * lock. After an extended pause from the lock screen, reopening Safari may be required to resume.
433
+ *
396
434
  * Disabled by default.
397
435
  */
398
436
  streamToMediaElementEnabled?: boolean;
@@ -653,6 +691,7 @@ export declare const CONNECTION_FAILED_AFTER_RETRIES_CODE = "connection_failed_w
653
691
  export declare const AUTHENTICATION_FAILED_CODE = "authentication_error";
654
692
  export declare const AUTHENTICATION_EXPIRED_CODE = "authentication_expired";
655
693
  export declare const CHANNEL_NOT_FOUND_CODE = "channel_not_found";
694
+ export declare const CHANNEL_NOT_LIVE_CODE = "channel_not_live";
656
695
  export declare const NO_INCOMING_DATA = "no_incoming_data_error";
657
696
  export declare const INACTIVITY_CODE = "connection_inactivity";
658
697
  export declare const DISCONNECTED_BY_EDGE = "disconnected_by_edge";
@@ -903,6 +942,13 @@ interface JitterModuleStatistics {
903
942
  audioJitter: JitterStatistics | undefined;
904
943
  videoJitter: JitterStatistics | undefined;
905
944
  }
945
+ type DecoyState = "detached" | "attached" | "playing" | "blocked";
946
+ interface MediaSessionModuleStatistics {
947
+ mediaSessionSupported: boolean;
948
+ mediaSessionOwner: boolean;
949
+ mediaSessionPlaybackState: MediaSessionPlaybackState;
950
+ decoyState?: DecoyState;
951
+ }
906
952
  interface MseModuleStatistics {
907
953
  quotaErrorCount: number;
908
954
  mediaSourceOpenTime: number;
@@ -1014,8 +1060,10 @@ interface SyncModuleStatistics {
1014
1060
  interface VideoPlayerStatistics {
1015
1061
  renderedFrameCount: number;
1016
1062
  rendererDroppedFrameCount: number;
1063
+ /** The platform's own view of the audio context, which a mute reading cannot tell apart. */
1064
+ audioContextState?: AudioContextState | "none";
1017
1065
  }
1018
- type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
1066
+ type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & Partial<MediaSessionModuleStatistics> & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
1019
1067
  /**
1020
1068
  * Contains internal statistics.
1021
1069
  *
@@ -1075,6 +1123,8 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1075
1123
  streamToMediaElementEnabled?: boolean;
1076
1124
  /** @deprecated */
1077
1125
  iosMediaElementEnabled?: boolean;
1126
+ /** Whether the element carrying the audio is paused right now, on the sinks that have one. */
1127
+ mediaElementPaused?: boolean;
1078
1128
  /**
1079
1129
  * Average bitrate for the entire session in bits/second.
1080
1130
  */
@@ -1096,11 +1146,49 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1096
1146
  */
1097
1147
  timeshiftAdjustmentsPerMinute: number;
1098
1148
  };
1149
+ /**
1150
+ * Represents a Vindral client instance
1151
+ *
1152
+ * The most most essential methods when using the Vindral class are:
1153
+ *
1154
+ * - connect() - this has to be called to actually start connecting
1155
+ * - attach() - to attach the Vindral video view to the DOM so that users can see it
1156
+ * - userInput() - to activate audio on browsers that require a user gesture to play audio
1157
+ * - unload() - unloads the instance, its very important that this is called when cleaning up the Vindral instance, otherwise background timers may leak.
1158
+ *
1159
+ * The Vindral instance will emit a variety of events during its lifetime. Use .on("event-name", callback) to listen to these events.
1160
+ * See [[PublicVindralEvents]] for the events types that can be emitted.
1161
+ *
1162
+ * ```typescript
1163
+ * // minimal configuration of a Vindral client instance
1164
+ * const instance = new Vindral({
1165
+ * url: "https://lb.cdn.vindral.com",
1166
+ * channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
1167
+ * })
1168
+ *
1169
+ * // Will be called when timed metadata is received
1170
+ * instance.on("metadata", console.log)
1171
+ *
1172
+ * // Will be called when a user interaction is needed to activate audio
1173
+ * instance.on("needs user input", console.log)
1174
+ *
1175
+ * // Start connecting to the cdn
1176
+ * instance.connect()
1177
+ *
1178
+ * // Attach the video view to the DOM
1179
+ * instance.attach(document.getElementById("root"))
1180
+ *
1181
+ * // When done with the instance
1182
+ * instance.unload()
1183
+ * ```
1184
+ */
1099
1185
  export declare class Vindral extends Emitter<PublicVindralEvents> {
1100
1186
  #private;
1101
1187
  private static MAX_POOL_SIZE;
1102
- private static DISCONNECT_TIMEOUT;
1103
1188
  private static REMOVE_CUE_THRESHOLD;
1189
+ private static BACKGROUND_INACTIVITY_DISCONNECT_TIMEOUT;
1190
+ /** How long a pause on a visible page may still turn out to be the platform backgrounding us. */
1191
+ private static VISIBLE_PAUSE_DISCONNECT_DELAY;
1104
1192
  /**
1105
1193
  * Picture in picture
1106
1194
  */
@@ -1143,6 +1231,10 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1143
1231
  private offscreenCanvasElement?;
1144
1232
  private webCodecsRenditionSupport;
1145
1233
  private hasCalledConnect;
1234
+ private hasRequestedAudioSession;
1235
+ private isUserPaused;
1236
+ /** Only the sinks that carry the audio report this, so a paused element here means silence. */
1237
+ private isMediaElementPaused;
1146
1238
  private latestEmittedLanguages;
1147
1239
  private wakeLock;
1148
1240
  private pool;
@@ -1157,7 +1249,8 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1157
1249
  private readonly unextractableSamplesWarned;
1158
1250
  private sizes;
1159
1251
  private isSuspended;
1160
- private disconnectTimeout;
1252
+ private inactivityDisconnectInterval;
1253
+ private visiblePauseTimeout;
1161
1254
  private offscreenSubtitleInterval?;
1162
1255
  constructor(options: Options);
1163
1256
  /**
@@ -1459,6 +1552,8 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1459
1552
  private isSupportedVideoCodecProfile;
1460
1553
  private supportedAudioCodecs;
1461
1554
  private initializeDecodingModule;
1555
+ private capturesCanvasOnWebKit;
1556
+ private connectWebKitVideoOutput;
1462
1557
  /**
1463
1558
  * Set up a polling interval that forwards subtitle cues to the decoder worker
1464
1559
  * when OffscreenCanvas rendering is active. This is needed because the canvas modules'
@@ -1490,6 +1585,12 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1490
1585
  * Pauses the stream. Call .play() to resume playback again.
1491
1586
  */
1492
1587
  pause: () => void;
1588
+ /**
1589
+ * A browser-initiated decoy pause means an interruption (another app took the focus, headphones
1590
+ * unplugged), so give the audio up rather than play over it. WebKit holds the decoy on purpose.
1591
+ */
1592
+ private yieldToInterruption;
1593
+ private fromNativeControls;
1493
1594
  private registerDebugInstance;
1494
1595
  /**
1495
1596
  *
@@ -1520,8 +1621,24 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1520
1621
  */
1521
1622
  getStatistics: () => Statistics;
1522
1623
  private resetModules;
1624
+ private disconnectForInactivePage;
1625
+ private scheduleInactivityDisconnect;
1626
+ /**
1627
+ * iOS pauses the element a moment before it hides the page, and that pause reaches us while the
1628
+ * page still reports visible. Acting on it at once tears the session down, so every app switch
1629
+ * comes back as a full reconnect. Wait for the hide that follows a platform pause instead.
1630
+ * Nowhere else pauses before hiding, so there a visible pause is the viewer's at once.
1631
+ */
1632
+ private onVisiblePause;
1633
+ private disconnectForVisiblePause;
1634
+ private clearVisiblePauseDisconnect;
1635
+ private clearInactivityDisconnect;
1636
+ private isHiddenWithBackgroundPlayback;
1637
+ private isVideoOnScreen;
1638
+ private isHiddenWithBackgroundPlayDisabled;
1523
1639
  private suspend;
1524
1640
  private unsuspend;
1641
+ private resumeModules;
1525
1642
  private getRuntimeInfo;
1526
1643
  private getPlaybackBufferState;
1527
1644
  private onMediaElementBufferState;
@@ -1535,6 +1652,20 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1535
1652
  private get targetSubscription();
1536
1653
  private timeToFirstFrame;
1537
1654
  private resolvedDecoder;
1655
+ /**
1656
+ * On mobile Chromium with WebCodecs audio the play action arrives but no sound comes back until
1657
+ * the page is visible, so a hidden pause is a stop there. Reads the decoder in use.
1658
+ */
1659
+ private hiddenPauseIsStop;
1660
+ private usesSplitCanvasAudio;
1661
+ private isWebKitCanvasPath;
1662
+ private holdsDecoyWhilePaused;
1663
+ private streamsToMediaElement;
1664
+ /**
1665
+ * Safari 16.4+: a playback audio session keeps Web Audio alive in the background. Document-wide
1666
+ * and not restorable, so it waits for playback to be wanted rather than for construction.
1667
+ */
1668
+ private requestAudioSessionOnce;
1538
1669
  private willUseMediaSource;
1539
1670
  private shouldUseWebCodecs;
1540
1671
  private isWebCodecsVideoAvailable;
@@ -1545,6 +1676,8 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1545
1676
  * is the optimal rendering path for WebCodecs (worker renders VideoFrames directly).
1546
1677
  */
1547
1678
  private shouldUseOffscreenCanvas;
1679
+ private isBackgroundPlayEnabled;
1680
+ private shouldAllowBackgroundPlayback;
1548
1681
  }
1549
1682
  interface TelemetryModuleStatistics {
1550
1683
  /**
@@ -1716,7 +1849,8 @@ export interface PublicVindralEvents {
1716
1849
  * Is emitted during connection whether the channel is live or not.
1717
1850
  *
1718
1851
  * If the channel is not live, the Vindral instance will try to reconnect until the `reconnectHandler`
1719
- * determines that no more retries should be made.
1852
+ * determines that no more retries should be made. Each attempt also emits a non-fatal `error` with
1853
+ * the code `channel_not_live`.
1720
1854
  *
1721
1855
  * Note: If the web-sdk is instantiated at the same time as you are starting the stream it is possible
1722
1856
  * that this emits false until the started state has propagated through the system.
package/core.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as e } from "./C3YYzwmQ.js";
2
- import { a as t, c as n, i as r, l as i, n as a, o, r as s, s as c, u as l } from "./C01DcfYu.js";
3
- export { a as AUTHENTICATION_EXPIRED_CODE, s as AUTHENTICATION_FAILED_CODE, r as CHANNEL_NOT_FOUND_CODE, t as CONNECTION_FAILED_AFTER_RETRIES_CODE, o as CONNECTION_FAILED_CODE, c as DISCONNECTED_BY_EDGE, n as INACTIVITY_CODE, i as NO_INCOMING_DATA, e as Vindral, l as VindralError };
1
+ import { t as e } from "./tY-Iy2bb.js";
2
+ import { a as t, c as n, d as r, f as i, i as a, l as o, n as s, o as c, r as l, s as u } from "./CEhUHEp2.js";
3
+ export { s as AUTHENTICATION_EXPIRED_CODE, l as AUTHENTICATION_FAILED_CODE, a as CHANNEL_NOT_FOUND_CODE, t as CHANNEL_NOT_LIVE_CODE, c as CONNECTION_FAILED_AFTER_RETRIES_CODE, u as CONNECTION_FAILED_CODE, n as DISCONNECTED_BY_EDGE, o as INACTIVITY_CODE, r as NO_INCOMING_DATA, e as Vindral, i as VindralError };