@cinecrew/cinecrew-player 0.1.1

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.
Files changed (66) hide show
  1. package/CineCrewPlayer.podspec +22 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +6 -0
  4. package/README.md +574 -0
  5. package/android/build.gradle +48 -0
  6. package/android/proguard-rules.pro +29 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/yuanzhou/vlc/ReactVlcPlayerPackage.java +28 -0
  9. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/ReactVlcPlayerView.java +988 -0
  10. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/ReactVlcPlayerViewManager.java +208 -0
  11. package/android/src/main/java/com/yuanzhou/vlc/vlcplayer/VideoEventEmitter.java +136 -0
  12. package/android/src/main/res/values/strings.xml +3 -0
  13. package/app.plugin.cjs +1 -0
  14. package/assets/cinecrew-player-logo.svg +44 -0
  15. package/package.json +132 -0
  16. package/packages/react-native-vlc-media-player/LICENSE +21 -0
  17. package/packages/react-native-vlc-media-player/VLCPlayer.js +207 -0
  18. package/packages/react-native-vlc-media-player/expo/android/withGradleTasks.cjs +49 -0
  19. package/packages/react-native-vlc-media-player/expo/ios/withMobileVlcKit.cjs +28 -0
  20. package/packages/react-native-vlc-media-player/expo/withVlcMediaPlayer.cjs +10 -0
  21. package/packages/react-native-vlc-media-player/index.d.ts +354 -0
  22. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayer.h +36 -0
  23. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayer.m +635 -0
  24. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayerManager.h +5 -0
  25. package/packages/react-native-vlc-media-player/ios/RCTVLCPlayer/RCTVLCPlayerManager.m +100 -0
  26. package/src/native/InlineLivePlayer.js +321 -0
  27. package/src/native/MediaPlayerView.js +3093 -0
  28. package/src/native/customization.js +44 -0
  29. package/src/native/index.js +107 -0
  30. package/src/native/media/ElectronVideoPlayer.js +288 -0
  31. package/src/native/media/EmojiPickerModal.js +30 -0
  32. package/src/native/media/LiveChatDrawer.js +1177 -0
  33. package/src/native/media/LiveRecordingOverlay.js +319 -0
  34. package/src/native/media/WebVideoPlayer.js +320 -0
  35. package/src/native/media/YouTubeVideoPlayer.native.js +120 -0
  36. package/src/native/media/YouTubeVideoPlayer.web.js +169 -0
  37. package/src/native/media/player/AudioOnlyView.js +337 -0
  38. package/src/native/media/player/CenterControls.js +94 -0
  39. package/src/native/media/player/ExoVideoFallback.js +329 -0
  40. package/src/native/media/player/PipOverlay.js +1 -0
  41. package/src/native/media/player/PlayerBottomBar.js +295 -0
  42. package/src/native/media/player/PlayerTopBar.js +255 -0
  43. package/src/native/media/player/VLCBoundary.js +41 -0
  44. package/src/native/media/player/VerticalIndicator.js +184 -0
  45. package/src/native/media/player/index.js +9 -0
  46. package/src/native/media/player/playerConstants.js +159 -0
  47. package/src/native/media/web/useWebAc3AudioPlayback.native.js +6 -0
  48. package/src/native/media/web/useWebAc3AudioPlayback.web.js +219 -0
  49. package/src/native/media/web/useWebHlsPlayback.native.js +3 -0
  50. package/src/native/media/web/useWebHlsPlayback.web.js +66 -0
  51. package/src/native/media/web/useWebMediaSession.js +90 -0
  52. package/src/native/media/web/useWebMpegTsPlayback.native.js +3 -0
  53. package/src/native/media/web/useWebMpegTsPlayback.web.js +356 -0
  54. package/src/native/media/web/useWebVideoAspectRatio.js +52 -0
  55. package/src/native/media/web/webPlaybackErrors.js +4 -0
  56. package/src/utils/layoutUtils.js +12 -0
  57. package/src/utils/mediaUtils.js +7 -0
  58. package/src/utils/recording.js +8 -0
  59. package/src/utils/runtimePlatform.js +19 -0
  60. package/src/utils/sourceUtils.js +99 -0
  61. package/src/utils/youtubeHtml.js +34 -0
  62. package/src/web/index.js +1129 -0
  63. package/src/web/styles.css +378 -0
  64. package/types/index.d.ts +268 -0
  65. package/vendor/mpegts.js/LICENSE +202 -0
  66. package/vendor/mpegts.js/mpegts.js +3 -0
