@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/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
@@ -193,6 +204,20 @@ interface Options {
193
204
  * Legacy alias kept for backwards compatibility.
194
205
  */
195
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;
196
221
  /**
197
222
  * Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
198
223
  * the viewers bandwidth and thus avoiding buffering events. This also disables the
@@ -307,6 +332,9 @@ interface Options {
307
332
  * This enables platform media features such as fullscreen and picture-in-picture
308
333
  * for non-MSE playback by routing the canvas output through a `<video>` element.
309
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
+ *
310
338
  * Disabled by default.
311
339
  */
312
340
  streamToMediaElementEnabled?: boolean;
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
  *
@@ -288,6 +300,20 @@ export interface Options {
288
300
  * Legacy alias kept for backwards compatibility.
289
301
  */
290
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;
291
317
  /**
292
318
  * Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
293
319
  * the viewers bandwidth and thus avoiding buffering events. This also disables the
@@ -402,6 +428,9 @@ export interface Options {
402
428
  * This enables platform media features such as fullscreen and picture-in-picture
403
429
  * for non-MSE playback by routing the canvas output through a `<video>` element.
404
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
+ *
405
434
  * Disabled by default.
406
435
  */
407
436
  streamToMediaElementEnabled?: boolean;
@@ -913,6 +942,13 @@ interface JitterModuleStatistics {
913
942
  audioJitter: JitterStatistics | undefined;
914
943
  videoJitter: JitterStatistics | undefined;
915
944
  }
945
+ type DecoyState = "detached" | "attached" | "playing" | "blocked";
946
+ interface MediaSessionModuleStatistics {
947
+ mediaSessionSupported: boolean;
948
+ mediaSessionOwner: boolean;
949
+ mediaSessionPlaybackState: MediaSessionPlaybackState;
950
+ decoyState?: DecoyState;
951
+ }
916
952
  interface MseModuleStatistics {
917
953
  quotaErrorCount: number;
918
954
  mediaSourceOpenTime: number;
@@ -1024,8 +1060,10 @@ interface SyncModuleStatistics {
1024
1060
  interface VideoPlayerStatistics {
1025
1061
  renderedFrameCount: number;
1026
1062
  rendererDroppedFrameCount: number;
1063
+ /** The platform's own view of the audio context, which a mute reading cannot tell apart. */
1064
+ audioContextState?: AudioContextState | "none";
1027
1065
  }
1028
- 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;
1029
1067
  /**
1030
1068
  * Contains internal statistics.
1031
1069
  *
@@ -1085,6 +1123,8 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1085
1123
  streamToMediaElementEnabled?: boolean;
1086
1124
  /** @deprecated */
1087
1125
  iosMediaElementEnabled?: boolean;
1126
+ /** Whether the element carrying the audio is paused right now, on the sinks that have one. */
1127
+ mediaElementPaused?: boolean;
1088
1128
  /**
1089
1129
  * Average bitrate for the entire session in bits/second.
1090
1130
  */
@@ -1106,11 +1146,49 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1106
1146
  */
1107
1147
  timeshiftAdjustmentsPerMinute: number;
1108
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
+ */
1109
1185
  export declare class Vindral extends Emitter<PublicVindralEvents> {
1110
1186
  #private;
1111
1187
  private static MAX_POOL_SIZE;
1112
1188
  private static REMOVE_CUE_THRESHOLD;
1113
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;
1114
1192
  /**
1115
1193
  * Picture in picture
1116
1194
  */
@@ -1153,7 +1231,10 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1153
1231
  private offscreenCanvasElement?;
1154
1232
  private webCodecsRenditionSupport;
1155
1233
  private hasCalledConnect;
1234
+ private hasRequestedAudioSession;
1156
1235
  private isUserPaused;
1236
+ /** Only the sinks that carry the audio report this, so a paused element here means silence. */
1237
+ private isMediaElementPaused;
1157
1238
  private latestEmittedLanguages;
1158
1239
  private wakeLock;
1159
1240
  private pool;
@@ -1169,6 +1250,7 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1169
1250
  private sizes;
1170
1251
  private isSuspended;
1171
1252
  private inactivityDisconnectInterval;
1253
+ private visiblePauseTimeout;
1172
1254
  private offscreenSubtitleInterval?;
1173
1255
  constructor(options: Options);
1174
1256
  /**
@@ -1470,6 +1552,8 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1470
1552
  private isSupportedVideoCodecProfile;
1471
1553
  private supportedAudioCodecs;
1472
1554
  private initializeDecodingModule;
1555
+ private capturesCanvasOnWebKit;
1556
+ private connectWebKitVideoOutput;
1473
1557
  /**
1474
1558
  * Set up a polling interval that forwards subtitle cues to the decoder worker
1475
1559
  * when OffscreenCanvas rendering is active. This is needed because the canvas modules'
@@ -1501,6 +1585,12 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1501
1585
  * Pauses the stream. Call .play() to resume playback again.
1502
1586
  */
1503
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;
1504
1594
  private registerDebugInstance;
1505
1595
  /**
1506
1596
  *
@@ -1533,8 +1623,18 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1533
1623
  private resetModules;
1534
1624
  private disconnectForInactivePage;
1535
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;
1536
1635
  private clearInactivityDisconnect;
1537
1636
  private isHiddenWithBackgroundPlayback;
1637
+ private isVideoOnScreen;
1538
1638
  private isHiddenWithBackgroundPlayDisabled;
1539
1639
  private suspend;
1540
1640
  private unsuspend;
@@ -1552,6 +1652,20 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1552
1652
  private get targetSubscription();
1553
1653
  private timeToFirstFrame;
1554
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;
1555
1669
  private willUseMediaSource;
1556
1670
  private shouldUseWebCodecs;
1557
1671
  private isWebCodecsVideoAvailable;
package/core.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as e } from "./Cj61-Cjf.js";
2
- import { a as t, c as n, d as r, i, l as a, n as o, o as s, r as c, s as l, u } from "./CiWlpwR0.js";
3
- export { o as AUTHENTICATION_EXPIRED_CODE, c as AUTHENTICATION_FAILED_CODE, i as CHANNEL_NOT_FOUND_CODE, t as CHANNEL_NOT_LIVE_CODE, s as CONNECTION_FAILED_AFTER_RETRIES_CODE, l as CONNECTION_FAILED_CODE, n as DISCONNECTED_BY_EDGE, a as INACTIVITY_CODE, u as NO_INCOMING_DATA, e as Vindral, r as VindralError };
1
+ import { t as e } from "./CN8w7_en.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 "./BBVSf5AB.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 };
package/legacy.d.ts CHANGED
@@ -192,6 +192,18 @@ export interface DrmOptions {
192
192
  export type Media = "audio" | "video" | "audio+video";
193
193
  type WebCodecsHardwareAccelerationPreference = "no-preference" | "prefer-hardware" | "prefer-software";
194
194
  type DecoderType = "mse" | "webcodecs" | "wasm";
195
+ /** What the OS media controls show for the stream. Mirrors the `MediaMetadata` fields. */
196
+ export interface MediaSessionMetadata {
197
+ title?: string;
198
+ artist?: string;
199
+ album?: string;
200
+ /** Fetched by the operating system, so the URLs should not carry credentials. */
201
+ artwork?: Array<{
202
+ src: string;
203
+ sizes?: string;
204
+ type?: string;
205
+ }>;
206
+ }
195
207
  /**
196
208
  * Options for the Vindral instance
197
209
  *
@@ -291,6 +303,20 @@ export interface Options {
291
303
  * Legacy alias kept for backwards compatibility.
292
304
  */
293
305
  iosBackgroundPlayEnabled?: boolean;
306
+ /**
307
+ * Show the stream in the browser and OS media controls (notification, lock screen, toolbar) and
308
+ * let play and pause from there reach the SDK. Enabled by default.
309
+ *
310
+ * The SDK takes over `navigator.mediaSession` for the document, so a page with its own Media
311
+ * Session integration should disable this. On canvas playback paths a silent `<audio>` element is
312
+ * added to `document.body` for the controls to attach to.
313
+ */
314
+ mediaSessionEnabled?: boolean;
315
+ /**
316
+ * Title, artist and artwork for the media controls. Without it the browser derives them from the
317
+ * page. Read once at construction.
318
+ */
319
+ mediaSessionMetadata?: MediaSessionMetadata;
294
320
  /**
295
321
  * Enable or disable Adaptive Bit Rate. This allows for automatically adapting the incoming bit rate based on
296
322
  * the viewers bandwidth and thus avoiding buffering events. This also disables the
@@ -405,6 +431,9 @@ export interface Options {
405
431
  * This enables platform media features such as fullscreen and picture-in-picture
406
432
  * for non-MSE playback by routing the canvas output through a `<video>` element.
407
433
  *
434
+ * On iOS the audio then plays from its own element, so it continues in the background and under
435
+ * lock. After an extended pause from the lock screen, reopening Safari may be required to resume.
436
+ *
408
437
  * Disabled by default.
409
438
  */
410
439
  streamToMediaElementEnabled?: boolean;
@@ -928,6 +957,13 @@ interface JitterModuleStatistics {
928
957
  audioJitter: JitterStatistics | undefined;
929
958
  videoJitter: JitterStatistics | undefined;
930
959
  }
960
+ type DecoyState = "detached" | "attached" | "playing" | "blocked";
961
+ interface MediaSessionModuleStatistics {
962
+ mediaSessionSupported: boolean;
963
+ mediaSessionOwner: boolean;
964
+ mediaSessionPlaybackState: MediaSessionPlaybackState;
965
+ decoyState?: DecoyState;
966
+ }
931
967
  interface MseModuleStatistics {
932
968
  quotaErrorCount: number;
933
969
  mediaSourceOpenTime: number;
@@ -1039,8 +1075,10 @@ interface SyncModuleStatistics {
1039
1075
  interface VideoPlayerStatistics {
1040
1076
  renderedFrameCount: number;
1041
1077
  rendererDroppedFrameCount: number;
1078
+ /** The platform's own view of the audio context, which a mute reading cannot tell apart. */
1079
+ audioContextState?: AudioContextState | "none";
1042
1080
  }
1043
- type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
1081
+ type ModuleStatistics = AdaptivityStatistics & BufferTimeStatistics & ConnectionStatistics & ConstraintCapStatistics & DecoderStatistics & DocumentStateModulesStatistics & IncomingDataModuleStatistics & JitterModuleStatistics & Partial<MediaSessionModuleStatistics> & MseModuleStatistics & PlaybackModuleStatistics & QualityOfServiceModuleStatistics & RenditionsModuleStatistics & SyncModuleStatistics & TelemetryModuleStatistics & VideoPlayerStatistics;
1044
1082
  /**
1045
1083
  * Contains internal statistics.
1046
1084
  *
@@ -1100,6 +1138,8 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1100
1138
  streamToMediaElementEnabled?: boolean;
1101
1139
  /** @deprecated */
1102
1140
  iosMediaElementEnabled?: boolean;
1141
+ /** Whether the element carrying the audio is paused right now, on the sinks that have one. */
1142
+ mediaElementPaused?: boolean;
1103
1143
  /**
1104
1144
  * Average bitrate for the entire session in bits/second.
1105
1145
  */
@@ -1121,11 +1161,49 @@ export type Statistics = ModuleStatistics & ReturnType<UserAgentInformation["get
1121
1161
  */
1122
1162
  timeshiftAdjustmentsPerMinute: number;
1123
1163
  };
1164
+ /**
1165
+ * Represents a Vindral client instance
1166
+ *
1167
+ * The most most essential methods when using the Vindral class are:
1168
+ *
1169
+ * - connect() - this has to be called to actually start connecting
1170
+ * - attach() - to attach the Vindral video view to the DOM so that users can see it
1171
+ * - userInput() - to activate audio on browsers that require a user gesture to play audio
1172
+ * - unload() - unloads the instance, its very important that this is called when cleaning up the Vindral instance, otherwise background timers may leak.
1173
+ *
1174
+ * The Vindral instance will emit a variety of events during its lifetime. Use .on("event-name", callback) to listen to these events.
1175
+ * See [[PublicVindralEvents]] for the events types that can be emitted.
1176
+ *
1177
+ * ```typescript
1178
+ * // minimal configuration of a Vindral client instance
1179
+ * const instance = new Vindral({
1180
+ * url: "https://lb.cdn.vindral.com",
1181
+ * channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
1182
+ * })
1183
+ *
1184
+ * // Will be called when timed metadata is received
1185
+ * instance.on("metadata", console.log)
1186
+ *
1187
+ * // Will be called when a user interaction is needed to activate audio
1188
+ * instance.on("needs user input", console.log)
1189
+ *
1190
+ * // Start connecting to the cdn
1191
+ * instance.connect()
1192
+ *
1193
+ * // Attach the video view to the DOM
1194
+ * instance.attach(document.getElementById("root"))
1195
+ *
1196
+ * // When done with the instance
1197
+ * instance.unload()
1198
+ * ```
1199
+ */
1124
1200
  export declare class Vindral extends Emitter<PublicVindralEvents> {
1125
1201
  #private;
1126
1202
  private static MAX_POOL_SIZE;
1127
1203
  private static REMOVE_CUE_THRESHOLD;
1128
1204
  private static BACKGROUND_INACTIVITY_DISCONNECT_TIMEOUT;
1205
+ /** How long a pause on a visible page may still turn out to be the platform backgrounding us. */
1206
+ private static VISIBLE_PAUSE_DISCONNECT_DELAY;
1129
1207
  /**
1130
1208
  * Picture in picture
1131
1209
  */
@@ -1168,7 +1246,10 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1168
1246
  private offscreenCanvasElement?;
1169
1247
  private webCodecsRenditionSupport;
1170
1248
  private hasCalledConnect;
1249
+ private hasRequestedAudioSession;
1171
1250
  private isUserPaused;
1251
+ /** Only the sinks that carry the audio report this, so a paused element here means silence. */
1252
+ private isMediaElementPaused;
1172
1253
  private latestEmittedLanguages;
1173
1254
  private wakeLock;
1174
1255
  private pool;
@@ -1184,6 +1265,7 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1184
1265
  private sizes;
1185
1266
  private isSuspended;
1186
1267
  private inactivityDisconnectInterval;
1268
+ private visiblePauseTimeout;
1187
1269
  private offscreenSubtitleInterval?;
1188
1270
  constructor(options: Options);
1189
1271
  /**
@@ -1485,6 +1567,8 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1485
1567
  private isSupportedVideoCodecProfile;
1486
1568
  private supportedAudioCodecs;
1487
1569
  private initializeDecodingModule;
1570
+ private capturesCanvasOnWebKit;
1571
+ private connectWebKitVideoOutput;
1488
1572
  /**
1489
1573
  * Set up a polling interval that forwards subtitle cues to the decoder worker
1490
1574
  * when OffscreenCanvas rendering is active. This is needed because the canvas modules'
@@ -1516,6 +1600,12 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1516
1600
  * Pauses the stream. Call .play() to resume playback again.
1517
1601
  */
1518
1602
  pause: () => void;
1603
+ /**
1604
+ * A browser-initiated decoy pause means an interruption (another app took the focus, headphones
1605
+ * unplugged), so give the audio up rather than play over it. WebKit holds the decoy on purpose.
1606
+ */
1607
+ private yieldToInterruption;
1608
+ private fromNativeControls;
1519
1609
  private registerDebugInstance;
1520
1610
  /**
1521
1611
  *
@@ -1548,8 +1638,18 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1548
1638
  private resetModules;
1549
1639
  private disconnectForInactivePage;
1550
1640
  private scheduleInactivityDisconnect;
1641
+ /**
1642
+ * iOS pauses the element a moment before it hides the page, and that pause reaches us while the
1643
+ * page still reports visible. Acting on it at once tears the session down, so every app switch
1644
+ * comes back as a full reconnect. Wait for the hide that follows a platform pause instead.
1645
+ * Nowhere else pauses before hiding, so there a visible pause is the viewer's at once.
1646
+ */
1647
+ private onVisiblePause;
1648
+ private disconnectForVisiblePause;
1649
+ private clearVisiblePauseDisconnect;
1551
1650
  private clearInactivityDisconnect;
1552
1651
  private isHiddenWithBackgroundPlayback;
1652
+ private isVideoOnScreen;
1553
1653
  private isHiddenWithBackgroundPlayDisabled;
1554
1654
  private suspend;
1555
1655
  private unsuspend;
@@ -1567,6 +1667,20 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
1567
1667
  private get targetSubscription();
1568
1668
  private timeToFirstFrame;
1569
1669
  private resolvedDecoder;
1670
+ /**
1671
+ * On mobile Chromium with WebCodecs audio the play action arrives but no sound comes back until
1672
+ * the page is visible, so a hidden pause is a stop there. Reads the decoder in use.
1673
+ */
1674
+ private hiddenPauseIsStop;
1675
+ private usesSplitCanvasAudio;
1676
+ private isWebKitCanvasPath;
1677
+ private holdsDecoyWhilePaused;
1678
+ private streamsToMediaElement;
1679
+ /**
1680
+ * Safari 16.4+: a playback audio session keeps Web Audio alive in the background. Document-wide
1681
+ * and not restorable, so it waits for playback to be wanted rather than for construction.
1682
+ */
1683
+ private requestAudioSessionOnce;
1570
1684
  private willUseMediaSource;
1571
1685
  private shouldUseWebCodecs;
1572
1686
  private isWebCodecsVideoAvailable;