@goboss/web-video-player-sdk 1.0.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.
Potentially problematic release.
This version of @goboss/web-video-player-sdk might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +331 -0
- package/dist/index.d.ts +463 -0
- package/dist/index.js +1803 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +10 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/web-video-player-sdk.css +2 -0
- package/package.json +72 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { default as default_2 } from 'react';
|
|
2
|
+
|
|
3
|
+
export declare type AnalyticsCallback = (event: AnalyticsEvent) => void;
|
|
4
|
+
|
|
5
|
+
export declare interface AnalyticsEvent {
|
|
6
|
+
eventType: 'play' | 'pause' | 'seek' | 'ended' | 'complete' | 'buffering_start' | 'buffering_end' | 'stall' | 'quality_change' | 'audio_track_change' | 'volume_change' | 'speed_change' | 'subtitle_change' | 'pip_toggle' | 'fullscreen_enter' | 'fullscreen_exit' | 'cast_start' | 'cast_stop' | 'error' | 'network_error' | 'session_start' | 'video_loaded' | 'first_quartile' | 'midpoint' | 'third_quartile' | 'heartbeat';
|
|
7
|
+
timestamp: number;
|
|
8
|
+
currentTime: number;
|
|
9
|
+
duration: number;
|
|
10
|
+
bitrate?: number;
|
|
11
|
+
rendition?: string;
|
|
12
|
+
fromRendition?: string;
|
|
13
|
+
volume?: number;
|
|
14
|
+
speed?: number;
|
|
15
|
+
errorMessage?: string;
|
|
16
|
+
errorCode?: number;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
videoId?: string;
|
|
19
|
+
deviceType?: string;
|
|
20
|
+
networkType?: string;
|
|
21
|
+
watchPercentage?: number;
|
|
22
|
+
totalWatchTime?: number;
|
|
23
|
+
bufferingCount?: number;
|
|
24
|
+
totalBufferingTime?: number;
|
|
25
|
+
seekFrom?: number;
|
|
26
|
+
pipState?: 'entered' | 'exited';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare class AnalyticsModule {
|
|
30
|
+
private callback?;
|
|
31
|
+
private heartbeatInterval?;
|
|
32
|
+
private isBuffering;
|
|
33
|
+
private sessionId;
|
|
34
|
+
private videoId;
|
|
35
|
+
private deviceType;
|
|
36
|
+
private networkType;
|
|
37
|
+
private isFirstPlay;
|
|
38
|
+
private watchStartTime;
|
|
39
|
+
private totalWatchTime;
|
|
40
|
+
private bufferingCount;
|
|
41
|
+
private totalBufferingTime;
|
|
42
|
+
private bufferingStartTime;
|
|
43
|
+
private milestonesHit;
|
|
44
|
+
private lastHeartbeatPosition;
|
|
45
|
+
private lastHeartbeatAt;
|
|
46
|
+
constructor(callback?: AnalyticsCallback, src?: string);
|
|
47
|
+
registerCallback(callback: AnalyticsCallback): void;
|
|
48
|
+
track(eventType: AnalyticsEvent['eventType'], videoEl: HTMLVideoElement, extra?: Partial<AnalyticsEvent>): void;
|
|
49
|
+
startHeartbeat(videoEl: HTMLVideoElement, getExtra: () => Partial<AnalyticsEvent>): void;
|
|
50
|
+
stopHeartbeat(): void;
|
|
51
|
+
setBuffering(isBuffering: boolean, videoEl: HTMLVideoElement, getExtra: () => Partial<AnalyticsEvent>): void;
|
|
52
|
+
private checkMilestones;
|
|
53
|
+
private checkStall;
|
|
54
|
+
private dispatchRaw;
|
|
55
|
+
private generateSessionId;
|
|
56
|
+
private extractVideoId;
|
|
57
|
+
private getDeviceType;
|
|
58
|
+
private getNetworkType;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare class CastingModule {
|
|
62
|
+
private isCasting;
|
|
63
|
+
private castDeviceName;
|
|
64
|
+
private onCastStateChangeCallback?;
|
|
65
|
+
private castContext;
|
|
66
|
+
private remotePlayer;
|
|
67
|
+
private remotePlayerController;
|
|
68
|
+
constructor();
|
|
69
|
+
private initCastApi;
|
|
70
|
+
getCastingState(): {
|
|
71
|
+
isCasting: boolean;
|
|
72
|
+
deviceName: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Prompts the native Google Cast device picker overlay.
|
|
76
|
+
*/
|
|
77
|
+
requestSession(currentSrc: string, currentTime: number): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Disconnects the current cast session.
|
|
80
|
+
*/
|
|
81
|
+
stopCasting(): void;
|
|
82
|
+
onCastStateChange(callback: (isCasting: boolean, deviceName: string) => void): void;
|
|
83
|
+
requestAirPlaySession(videoElement: HTMLVideoElement): void;
|
|
84
|
+
stopAirPlay(videoElement: HTMLVideoElement): void;
|
|
85
|
+
isAirPlayAvailable(): boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export declare interface Chapter {
|
|
89
|
+
title: string;
|
|
90
|
+
startTime: number;
|
|
91
|
+
endTime: number;
|
|
92
|
+
thumbnail?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
declare class ChaptersModule extends KeyMomentsModule {
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Mounts the full video player (React UI + all controls) into any DOM element.
|
|
100
|
+
* Use this in Vue, Angular, Vanilla JS, or any environment where JSX is unavailable.
|
|
101
|
+
*
|
|
102
|
+
* @example Vanilla JS
|
|
103
|
+
* const player = createPlayer(document.getElementById('player'), { src: 'https://...' });
|
|
104
|
+
* player.destroy(); // cleanup
|
|
105
|
+
*
|
|
106
|
+
* @example Vue 3
|
|
107
|
+
* const player = createPlayer(containerRef.value, { src: props.src });
|
|
108
|
+
* onUnmounted(() => player.destroy());
|
|
109
|
+
*
|
|
110
|
+
* @example Angular
|
|
111
|
+
* const player = createPlayer(this.containerRef.nativeElement, { src: this.src });
|
|
112
|
+
* ngOnDestroy() { this.player.destroy(); }
|
|
113
|
+
*/
|
|
114
|
+
export declare function createPlayer(container: HTMLElement, props: PlayerProps): PlayerInstance;
|
|
115
|
+
|
|
116
|
+
export declare interface DRMConfig {
|
|
117
|
+
widevineLicenseUrl?: string;
|
|
118
|
+
playreadyLicenseUrl?: string;
|
|
119
|
+
fairplayLicenseUrl?: string;
|
|
120
|
+
authToken?: string;
|
|
121
|
+
allowedDomains?: string[];
|
|
122
|
+
watermarkText?: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
declare class DRMModule {
|
|
126
|
+
private config?;
|
|
127
|
+
private watermarkElement?;
|
|
128
|
+
private floatInterval?;
|
|
129
|
+
constructor(config?: DRMConfig);
|
|
130
|
+
/**
|
|
131
|
+
* Validates if the active origin domain is permitted to load this stream asset.
|
|
132
|
+
*/
|
|
133
|
+
validateDomain(currentDomain: string): boolean;
|
|
134
|
+
getAuthToken(): string | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Injects an animated floating watermark on top of the media container to obstruct piracy or recording.
|
|
137
|
+
*/
|
|
138
|
+
setupWatermark(container: HTMLElement): void;
|
|
139
|
+
/**
|
|
140
|
+
* Cleans up active watermarks.
|
|
141
|
+
*/
|
|
142
|
+
removeWatermark(): void;
|
|
143
|
+
isDRMProtected(): boolean;
|
|
144
|
+
getDRMDetails(): {
|
|
145
|
+
widevine: string | null;
|
|
146
|
+
playready: string | null;
|
|
147
|
+
fairplay: string | null;
|
|
148
|
+
authTokenPresent: boolean;
|
|
149
|
+
allowedDomains: string[];
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sends all player analytics events to Firebase Analytics (GA4).
|
|
155
|
+
*
|
|
156
|
+
* Events appear in:
|
|
157
|
+
* Firebase Console → Analytics → Events (24-48 hr aggregated view)
|
|
158
|
+
* Firebase Console → Analytics → DebugView (real-time while testing)
|
|
159
|
+
* Google Analytics 4 → Reports → Realtime (within a few minutes)
|
|
160
|
+
*
|
|
161
|
+
* No Firestore / database setup required — Firebase Analytics handles all storage.
|
|
162
|
+
*/
|
|
163
|
+
export declare class FirebaseAnalyticsProvider {
|
|
164
|
+
private analytics;
|
|
165
|
+
constructor(config: FirebaseConfig);
|
|
166
|
+
private init;
|
|
167
|
+
createCallback(): AnalyticsCallback;
|
|
168
|
+
private handleEvent;
|
|
169
|
+
private buildParams;
|
|
170
|
+
destroy(): Promise<void>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export declare interface FirebaseConfig {
|
|
174
|
+
apiKey: string;
|
|
175
|
+
authDomain: string;
|
|
176
|
+
projectId: string;
|
|
177
|
+
storageBucket: string;
|
|
178
|
+
messagingSenderId: string;
|
|
179
|
+
appId: string;
|
|
180
|
+
measurementId?: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export declare type KeyMoment = Chapter;
|
|
184
|
+
|
|
185
|
+
declare class KeyMomentsModule {
|
|
186
|
+
private keyMoments;
|
|
187
|
+
private currentMomentIndex;
|
|
188
|
+
private onMomentChangeCallback?;
|
|
189
|
+
constructor(keyMoments?: KeyMoment[]);
|
|
190
|
+
/**
|
|
191
|
+
* Sorts and stores the key moments.
|
|
192
|
+
*/
|
|
193
|
+
setKeyMoments(keyMoments: KeyMoment[]): void;
|
|
194
|
+
getKeyMoments(): KeyMoment[];
|
|
195
|
+
/**
|
|
196
|
+
* Locates the key moment corresponding to the active playback timestamp.
|
|
197
|
+
*/
|
|
198
|
+
getCurrentMoment(currentTime: number): {
|
|
199
|
+
keyMoment: KeyMoment | null;
|
|
200
|
+
index: number;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Evaluates if playback has crossed a key moment boundary.
|
|
204
|
+
*/
|
|
205
|
+
updateTime(currentTime: number): void;
|
|
206
|
+
/**
|
|
207
|
+
* Subscribes a callback to change events.
|
|
208
|
+
*/
|
|
209
|
+
onMomentChange(callback: (keyMoment: KeyMoment | null, index: number) => void): void;
|
|
210
|
+
setChapters(chapters: KeyMoment[]): void;
|
|
211
|
+
getChapters(): KeyMoment[];
|
|
212
|
+
getCurrentChapter(currentTime: number): {
|
|
213
|
+
chapter: KeyMoment | null;
|
|
214
|
+
index: number;
|
|
215
|
+
};
|
|
216
|
+
onChapterChange(callback: (chapter: KeyMoment | null, index: number) => void): void;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export declare interface PlayerInstance {
|
|
220
|
+
/** Re-render the player with updated props (src change, theme, etc.) */
|
|
221
|
+
update(props: Partial<PlayerProps>): void;
|
|
222
|
+
/** Unmounts the player and releases all resources */
|
|
223
|
+
destroy(): void;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Props accepted by createPlayer — mirrors WebVideoPlayerProps so all
|
|
228
|
+
* framework wrappers (Vue, Angular, Vanilla JS) share the same API surface.
|
|
229
|
+
*/
|
|
230
|
+
export declare interface PlayerProps {
|
|
231
|
+
src: string;
|
|
232
|
+
chapters?: Chapter[];
|
|
233
|
+
keyMoments?: KeyMoment[];
|
|
234
|
+
subtitles?: SubtitleTrack[];
|
|
235
|
+
watermark?: string;
|
|
236
|
+
themeColor?: string;
|
|
237
|
+
drmConfig?: any;
|
|
238
|
+
firebaseConfig?: FirebaseConfig;
|
|
239
|
+
onAnalyticsEvent?: (event: AnalyticsEvent) => void;
|
|
240
|
+
onKeyMomentsLoaded?: (keyMoments: KeyMoment[]) => void;
|
|
241
|
+
enableControls?: boolean;
|
|
242
|
+
enableChromecast?: boolean;
|
|
243
|
+
enableKeyMoments?: boolean;
|
|
244
|
+
enableSubtitles?: boolean;
|
|
245
|
+
enableQuality?: boolean;
|
|
246
|
+
enablePlaybackSpeed?: boolean;
|
|
247
|
+
enablePiP?: boolean;
|
|
248
|
+
enableFullscreen?: boolean;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export declare interface PlayerSDKOptions {
|
|
252
|
+
container: HTMLElement;
|
|
253
|
+
src: string;
|
|
254
|
+
autoplay?: boolean;
|
|
255
|
+
muted?: boolean;
|
|
256
|
+
controls?: boolean;
|
|
257
|
+
chapters?: Chapter[];
|
|
258
|
+
keyMoments?: KeyMoment[];
|
|
259
|
+
subtitles?: SubtitleTrack[];
|
|
260
|
+
thumbnails?: ThumbnailConfig;
|
|
261
|
+
drm?: DRMConfig;
|
|
262
|
+
analyticsCallback?: AnalyticsCallback;
|
|
263
|
+
themeColor?: string;
|
|
264
|
+
watermark?: string;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
declare class SubtitlesModule {
|
|
268
|
+
private tracks;
|
|
269
|
+
private activeTrackId;
|
|
270
|
+
private currentCues;
|
|
271
|
+
private activeText;
|
|
272
|
+
private onSubtitleChangeCallback?;
|
|
273
|
+
private onTrackSwitchCallback?;
|
|
274
|
+
constructor(tracks?: SubtitleTrack[]);
|
|
275
|
+
getTracks(): SubtitleTrack[];
|
|
276
|
+
getActiveTrackId(): string;
|
|
277
|
+
setHlsTracks(hlsTracks: SubtitleTrack[]): void;
|
|
278
|
+
addTrack(track: SubtitleTrack): void;
|
|
279
|
+
onTrackSwitch(callback: (track: SubtitleTrack | null) => void): void;
|
|
280
|
+
setCustomSubtitleText(text: string): void;
|
|
281
|
+
/**
|
|
282
|
+
* Switches the active track. Fetches external tracks if they need loading.
|
|
283
|
+
*/
|
|
284
|
+
setActiveTrack(trackId: string): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Scans the subtitle cues for the current playback position.
|
|
287
|
+
*/
|
|
288
|
+
updateTime(currentTime: number): void;
|
|
289
|
+
/**
|
|
290
|
+
* Triggers the text update callback if a change in caption is detected.
|
|
291
|
+
*/
|
|
292
|
+
private updateActiveText;
|
|
293
|
+
onSubtitleChange(callback: (text: string) => void): void;
|
|
294
|
+
/**
|
|
295
|
+
* Robust parser supporting WebVTT and SRT formats.
|
|
296
|
+
*/
|
|
297
|
+
private parseVttOrSrt;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
declare interface SubtitleStyle {
|
|
301
|
+
size?: 'small' | 'medium' | 'large';
|
|
302
|
+
background?: 'none' | 'dim' | 'solid';
|
|
303
|
+
color?: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export declare interface SubtitleTrack {
|
|
307
|
+
id: string;
|
|
308
|
+
label: string;
|
|
309
|
+
lang: string;
|
|
310
|
+
src?: string;
|
|
311
|
+
isDefault?: boolean;
|
|
312
|
+
cues?: Array<{
|
|
313
|
+
startTime: number;
|
|
314
|
+
endTime: number;
|
|
315
|
+
text: string;
|
|
316
|
+
}>;
|
|
317
|
+
isHls?: boolean;
|
|
318
|
+
hlsTrackId?: number;
|
|
319
|
+
isNative?: boolean;
|
|
320
|
+
nativeTrackIndex?: number;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export declare interface ThumbnailConfig {
|
|
324
|
+
spriteUrl: string;
|
|
325
|
+
tileWidth: number;
|
|
326
|
+
tileHeight: number;
|
|
327
|
+
columns: number;
|
|
328
|
+
rows: number;
|
|
329
|
+
interval: number;
|
|
330
|
+
totalCount: number;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
declare class ThumbnailsModule {
|
|
334
|
+
private config?;
|
|
335
|
+
constructor(config?: ThumbnailConfig);
|
|
336
|
+
/**
|
|
337
|
+
* Calculates the position offset inside the sprite sheet for a given seek hover time.
|
|
338
|
+
*/
|
|
339
|
+
getThumbnail(time: number): {
|
|
340
|
+
url: string;
|
|
341
|
+
x: number;
|
|
342
|
+
y: number;
|
|
343
|
+
width: number;
|
|
344
|
+
height: number;
|
|
345
|
+
} | null;
|
|
346
|
+
hasThumbnails(): boolean;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export declare class VideoPlayerSDK {
|
|
350
|
+
private options;
|
|
351
|
+
private videoElement;
|
|
352
|
+
private hlsInstance;
|
|
353
|
+
private dashInstance;
|
|
354
|
+
private activeQuality;
|
|
355
|
+
private qualityLevels;
|
|
356
|
+
analytics: AnalyticsModule;
|
|
357
|
+
keyMoments: KeyMomentsModule;
|
|
358
|
+
chapters: ChaptersModule;
|
|
359
|
+
subtitles: SubtitlesModule;
|
|
360
|
+
drm: DRMModule;
|
|
361
|
+
casting: CastingModule;
|
|
362
|
+
thumbnails: ThumbnailsModule;
|
|
363
|
+
private hlsSubtitleCues;
|
|
364
|
+
private hlsActiveSubtitleKey;
|
|
365
|
+
private audioTrackList;
|
|
366
|
+
private eventListeners;
|
|
367
|
+
constructor(options: PlayerSDKOptions);
|
|
368
|
+
/**
|
|
369
|
+
* Builds the video DOM hierarchy, binds events, validates domain restrictions, and mounts DRM watermarks.
|
|
370
|
+
*/
|
|
371
|
+
private initializePlayer;
|
|
372
|
+
/**
|
|
373
|
+
* Binds direct event listeners to the native HTML5 Video tag, routing them to our sub-packages.
|
|
374
|
+
*/
|
|
375
|
+
private bindMediaEvents;
|
|
376
|
+
private rewriteToProxy;
|
|
377
|
+
/**
|
|
378
|
+
* Initializes HLS adaptive streaming through Hls.js or falls back to native browser playback.
|
|
379
|
+
*/
|
|
380
|
+
private loadSource;
|
|
381
|
+
/**
|
|
382
|
+
* Sets up global lock-screen metadata and media control keys (Media Session API).
|
|
383
|
+
*/
|
|
384
|
+
private setupBackgroundControls;
|
|
385
|
+
play(): void;
|
|
386
|
+
pause(): void;
|
|
387
|
+
seek(seconds: number): void;
|
|
388
|
+
setVolume(volume: number): void;
|
|
389
|
+
setMute(muted: boolean): void;
|
|
390
|
+
setPlaybackRate(rate: number): void;
|
|
391
|
+
/**
|
|
392
|
+
* Sets manual video quality rendition or switches back to auto bitrate scaling.
|
|
393
|
+
*/
|
|
394
|
+
setQuality(qualityId: number): void;
|
|
395
|
+
/**
|
|
396
|
+
* Activates native Picture-in-Picture floating viewport.
|
|
397
|
+
*/
|
|
398
|
+
togglePictureInPicture(): Promise<boolean>;
|
|
399
|
+
/**
|
|
400
|
+
* Requests element-level fullscreen.
|
|
401
|
+
*/
|
|
402
|
+
toggleFullscreen(): void;
|
|
403
|
+
getVideoElement(): HTMLVideoElement;
|
|
404
|
+
getCurrentTime(): number;
|
|
405
|
+
getDuration(): number;
|
|
406
|
+
getVolume(): number;
|
|
407
|
+
isMuted(): boolean;
|
|
408
|
+
getPlaybackRate(): number;
|
|
409
|
+
getActiveQuality(): VideoQuality;
|
|
410
|
+
getQualityLevels(): VideoQuality[];
|
|
411
|
+
getBufferLength(): number;
|
|
412
|
+
getBufferedRanges(): Array<{
|
|
413
|
+
start: number;
|
|
414
|
+
end: number;
|
|
415
|
+
}>;
|
|
416
|
+
private getAnalyticsPayload;
|
|
417
|
+
on(event: string, callback: (...args: any[]) => void): void;
|
|
418
|
+
off(event: string, callback: (...args: any[]) => void): void;
|
|
419
|
+
private emit;
|
|
420
|
+
private extractSubtitlesFromManifest;
|
|
421
|
+
private extractKeyMomentsFromManifest;
|
|
422
|
+
getAudioTracks(): Array<{
|
|
423
|
+
id: number;
|
|
424
|
+
label: string;
|
|
425
|
+
lang: string;
|
|
426
|
+
}>;
|
|
427
|
+
setAudioTrack(id: number): void;
|
|
428
|
+
destroy(): void;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export declare interface VideoQuality {
|
|
432
|
+
id: number;
|
|
433
|
+
height: number;
|
|
434
|
+
width: number;
|
|
435
|
+
bitrate: number;
|
|
436
|
+
label: string;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export declare const WebVideoPlayer: default_2.FC<WebVideoPlayerProps>;
|
|
440
|
+
|
|
441
|
+
declare interface WebVideoPlayerProps {
|
|
442
|
+
src: string;
|
|
443
|
+
chapters?: Chapter[];
|
|
444
|
+
keyMoments?: KeyMoment[];
|
|
445
|
+
subtitles?: SubtitleTrack[];
|
|
446
|
+
watermark?: string;
|
|
447
|
+
themeColor?: string;
|
|
448
|
+
drmConfig?: any;
|
|
449
|
+
firebaseConfig?: FirebaseConfig;
|
|
450
|
+
onAnalyticsEvent?: (event: AnalyticsEvent) => void;
|
|
451
|
+
onKeyMomentsLoaded?: (keyMoments: KeyMoment[]) => void;
|
|
452
|
+
enableControls?: boolean;
|
|
453
|
+
enableChromecast?: boolean;
|
|
454
|
+
enableKeyMoments?: boolean;
|
|
455
|
+
enableSubtitles?: boolean;
|
|
456
|
+
enableQuality?: boolean;
|
|
457
|
+
enablePlaybackSpeed?: boolean;
|
|
458
|
+
enablePiP?: boolean;
|
|
459
|
+
enableFullscreen?: boolean;
|
|
460
|
+
subtitleStyle?: SubtitleStyle;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export { }
|