@@ -0,0 +1,378 @@
1
+ .cinecrew-player {
2
+ position: relative;
3
+ display: flex;
4
+ width: 100%;
5
+ min-width: 0;
6
+ min-height: 180px;
7
+ aspect-ratio: 16 / 9;
8
+ overflow: hidden;
9
+ isolation: isolate;
10
+ color: var(--cinecrew-text, #fff);
11
+ font: 500 14px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
12
+ }
13
+
14
+ .cinecrew-player:fullscreen {
15
+ width: 100vw;
16
+ height: 100vh;
17
+ aspect-ratio: auto;
18
+ border-radius: 0 !important;
19
+ }
20
+
21
+ .cinecrew-player__video,
22
+ .cinecrew-player__empty {
23
+ position: absolute;
24
+ inset: 0;
25
+ width: 100%;
26
+ height: 100%;
27
+ background: #000;
28
+ }
29
+
30
+ .cinecrew-player__shade {
31
+ position: absolute;
32
+ inset: 0;
33
+ pointer-events: none;
34
+ }
35
+
36
+ .cinecrew-player__title {
37
+ position: absolute;
38
+ top: 18px;
39
+ left: 20px;
40
+ z-index: 2;
41
+ max-width: min(65%, 680px);
42
+ overflow: hidden;
43
+ font-weight: 700;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ text-shadow: 0 1px 4px #000;
47
+ }
48
+
49
+ .cinecrew-player__controls {
50
+ position: absolute;
51
+ inset: 0;
52
+ z-index: 3;
53
+ display: flex;
54
+ flex-direction: column;
55
+ justify-content: space-between;
56
+ padding: 14px;
57
+ opacity: 0;
58
+ transition: opacity 160ms ease;
59
+ }
60
+
61
+ .cinecrew-player:hover .cinecrew-player__controls,
62
+ .cinecrew-player:focus-within .cinecrew-player__controls {
63
+ opacity: 1;
64
+ }
65
+
66
+ .cinecrew-player__top-controls,
67
+ .cinecrew-player__bottom-controls,
68
+ .cinecrew-player__center-controls,
69
+ .cinecrew-player__seek {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 8px;
73
+ }
74
+
75
+ .cinecrew-player__top-controls,
76
+ .cinecrew-player__bottom-controls {
77
+ flex-wrap: wrap;
78
+ }
79
+
80
+ .cinecrew-player__bottom-controls {
81
+ justify-content: flex-end;
82
+ }
83
+
84
+ .cinecrew-player__center-controls {
85
+ justify-content: center;
86
+ }
87
+
88
+ .cinecrew-player__seek {
89
+ flex: 1 1 100%;
90
+ font-variant-numeric: tabular-nums;
91
+ text-shadow: 0 1px 3px #000;
92
+ }
93
+
94
+ .cinecrew-player__seek input {
95
+ flex: 1;
96
+ min-width: 50px;
97
+ }
98
+
99
+ .cinecrew-player__button {
100
+ display: inline-flex;
101
+ min-width: 38px;
102
+ min-height: 38px;
103
+ align-items: center;
104
+ justify-content: center;
105
+ gap: 7px;
106
+ padding: 8px 11px;
107
+ border: 1px solid rgba(255,255,255,.18);
108
+ border-radius: 999px;
109
+ cursor: pointer;
110
+ font: inherit;
111
+ line-height: 1;
112
+ backdrop-filter: blur(12px);
113
+ }
114
+
115
+ .cinecrew-player__button:hover,
116
+ .cinecrew-player__button:focus-visible,
117
+ .cinecrew-player__button.is-active {
118
+ outline: none;
119
+ border-color: var(--cinecrew-accent, #00d4ff);
120
+ }
121
+
122
+ .cinecrew-player__button:disabled {
123
+ opacity: .45;
124
+ cursor: not-allowed;
125
+ }
126
+
127
+ .cinecrew-player__icon {
128
+ display: inline-flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ min-width: 1em;
132
+ font-size: 18px;
133
+ }
134
+
135
+ .cinecrew-player__status,
136
+ .cinecrew-player__error {
137
+ position: absolute;
138
+ inset: 0;
139
+ z-index: 5;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 12px;
144
+ text-align: center;
145
+ }
146
+
147
+ .cinecrew-player__audio-card {
148
+ position: absolute;
149
+ inset: 10%;
150
+ z-index: 5;
151
+ display: flex;
152
+ flex-direction: column;
153
+ align-items: center;
154
+ justify-content: center;
155
+ gap: 18px;
156
+ padding: 24px;
157
+ border: 1px solid;
158
+ border-radius: 20px;
159
+ text-align: center;
160
+ box-shadow: 0 18px 60px rgba(0, 0, 0, .32);
161
+ }
162
+
163
+ .cinecrew-player__audio-poster {
164
+ width: min(30vw, 160px);
165
+ aspect-ratio: 1;
166
+ object-fit: cover;
167
+ border-radius: 50%;
168
+ }
169
+
170
+ .cinecrew-player__audio-wave {
171
+ letter-spacing: .28em;
172
+ font-size: 1.25rem;
173
+ }
174
+
175
+ .cinecrew-player__audio-card strong {
176
+ max-width: 100%;
177
+ font-size: clamp(1rem, 2vw, 1.4rem);
178
+ }
179
+
180
+ .cinecrew-player__audio-card button {
181
+ border: 1px solid;
182
+ border-radius: 999px;
183
+ background: transparent;
184
+ padding: 10px 18px;
185
+ font: inherit;
186
+ cursor: pointer;
187
+ }
188
+
189
+ .cinecrew-player__status {
190
+ pointer-events: none;
191
+ background: rgba(0,0,0,.24);
192
+ }
193
+
194
+ .cinecrew-player__spinner {
195
+ width: 24px;
196
+ height: 24px;
197
+ border: 3px solid rgba(255,255,255,.25);
198
+ border-radius: 50%;
199
+ animation: cinecrew-spin .75s linear infinite;
200
+ }
201
+
202
+ .cinecrew-player__error {
203
+ flex-direction: column;
204
+ padding: 24px;
205
+ }
206
+
207
+ .cinecrew-player__error strong {
208
+ font-size: 1.1em;
209
+ }
210
+
211
+ .cinecrew-player__menu-wrap {
212
+ position: relative;
213
+ }
214
+
215
+ .cinecrew-player__menu {
216
+ position: absolute;
217
+ right: 0;
218
+ bottom: calc(100% + 8px);
219
+ display: flex;
220
+ min-width: 150px;
221
+ flex-direction: column;
222
+ overflow: hidden;
223
+ border: 1px solid rgba(255,255,255,.16);
224
+ border-radius: 10px;
225
+ box-shadow: 0 8px 30px rgba(0,0,0,.4);
226
+ }
227
+
228
+ .cinecrew-player__menu button,
229
+ .cinecrew-player__panel-close {
230
+ padding: 10px 13px;
231
+ border: 0;
232
+ color: inherit;
233
+ background: transparent;
234
+ cursor: pointer;
235
+ text-align: left;
236
+ font: inherit;
237
+ }
238
+
239
+ .cinecrew-player__panel-content {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: 10px;
243
+ min-height: 0;
244
+ max-height: 100%;
245
+ font: inherit;
246
+ }
247
+
248
+ .cinecrew-player__panel-heading {
249
+ display: flex;
250
+ align-items: center;
251
+ justify-content: space-between;
252
+ gap: 12px;
253
+ padding-bottom: 8px;
254
+ border-bottom: 1px solid rgba(255, 255, 255, .14);
255
+ }
256
+
257
+ .cinecrew-player__panel-heading button,
258
+ .cinecrew-player__chat-form button {
259
+ border: 0;
260
+ border-radius: 8px;
261
+ padding: 8px 12px;
262
+ color: inherit;
263
+ background: rgba(255, 255, 255, .12);
264
+ cursor: pointer;
265
+ }
266
+
267
+ .cinecrew-player__panel-list {
268
+ display: flex;
269
+ flex: 1;
270
+ flex-direction: column;
271
+ gap: 8px;
272
+ min-height: 0;
273
+ overflow: auto;
274
+ }
275
+
276
+ .cinecrew-player__chat-message,
277
+ .cinecrew-player__epg-item {
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: 3px;
281
+ padding: 9px 10px;
282
+ border-radius: 9px;
283
+ background: rgba(255, 255, 255, .06);
284
+ }
285
+
286
+ .cinecrew-player__chat-message strong,
287
+ .cinecrew-player__epg-item strong {
288
+ color: var(--cinecrew-accent);
289
+ }
290
+
291
+ .cinecrew-player__epg-item small,
292
+ .cinecrew-player__panel-state {
293
+ opacity: .75;
294
+ }
295
+
296
+ .cinecrew-player__panel-state.is-error {
297
+ color: #ff647c;
298
+ }
299
+
300
+ .cinecrew-player__chat-form {
301
+ display: flex;
302
+ gap: 8px;
303
+ }
304
+
305
+ .cinecrew-player__chat-form input {
306
+ flex: 1;
307
+ min-width: 0;
308
+ border: 1px solid rgba(255, 255, 255, .16);
309
+ border-radius: 20px;
310
+ padding: 10px 13px;
311
+ color: inherit;
312
+ background: rgba(0, 0, 0, .2);
313
+ font: inherit;
314
+ }
315
+
316
+ .cinecrew-player__chat-form button:disabled {
317
+ opacity: .5;
318
+ cursor: not-allowed;
319
+ }
320
+
321
+ .cinecrew-player__rate {
322
+ max-width: 88px;
323
+ border: 1px solid rgba(255, 255, 255, .18);
324
+ border-radius: 8px;
325
+ padding: 7px 8px;
326
+ color: var(--cinecrew-text);
327
+ background: var(--cinecrew-surface);
328
+ }
329
+
330
+ .cinecrew-player__inline-poster {
331
+ display: grid;
332
+ width: 100%;
333
+ place-items: center;
334
+ border: 0;
335
+ border-radius: 14px;
336
+ overflow: hidden;
337
+ color: #fff;
338
+ background: #07111e;
339
+ font-size: 28px;
340
+ cursor: pointer;
341
+ }
342
+
343
+ .cinecrew-player__inline-poster img {
344
+ width: 100%;
345
+ height: 100%;
346
+ object-fit: cover;
347
+ }
348
+
349
+ .cinecrew-player__menu button:hover {
350
+ background: rgba(255,255,255,.1);
351
+ }
352
+
353
+ .cinecrew-player__panel {
354
+ position: absolute;
355
+ inset: 8% 4% 8% auto;
356
+ z-index: 6;
357
+ width: min(380px, 92%);
358
+ overflow: auto;
359
+ padding: 18px;
360
+ border: 1px solid rgba(255,255,255,.14);
361
+ border-radius: 16px;
362
+ box-shadow: 0 16px 48px rgba(0,0,0,.45);
363
+ }
364
+
365
+ .cinecrew-player__panel-close {
366
+ position: absolute;
367
+ top: 4px;
368
+ right: 6px;
369
+ font-size: 24px;
370
+ }
371
+
372
+ @keyframes cinecrew-spin {
373
+ to { transform: rotate(360deg); }
374
+ }
375
+
376
+ @media (hover: none) {
377
+ .cinecrew-player__controls { opacity: 1; }
378
+ }
@@ -0,0 +1,268 @@
1
+ import type * as React from 'react';
2
+
3
+ export type AspectRatio = 'FIT' | 'FILL' | 'STRETCH' | 'FILL_SCREEN' | string;
4
+ export type PlayerMediaType = 'live' | 'channel' | 'movie' | 'series' | string;
5
+
6
+ export interface PlayerSource {
7
+ /** Local media or a URL the target platform can play. */
8
+ uri?: string;
9
+ /** Alias for `uri`. */
10
+ url?: string;
11
+ title?: string;
12
+ poster?: string;
13
+ posterUrl?: string;
14
+ type?: string;
15
+ mimeType?: string;
16
+ mediaType?: PlayerMediaType;
17
+ isLive?: boolean;
18
+ id?: string | number;
19
+ streamId?: string | number;
20
+ mediaId?: string | number;
21
+ [key: string]: unknown;
22
+ }
23
+
24
+ export interface PlayerControls {
25
+ back?: boolean;
26
+ playPause?: boolean;
27
+ restart?: boolean;
28
+ lock?: boolean;
29
+ mute?: boolean;
30
+ aspectRatio?: boolean;
31
+ videoOnly?: boolean;
32
+ audioOnly?: boolean;
33
+ audioTracks?: boolean;
34
+ playbackRate?: boolean;
35
+ minimize?: boolean;
36
+ fullscreen?: boolean;
37
+ recording?: boolean;
38
+ liveChat?: boolean;
39
+ epg?: boolean;
40
+ seek?: boolean;
41
+ }
42
+
43
+ export interface PlayerApi {
44
+ play(): void;
45
+ pause(): void;
46
+ togglePlayPause(nextPlaying?: boolean): void;
47
+ restart(): void;
48
+ setMuted(muted: boolean): void;
49
+ toggleMute(): void;
50
+ setAspectRatio(ratio: AspectRatio): void;
51
+ setAudioTrack(trackId: string | number): void;
52
+ setAudioOnly(enabled: boolean): void;
53
+ setVideoOnly(enabled: boolean): void;
54
+ seekTo(seconds: number): void;
55
+ seekBy(seconds: number): void;
56
+ back(): void;
57
+ minimize(): void;
58
+ setPlaybackRate(rate: number): void;
59
+ getVideoElement(): unknown | null;
60
+ getAudioTracks(): AudioTrack[];
61
+ enterFullscreen?(): void | Promise<void>;
62
+ exitFullscreen?(): void | Promise<void>;
63
+ }
64
+
65
+ export interface AudioTrack {
66
+ id: string | number;
67
+ name?: string;
68
+ language?: string;
69
+ selected?: boolean;
70
+ enabled?: boolean;
71
+ nativeTrack?: unknown;
72
+ }
73
+
74
+ export interface PlayerActionContext {
75
+ player: PlayerApi | null;
76
+ video?: unknown | null;
77
+ }
78
+
79
+ export type PlayerAction = (payload?: Record<string, unknown>, context?: PlayerActionContext) => unknown;
80
+
81
+ export interface PlayerActions {
82
+ onBack?: PlayerAction;
83
+ onPlayPause?: PlayerAction;
84
+ onSeek?: PlayerAction;
85
+ onRestart?: PlayerAction;
86
+ onLock?: PlayerAction;
87
+ onMute?: PlayerAction;
88
+ onAspectRatioChange?: PlayerAction;
89
+ onVideoOnlyChange?: PlayerAction;
90
+ onAudioOnlyChange?: PlayerAction;
91
+ onAudioTrackChange?: PlayerAction;
92
+ onMinimize?: PlayerAction;
93
+ onPlaybackRateChange?: PlayerAction;
94
+ onFullscreen?: PlayerAction;
95
+ onRecordingStart?: PlayerAction;
96
+ onRecordingPause?: PlayerAction;
97
+ onRecordingResume?: PlayerAction;
98
+ onRecordingStop?: PlayerAction;
99
+ onLiveChatOpen?: PlayerAction;
100
+ onEpgOpen?: PlayerAction;
101
+ onDiagnosticsOpen?: PlayerAction;
102
+ }
103
+
104
+ export interface PlayerTheme {
105
+ /** Shared accent color for controls and active states. */
106
+ accentColor?: string;
107
+ backgroundColor?: string;
108
+ controlBackground?: string;
109
+ controlColor?: string;
110
+ surfaceColor?: string;
111
+ errorColor?: string;
112
+ borderRadius?: number;
113
+ /** React Native palette shape accepted by the native controls. */
114
+ colors?: Record<string, string | number | undefined>;
115
+ [key: string]: unknown;
116
+ }
117
+
118
+ export interface PlayerIconProps {
119
+ name?: string;
120
+ size?: number;
121
+ color?: string;
122
+ style?: unknown;
123
+ }
124
+
125
+ export type PlayerIcon = string | React.ReactNode | React.ComponentType<PlayerIconProps>;
126
+ export type PlayerIcons = Partial<Record<
127
+ | 'play' | 'pause' | 'restart' | 'lock' | 'unlock' | 'mute' | 'unmute'
128
+ | 'aspectRatio' | 'videoOnly' | 'audio' | 'minimize' | 'back'
129
+ | 'recording' | 'stop' | 'liveChat' | 'epg' | 'fullscreen' | 'close'
130
+ | string,
131
+ PlayerIcon
132
+ >>;
133
+
134
+ export interface ChatMessage {
135
+ id?: string | number;
136
+ username?: string;
137
+ comment?: string;
138
+ message?: string;
139
+ createdAt?: string | number;
140
+ [key: string]: unknown;
141
+ }
142
+
143
+ export interface EpgListing {
144
+ title?: string;
145
+ description?: string;
146
+ startMs: number;
147
+ endMs: number;
148
+ [key: string]: unknown;
149
+ }
150
+
151
+ export interface PlayerIntegrations {
152
+ user?: { id?: string | number; username?: string };
153
+ getUser?: () => Promise<{ id?: string | number; username?: string } | null>;
154
+ liveChat?: {
155
+ loadMessages?: (args: { channelId: string; limit: number }) => Promise<ChatMessage[]>;
156
+ sendMessage?: (args: { channelId: string; userId?: string | number; username?: string; comment: string }) => Promise<unknown>;
157
+ pollIntervalMs?: number;
158
+ render?: (context: { title: string; source: PlayerSource; onClose: () => void }) => React.ReactNode;
159
+ };
160
+ epg?: {
161
+ loadListings?: (args: { channelId: string | number; limit: number }) => Promise<EpgListing[]>;
162
+ limit?: number;
163
+ render?: (context: { title: string; source: PlayerSource; onClose: () => void }) => React.ReactNode;
164
+ };
165
+ recording?: {
166
+ start?: (args: { getVideoElement: () => unknown | null; streamUrl: string; title?: string }) => Promise<unknown>;
167
+ pause?: () => Promise<unknown>;
168
+ resume?: () => Promise<unknown>;
169
+ stop?: () => Promise<{ filename?: string } | unknown>;
170
+ isActive?: () => boolean;
171
+ subscribe?: (listener: (state: { status: string; elapsedMs: number }) => void) => (() => void) | void;
172
+ };
173
+ onEvent?: (event: { name: string; payload?: Record<string, unknown> }) => unknown;
174
+ onProgress?: (progress: Record<string, unknown>) => unknown;
175
+ onPresence?: (presence: { online: boolean; title: string; mediaType: string; mediaId?: string | number | null }) => unknown;
176
+ onSleepTimerExpired?: (callback: () => void) => (() => void) | void;
177
+ }
178
+
179
+ export interface CineCrewPlayerProps {
180
+ source?: string | PlayerSource;
181
+ /** Alias for `source`. */
182
+ url?: string;
183
+ title?: string;
184
+ poster?: string;
185
+ posterUrl?: string;
186
+ mediaType?: PlayerMediaType;
187
+ isLive?: boolean;
188
+ visible?: boolean;
189
+ autoPlay?: boolean;
190
+ /** Initial paused state; changes are observed by the web player and on source changes natively. */
191
+ paused?: boolean;
192
+ muted?: boolean;
193
+ audioOnly?: boolean;
194
+ /** Volume is normalized from 0 (silent) to 1 (full). */
195
+ volume?: number;
196
+ playbackRate?: number;
197
+ controls?: PlayerControls;
198
+ features?: { diagnostics?: boolean; [key: string]: boolean | undefined };
199
+ actions?: PlayerActions;
200
+ integrations?: PlayerIntegrations;
201
+ theme?: PlayerTheme;
202
+ icons?: PlayerIcons;
203
+ style?: unknown;
204
+ className?: string;
205
+ videoOnly?: boolean;
206
+ /** Optional resolver for share pages or other non-media links. */
207
+ resolveSource?: (source: PlayerSource, context: { platform: 'web' | 'native' | 'electron' }) => PlayerSource | string | Promise<PlayerSource | string>;
208
+ audioTracks?: AudioTrack[];
209
+ selectedAudioTrack?: string | number;
210
+ resumePosition?: number;
211
+ durationSecs?: number;
212
+ mediaId?: string | number;
213
+ episodeLabel?: string;
214
+ season?: number;
215
+ episode?: number;
216
+ genre?: string;
217
+ categoryName?: string;
218
+ playlist?: Array<Record<string, unknown>>;
219
+ shuffle?: boolean;
220
+ onClose?: () => void;
221
+ onBack?: () => void;
222
+ onMinimize?: () => void;
223
+ onFullscreen?: (state: { isFullscreen: boolean }) => void;
224
+ onPlayerHostRef?: (node: unknown | null) => void;
225
+ onInlinePreviewWheel?: (deltaY: number) => void;
226
+ inlinePreview?: boolean;
227
+ inlinePreviewRect?: { x: number; y: number; width: number; height: number };
228
+ onPromotePreview?: () => void;
229
+ initialShowLiveChat?: boolean;
230
+ liveChatNonce?: number;
231
+ onReady?: (playerOrEvent: unknown) => void;
232
+ onProgress?: (event: unknown) => void;
233
+ onPlaying?: (event: unknown) => void;
234
+ onBuffering?: (buffering: boolean) => void;
235
+ onError?: (error: Error | Record<string, unknown>) => void;
236
+ onEnded?: () => void;
237
+ onPlaybackRoute?: (url: string) => void;
238
+ onNextEpisode?: (episode: Record<string, unknown>) => void;
239
+ onCwRefresh?: () => void;
240
+ renderLiveChat?: PlayerIntegrations['liveChat'] extends infer T ? T extends { render?: infer R } ? R : never : never;
241
+ renderEpg?: PlayerIntegrations['epg'] extends infer T ? T extends { render?: infer R } ? R : never : never;
242
+ }
243
+
244
+ export interface InlineLivePlayerProps {
245
+ source?: string | PlayerSource;
246
+ url?: string;
247
+ title?: string;
248
+ height?: number;
249
+ poster?: string;
250
+ posterChannel?: Record<string, unknown>;
251
+ paused?: boolean;
252
+ isActive?: boolean;
253
+ onActivate?: () => void;
254
+ onFullscreen?: () => void;
255
+ controls?: Pick<PlayerControls, 'playPause' | 'mute' | 'fullscreen'>;
256
+ actions?: Pick<PlayerActions, 'onPlayPause' | 'onMute' | 'onFullscreen'>;
257
+ theme?: PlayerTheme;
258
+ icons?: PlayerIcons;
259
+ style?: unknown;
260
+ initialMuted?: boolean;
261
+ onError?: (error: Error | Record<string, unknown>) => void;
262
+ onPlaying?: (event: unknown) => void;
263
+ }
264
+
265
+ export const CineCrewPlayer: React.ForwardRefExoticComponent<CineCrewPlayerProps & React.RefAttributes<PlayerApi>>;
266
+ export const InlineLivePlayer: React.MemoExoticComponent<React.FC<InlineLivePlayerProps>>;
267
+ export const PlayerCustomizationProvider: React.FC<{ icons?: PlayerIcons; theme?: PlayerTheme; children?: React.ReactNode }>;
268
+ export default CineCrewPlayer;