@livepeer-frameworks/player-core 0.0.3
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/dist/cjs/index.js +19493 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +19398 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/player.css +2140 -0
- package/dist/types/core/ABRController.d.ts +164 -0
- package/dist/types/core/CodecUtils.d.ts +54 -0
- package/dist/types/core/Disposable.d.ts +61 -0
- package/dist/types/core/EventEmitter.d.ts +73 -0
- package/dist/types/core/GatewayClient.d.ts +144 -0
- package/dist/types/core/InteractionController.d.ts +121 -0
- package/dist/types/core/LiveDurationProxy.d.ts +102 -0
- package/dist/types/core/MetaTrackManager.d.ts +220 -0
- package/dist/types/core/MistReporter.d.ts +163 -0
- package/dist/types/core/MistSignaling.d.ts +148 -0
- package/dist/types/core/PlayerController.d.ts +665 -0
- package/dist/types/core/PlayerInterface.d.ts +230 -0
- package/dist/types/core/PlayerManager.d.ts +182 -0
- package/dist/types/core/PlayerRegistry.d.ts +27 -0
- package/dist/types/core/QualityMonitor.d.ts +184 -0
- package/dist/types/core/ScreenWakeLockManager.d.ts +70 -0
- package/dist/types/core/SeekingUtils.d.ts +142 -0
- package/dist/types/core/StreamStateClient.d.ts +108 -0
- package/dist/types/core/SubtitleManager.d.ts +111 -0
- package/dist/types/core/TelemetryReporter.d.ts +79 -0
- package/dist/types/core/TimeFormat.d.ts +97 -0
- package/dist/types/core/TimerManager.d.ts +83 -0
- package/dist/types/core/UrlUtils.d.ts +81 -0
- package/dist/types/core/detector.d.ts +149 -0
- package/dist/types/core/index.d.ts +49 -0
- package/dist/types/core/scorer.d.ts +167 -0
- package/dist/types/core/selector.d.ts +9 -0
- package/dist/types/index.d.ts +45 -0
- package/dist/types/lib/utils.d.ts +2 -0
- package/dist/types/players/DashJsPlayer.d.ts +102 -0
- package/dist/types/players/HlsJsPlayer.d.ts +70 -0
- package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +119 -0
- package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +60 -0
- package/dist/types/players/MewsWsPlayer/index.d.ts +220 -0
- package/dist/types/players/MewsWsPlayer/types.d.ts +89 -0
- package/dist/types/players/MistPlayer.d.ts +25 -0
- package/dist/types/players/MistWebRTCPlayer/index.d.ts +133 -0
- package/dist/types/players/NativePlayer.d.ts +143 -0
- package/dist/types/players/VideoJsPlayer.d.ts +59 -0
- package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +118 -0
- package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +64 -0
- package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +63 -0
- package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +174 -0
- package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +164 -0
- package/dist/types/players/WebCodecsPlayer/index.d.ts +149 -0
- package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +105 -0
- package/dist/types/players/WebCodecsPlayer/types.d.ts +395 -0
- package/dist/types/players/WebCodecsPlayer/worker/decoder.worker.d.ts +13 -0
- package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +197 -0
- package/dist/types/players/index.d.ts +14 -0
- package/dist/types/styles/index.d.ts +11 -0
- package/dist/types/types.d.ts +363 -0
- package/dist/types/vanilla/FrameWorksPlayer.d.ts +143 -0
- package/dist/types/vanilla/index.d.ts +19 -0
- package/dist/workers/decoder.worker.js +989 -0
- package/dist/workers/decoder.worker.js.map +1 -0
- package/package.json +80 -0
- package/src/core/ABRController.ts +550 -0
- package/src/core/CodecUtils.ts +257 -0
- package/src/core/Disposable.ts +120 -0
- package/src/core/EventEmitter.ts +113 -0
- package/src/core/GatewayClient.ts +439 -0
- package/src/core/InteractionController.ts +712 -0
- package/src/core/LiveDurationProxy.ts +270 -0
- package/src/core/MetaTrackManager.ts +753 -0
- package/src/core/MistReporter.ts +543 -0
- package/src/core/MistSignaling.ts +346 -0
- package/src/core/PlayerController.ts +2829 -0
- package/src/core/PlayerInterface.ts +432 -0
- package/src/core/PlayerManager.ts +900 -0
- package/src/core/PlayerRegistry.ts +149 -0
- package/src/core/QualityMonitor.ts +597 -0
- package/src/core/ScreenWakeLockManager.ts +163 -0
- package/src/core/SeekingUtils.ts +364 -0
- package/src/core/StreamStateClient.ts +457 -0
- package/src/core/SubtitleManager.ts +297 -0
- package/src/core/TelemetryReporter.ts +308 -0
- package/src/core/TimeFormat.ts +205 -0
- package/src/core/TimerManager.ts +209 -0
- package/src/core/UrlUtils.ts +179 -0
- package/src/core/detector.ts +382 -0
- package/src/core/index.ts +140 -0
- package/src/core/scorer.ts +553 -0
- package/src/core/selector.ts +16 -0
- package/src/global.d.ts +11 -0
- package/src/index.ts +75 -0
- package/src/lib/utils.ts +6 -0
- package/src/players/DashJsPlayer.ts +642 -0
- package/src/players/HlsJsPlayer.ts +483 -0
- package/src/players/MewsWsPlayer/SourceBufferManager.ts +572 -0
- package/src/players/MewsWsPlayer/WebSocketManager.ts +241 -0
- package/src/players/MewsWsPlayer/index.ts +1065 -0
- package/src/players/MewsWsPlayer/types.ts +106 -0
- package/src/players/MistPlayer.ts +188 -0
- package/src/players/MistWebRTCPlayer/index.ts +703 -0
- package/src/players/NativePlayer.ts +820 -0
- package/src/players/VideoJsPlayer.ts +643 -0
- package/src/players/WebCodecsPlayer/JitterBuffer.ts +299 -0
- package/src/players/WebCodecsPlayer/LatencyProfiles.ts +151 -0
- package/src/players/WebCodecsPlayer/RawChunkParser.ts +151 -0
- package/src/players/WebCodecsPlayer/SyncController.ts +456 -0
- package/src/players/WebCodecsPlayer/WebSocketController.ts +564 -0
- package/src/players/WebCodecsPlayer/index.ts +1650 -0
- package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +379 -0
- package/src/players/WebCodecsPlayer/types.ts +542 -0
- package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +1360 -0
- package/src/players/WebCodecsPlayer/worker/types.ts +276 -0
- package/src/players/index.ts +22 -0
- package/src/styles/animations.css +21 -0
- package/src/styles/index.ts +52 -0
- package/src/styles/player.css +2126 -0
- package/src/styles/tailwind.css +1015 -0
- package/src/types.ts +421 -0
- package/src/vanilla/FrameWorksPlayer.ts +367 -0
- package/src/vanilla/index.ts +22 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser and Codec Detection
|
|
3
|
+
* Ported from MistMetaPlayer v3.1.0
|
|
4
|
+
*
|
|
5
|
+
* Detects browser capabilities and codec support
|
|
6
|
+
* Removes legacy IE/Flash detection code
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { translateCodec } from './CodecUtils';
|
|
10
|
+
|
|
11
|
+
export interface BrowserInfo {
|
|
12
|
+
isChrome: boolean;
|
|
13
|
+
isFirefox: boolean;
|
|
14
|
+
isSafari: boolean;
|
|
15
|
+
isEdge: boolean;
|
|
16
|
+
isAndroid: boolean;
|
|
17
|
+
isIOS: boolean;
|
|
18
|
+
isMobile: boolean;
|
|
19
|
+
supportsMediaSource: boolean;
|
|
20
|
+
supportsWebRTC: boolean;
|
|
21
|
+
supportsWebSocket: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface CodecSupport {
|
|
25
|
+
h264: boolean;
|
|
26
|
+
h265: boolean;
|
|
27
|
+
vp8: boolean;
|
|
28
|
+
vp9: boolean;
|
|
29
|
+
av1: boolean;
|
|
30
|
+
aac: boolean;
|
|
31
|
+
mp3: boolean;
|
|
32
|
+
opus: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Detect browser information
|
|
37
|
+
*/
|
|
38
|
+
export function getBrowserInfo(): BrowserInfo {
|
|
39
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
isChrome: /chrome|crios/.test(ua) && !/edge|edg/.test(ua),
|
|
43
|
+
isFirefox: /firefox/.test(ua),
|
|
44
|
+
isSafari: /safari/.test(ua) && !/chrome|crios/.test(ua),
|
|
45
|
+
isEdge: /edge|edg/.test(ua),
|
|
46
|
+
isAndroid: /android/.test(ua),
|
|
47
|
+
isIOS: /iphone|ipad|ipod/.test(ua),
|
|
48
|
+
isMobile: /mobile|android|iphone|ipad|ipod/.test(ua),
|
|
49
|
+
supportsMediaSource: 'MediaSource' in window,
|
|
50
|
+
supportsWebRTC: 'RTCPeerConnection' in window,
|
|
51
|
+
supportsWebSocket: 'WebSocket' in window
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Re-export translateCodec from CodecUtils for backwards compatibility
|
|
56
|
+
export { translateCodec };
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Test codec support using MediaSource API
|
|
60
|
+
*/
|
|
61
|
+
export function testCodecSupport(mimeType: string, codec: string): boolean {
|
|
62
|
+
if (!('MediaSource' in window)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!MediaSource.isTypeSupported) {
|
|
67
|
+
return true; // Can't test, assume it works
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const fullType = `${mimeType};codecs="${codec}"`;
|
|
71
|
+
return MediaSource.isTypeSupported(fullType);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get comprehensive codec support info
|
|
76
|
+
*/
|
|
77
|
+
export function getCodecSupport(): CodecSupport {
|
|
78
|
+
return {
|
|
79
|
+
h264: testCodecSupport('video/mp4', 'avc1.42E01E'),
|
|
80
|
+
h265: testCodecSupport('video/mp4', 'hev1.1.6.L93.90'),
|
|
81
|
+
vp8: testCodecSupport('video/webm', 'vp8'),
|
|
82
|
+
vp9: testCodecSupport('video/webm', 'vp09.00.10.08'),
|
|
83
|
+
av1: testCodecSupport('video/mp4', 'av01.0.04M.08'),
|
|
84
|
+
aac: testCodecSupport('video/mp4', 'mp4a.40.2'),
|
|
85
|
+
mp3: testCodecSupport('audio/mpeg', 'mp3'),
|
|
86
|
+
opus: testCodecSupport('audio/webm', 'opus')
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Check if tracks are playable by testing codecs
|
|
92
|
+
*/
|
|
93
|
+
export function checkTrackPlayability(
|
|
94
|
+
tracks: Array<{ type: string; codec: string; codecstring?: string; init?: string }>,
|
|
95
|
+
containerType: string
|
|
96
|
+
): { playable: string[]; supported: string[] } {
|
|
97
|
+
const playable: string[] = [];
|
|
98
|
+
const supported: string[] = [];
|
|
99
|
+
|
|
100
|
+
const tracksByType: Record<string, typeof tracks> = {};
|
|
101
|
+
|
|
102
|
+
// Group tracks by type
|
|
103
|
+
for (const track of tracks) {
|
|
104
|
+
if (track.type === 'meta') continue;
|
|
105
|
+
|
|
106
|
+
if (!tracksByType[track.type]) {
|
|
107
|
+
tracksByType[track.type] = [];
|
|
108
|
+
}
|
|
109
|
+
tracksByType[track.type].push(track);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Test each track type
|
|
113
|
+
for (const [trackType, typeTracks] of Object.entries(tracksByType)) {
|
|
114
|
+
let hasPlayableTrack = false;
|
|
115
|
+
|
|
116
|
+
for (const track of typeTracks) {
|
|
117
|
+
const codecString = translateCodec(track);
|
|
118
|
+
if (testCodecSupport(containerType, codecString)) {
|
|
119
|
+
supported.push(track.codec);
|
|
120
|
+
hasPlayableTrack = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (hasPlayableTrack) {
|
|
125
|
+
playable.push(trackType);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { playable, supported };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check protocol/scheme mismatch (http/https)
|
|
134
|
+
*/
|
|
135
|
+
export function checkProtocolMismatch(sourceUrl: string): boolean {
|
|
136
|
+
const pageProtocol = window.location.protocol;
|
|
137
|
+
const sourceProtocol = new URL(sourceUrl).protocol;
|
|
138
|
+
|
|
139
|
+
// Allow file:// to access http://
|
|
140
|
+
if (pageProtocol === 'file:' && sourceProtocol === 'http:') {
|
|
141
|
+
return false; // No mismatch
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return pageProtocol !== sourceProtocol;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Check if current page is loaded over file://
|
|
149
|
+
*/
|
|
150
|
+
export function isFileProtocol(): boolean {
|
|
151
|
+
return window.location.protocol === 'file:';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get Android version (returns null if not Android)
|
|
156
|
+
*/
|
|
157
|
+
export function getAndroidVersion(): number | null {
|
|
158
|
+
const match = navigator.userAgent.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);
|
|
159
|
+
if (!match) return null;
|
|
160
|
+
|
|
161
|
+
const major = parseInt(match[1], 10);
|
|
162
|
+
const minor = match[2] ? parseInt(match[2], 10) : 0;
|
|
163
|
+
|
|
164
|
+
return major + (minor / 10);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Browser-specific compatibility checks
|
|
169
|
+
*/
|
|
170
|
+
export function getBrowserCompatibility() {
|
|
171
|
+
const browser = getBrowserInfo();
|
|
172
|
+
const android = getAndroidVersion();
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
// Native HLS support
|
|
176
|
+
supportsNativeHLS: browser.isSafari || browser.isIOS || (android && android >= 7),
|
|
177
|
+
|
|
178
|
+
// MSE support
|
|
179
|
+
supportsMSE: browser.supportsMediaSource,
|
|
180
|
+
|
|
181
|
+
// WebSocket support
|
|
182
|
+
supportsWebSocket: browser.supportsWebSocket,
|
|
183
|
+
|
|
184
|
+
// WebRTC support
|
|
185
|
+
supportsWebRTC: browser.supportsWebRTC && 'RTCRtpReceiver' in window,
|
|
186
|
+
|
|
187
|
+
// Specific player recommendations
|
|
188
|
+
preferVideoJs: android && android < 7, // VideoJS better for older Android
|
|
189
|
+
avoidMEWSOnMac: browser.isSafari, // MEWS breaks often on Safari/macOS
|
|
190
|
+
|
|
191
|
+
// File protocol limitations
|
|
192
|
+
fileProtocolLimitations: isFileProtocol()
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// WebRTC Codec Compatibility
|
|
198
|
+
// ============================================================================
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Codecs that are compatible with WebRTC (WHEP/MistServer native)
|
|
202
|
+
* These are the only codecs that can be used in RTP streams
|
|
203
|
+
*/
|
|
204
|
+
export const WEBRTC_COMPATIBLE_CODECS = {
|
|
205
|
+
video: ['H264', 'VP8', 'VP9', 'AV1'],
|
|
206
|
+
// Note: AAC is NOT natively supported in browser WebRTC - OPUS is standard
|
|
207
|
+
// MistServer may transcode to OPUS for WebRTC output
|
|
208
|
+
audio: ['OPUS', 'PCMU', 'PCMA', 'G711', 'G722'],
|
|
209
|
+
} as const;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Codecs that are explicitly incompatible with WebRTC
|
|
213
|
+
*/
|
|
214
|
+
export const WEBRTC_INCOMPATIBLE_CODECS = {
|
|
215
|
+
video: ['HEVC', 'H265', 'THEORA', 'MPEG2'],
|
|
216
|
+
audio: ['AC3', 'EAC3', 'EC3', 'MP3', 'FLAC', 'VORBIS', 'DTS'],
|
|
217
|
+
} as const;
|
|
218
|
+
|
|
219
|
+
export interface WebRTCCodecCompatibility {
|
|
220
|
+
/** Whether at least one video track is WebRTC-compatible */
|
|
221
|
+
videoCompatible: boolean;
|
|
222
|
+
/** Whether at least one audio track is WebRTC-compatible (or no audio tracks) */
|
|
223
|
+
audioCompatible: boolean;
|
|
224
|
+
/** Overall compatibility - both video and audio must be compatible */
|
|
225
|
+
compatible: boolean;
|
|
226
|
+
/** List of incompatible codecs found */
|
|
227
|
+
incompatibleCodecs: string[];
|
|
228
|
+
/** Detailed breakdown per track type */
|
|
229
|
+
details: {
|
|
230
|
+
videoTracks: number;
|
|
231
|
+
audioTracks: number;
|
|
232
|
+
compatibleVideoCodecs: string[];
|
|
233
|
+
compatibleAudioCodecs: string[];
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Check if browser supports a codec via WebRTC
|
|
239
|
+
* Uses RTCRtpReceiver.getCapabilities() for dynamic browser detection (reference: webrtc.js:38-46)
|
|
240
|
+
* Falls back to static list if API unavailable
|
|
241
|
+
*/
|
|
242
|
+
function isBrowserWebRTCCodecSupported(type: 'video' | 'audio', codec: string): boolean {
|
|
243
|
+
// Try dynamic browser API first (reference: webrtc.js:39)
|
|
244
|
+
if (typeof RTCRtpReceiver !== 'undefined' && RTCRtpReceiver.getCapabilities) {
|
|
245
|
+
try {
|
|
246
|
+
const capabilities = RTCRtpReceiver.getCapabilities(type);
|
|
247
|
+
if (capabilities?.codecs) {
|
|
248
|
+
const targetMime = `${type}/${codec}`.toLowerCase();
|
|
249
|
+
return capabilities.codecs.some(c => c.mimeType.toLowerCase() === targetMime);
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
// Fall through to static list
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Fallback to static list for older browsers/SSR
|
|
257
|
+
const compatibleCodecs = WEBRTC_COMPATIBLE_CODECS[type] as readonly string[];
|
|
258
|
+
return compatibleCodecs.includes(codec.toUpperCase());
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check if stream tracks are compatible with WebRTC playback
|
|
263
|
+
*
|
|
264
|
+
* Uses RTCRtpReceiver.getCapabilities() to dynamically query browser support,
|
|
265
|
+
* matching the reference MistServer implementation (webrtc.js:38-46).
|
|
266
|
+
*
|
|
267
|
+
* @param tracks - Array of track metadata from MistServer
|
|
268
|
+
* @returns Compatibility assessment
|
|
269
|
+
*/
|
|
270
|
+
export function checkWebRTCCodecCompatibility(
|
|
271
|
+
tracks: Array<{ type: string; codec: string }>
|
|
272
|
+
): WebRTCCodecCompatibility {
|
|
273
|
+
const videoTracks = tracks.filter(t => t.type === 'video');
|
|
274
|
+
const audioTracks = tracks.filter(t => t.type === 'audio');
|
|
275
|
+
|
|
276
|
+
const compatibleVideoCodecs: string[] = [];
|
|
277
|
+
const compatibleAudioCodecs: string[] = [];
|
|
278
|
+
const incompatibleCodecs: string[] = [];
|
|
279
|
+
|
|
280
|
+
// Check video tracks using dynamic browser detection
|
|
281
|
+
for (const track of videoTracks) {
|
|
282
|
+
if (isBrowserWebRTCCodecSupported('video', track.codec)) {
|
|
283
|
+
compatibleVideoCodecs.push(track.codec);
|
|
284
|
+
} else {
|
|
285
|
+
incompatibleCodecs.push(`video:${track.codec}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Check audio tracks using dynamic browser detection
|
|
290
|
+
for (const track of audioTracks) {
|
|
291
|
+
if (isBrowserWebRTCCodecSupported('audio', track.codec)) {
|
|
292
|
+
compatibleAudioCodecs.push(track.codec);
|
|
293
|
+
} else {
|
|
294
|
+
incompatibleCodecs.push(`audio:${track.codec}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Video is compatible if there's at least one compatible video codec
|
|
299
|
+
// (or no video tracks at all - audio-only streams are fine)
|
|
300
|
+
const videoCompatible = videoTracks.length === 0 || compatibleVideoCodecs.length > 0;
|
|
301
|
+
|
|
302
|
+
// Audio is compatible if there's at least one compatible audio codec
|
|
303
|
+
// (or no audio tracks at all - video-only streams are fine)
|
|
304
|
+
const audioCompatible = audioTracks.length === 0 || compatibleAudioCodecs.length > 0;
|
|
305
|
+
|
|
306
|
+
return {
|
|
307
|
+
videoCompatible,
|
|
308
|
+
audioCompatible,
|
|
309
|
+
compatible: videoCompatible && audioCompatible,
|
|
310
|
+
incompatibleCodecs,
|
|
311
|
+
details: {
|
|
312
|
+
videoTracks: videoTracks.length,
|
|
313
|
+
audioTracks: audioTracks.length,
|
|
314
|
+
compatibleVideoCodecs,
|
|
315
|
+
compatibleAudioCodecs,
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// MSE Codec Compatibility (for HLS.js, DASH.js)
|
|
322
|
+
// ============================================================================
|
|
323
|
+
|
|
324
|
+
export interface MSECodecCompatibility {
|
|
325
|
+
/** Whether at least one video track is MSE-compatible in this browser */
|
|
326
|
+
videoCompatible: boolean;
|
|
327
|
+
/** Whether at least one audio track is MSE-compatible in this browser */
|
|
328
|
+
audioCompatible: boolean;
|
|
329
|
+
/** Overall compatibility */
|
|
330
|
+
compatible: boolean;
|
|
331
|
+
/** Codecs that failed browser support test */
|
|
332
|
+
unsupportedCodecs: string[];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Check if stream tracks are compatible with MSE playback in this browser
|
|
337
|
+
*
|
|
338
|
+
* Unlike WebRTC, MSE compatibility varies by browser. HEVC works in Safari
|
|
339
|
+
* but not Firefox. This function actually tests MediaSource.isTypeSupported().
|
|
340
|
+
*
|
|
341
|
+
* @param tracks - Array of track metadata
|
|
342
|
+
* @param containerType - MIME type (e.g., 'video/mp4')
|
|
343
|
+
*/
|
|
344
|
+
export function checkMSECodecCompatibility(
|
|
345
|
+
tracks: Array<{ type: string; codec: string; codecstring?: string; init?: string }>,
|
|
346
|
+
containerType = 'video/mp4'
|
|
347
|
+
): MSECodecCompatibility {
|
|
348
|
+
const videoTracks = tracks.filter(t => t.type === 'video');
|
|
349
|
+
const audioTracks = tracks.filter(t => t.type === 'audio');
|
|
350
|
+
const unsupportedCodecs: string[] = [];
|
|
351
|
+
|
|
352
|
+
let hasCompatibleVideo = videoTracks.length === 0;
|
|
353
|
+
let hasCompatibleAudio = audioTracks.length === 0;
|
|
354
|
+
|
|
355
|
+
// Test each video track
|
|
356
|
+
for (const track of videoTracks) {
|
|
357
|
+
const codecString = translateCodec(track);
|
|
358
|
+
if (testCodecSupport(containerType, codecString)) {
|
|
359
|
+
hasCompatibleVideo = true;
|
|
360
|
+
} else {
|
|
361
|
+
unsupportedCodecs.push(`video:${track.codec}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Test each audio track
|
|
366
|
+
for (const track of audioTracks) {
|
|
367
|
+
const codecString = translateCodec(track);
|
|
368
|
+
const audioContainer = track.codec === 'MP3' ? 'audio/mpeg' : containerType;
|
|
369
|
+
if (testCodecSupport(audioContainer, codecString)) {
|
|
370
|
+
hasCompatibleAudio = true;
|
|
371
|
+
} else {
|
|
372
|
+
unsupportedCodecs.push(`audio:${track.codec}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
videoCompatible: hasCompatibleVideo,
|
|
378
|
+
audioCompatible: hasCompatibleAudio,
|
|
379
|
+
compatible: hasCompatibleVideo && hasCompatibleAudio,
|
|
380
|
+
unsupportedCodecs,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Player Management System
|
|
3
|
+
*
|
|
4
|
+
* Exports all core functionality for the FrameWorks player system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Browser and codec detection
|
|
8
|
+
export * from './detector';
|
|
9
|
+
|
|
10
|
+
// Scoring system
|
|
11
|
+
export * from './scorer';
|
|
12
|
+
|
|
13
|
+
// Player interfaces and base classes
|
|
14
|
+
export * from './PlayerInterface';
|
|
15
|
+
|
|
16
|
+
// Main player manager (single source of truth for selection)
|
|
17
|
+
export {
|
|
18
|
+
PlayerManager,
|
|
19
|
+
type PlayerSelection,
|
|
20
|
+
type PlayerCombination,
|
|
21
|
+
type PlayerManagerOptions,
|
|
22
|
+
type PlayerManagerEvents,
|
|
23
|
+
} from './PlayerManager';
|
|
24
|
+
|
|
25
|
+
// Player registry with all implementations
|
|
26
|
+
export * from './PlayerRegistry';
|
|
27
|
+
|
|
28
|
+
// Re-export for convenience
|
|
29
|
+
export { globalPlayerManager, createPlayerManager, ensurePlayersRegistered } from './PlayerRegistry';
|
|
30
|
+
export type { IPlayer, PlayerOptions } from './PlayerInterface';
|
|
31
|
+
|
|
32
|
+
// New core classes (MistMetaPlayer feature backport)
|
|
33
|
+
export { QualityMonitor, PROTOCOL_THRESHOLDS } from './QualityMonitor';
|
|
34
|
+
export type { QualityMonitorOptions, QualityMonitorState, PlayerProtocol } from './QualityMonitor';
|
|
35
|
+
export { TelemetryReporter } from './TelemetryReporter';
|
|
36
|
+
export type { TelemetryReporterConfig } from './TelemetryReporter';
|
|
37
|
+
export { ABRController } from './ABRController';
|
|
38
|
+
export type { ABRControllerConfig, ABRDecision } from './ABRController';
|
|
39
|
+
export { MetaTrackManager } from './MetaTrackManager';
|
|
40
|
+
export type { MetaTrackManagerConfig, MetaTrackSubscription } from './MetaTrackManager';
|
|
41
|
+
|
|
42
|
+
// Headless core classes (framework-agnostic)
|
|
43
|
+
export { TypedEventEmitter } from './EventEmitter';
|
|
44
|
+
export { GatewayClient } from './GatewayClient';
|
|
45
|
+
export type { GatewayClientConfig, GatewayClientEvents, GatewayStatus } from './GatewayClient';
|
|
46
|
+
export { StreamStateClient } from './StreamStateClient';
|
|
47
|
+
export type { StreamStateClientConfig, StreamStateClientEvents } from './StreamStateClient';
|
|
48
|
+
export {
|
|
49
|
+
PlayerController,
|
|
50
|
+
buildStreamInfoFromEndpoints,
|
|
51
|
+
MIST_SOURCE_TYPES,
|
|
52
|
+
PROTOCOL_TO_MIME,
|
|
53
|
+
getMimeTypeForProtocol,
|
|
54
|
+
getSourceTypeInfo,
|
|
55
|
+
} from './PlayerController';
|
|
56
|
+
export type { PlayerControllerConfig, PlayerControllerEvents } from './PlayerController';
|
|
57
|
+
|
|
58
|
+
// MistServer reporting (MistMetaPlayer feature backport)
|
|
59
|
+
export { MistReporter } from './MistReporter';
|
|
60
|
+
export type { MistReporterStats, MistReporterOptions, MistReporterInitialReport } from './MistReporter';
|
|
61
|
+
|
|
62
|
+
// MistServer WebRTC signaling (MistMetaPlayer feature backport)
|
|
63
|
+
export { MistSignaling } from './MistSignaling';
|
|
64
|
+
export type { MistSignalingConfig, MistSignalingEvents, MistTimeUpdate, MistSignalingState } from './MistSignaling';
|
|
65
|
+
|
|
66
|
+
// Live duration handling for live streams
|
|
67
|
+
export { LiveDurationProxy, createLiveVideoProxy } from './LiveDurationProxy';
|
|
68
|
+
export type { LiveDurationProxyOptions, LiveDurationState } from './LiveDurationProxy';
|
|
69
|
+
|
|
70
|
+
// Timer management for memory leak prevention
|
|
71
|
+
export { TimerManager } from './TimerManager';
|
|
72
|
+
|
|
73
|
+
// Disposable interface for consistent cleanup
|
|
74
|
+
export { BaseDisposable, disposeAll, createCompositeDisposable } from './Disposable';
|
|
75
|
+
export type { Disposable } from './Disposable';
|
|
76
|
+
|
|
77
|
+
// URL utilities (MistMetaPlayer feature backport)
|
|
78
|
+
export {
|
|
79
|
+
appendUrlParams,
|
|
80
|
+
parseUrlParams,
|
|
81
|
+
stripUrlParams,
|
|
82
|
+
buildUrl,
|
|
83
|
+
isSecureUrl,
|
|
84
|
+
httpToWs,
|
|
85
|
+
wsToHttp,
|
|
86
|
+
matchPageProtocol,
|
|
87
|
+
} from './UrlUtils';
|
|
88
|
+
|
|
89
|
+
// Codec utilities (MistMetaPlayer feature backport)
|
|
90
|
+
export {
|
|
91
|
+
translateCodec,
|
|
92
|
+
isCodecSupported,
|
|
93
|
+
getBestSupportedTrack,
|
|
94
|
+
} from './CodecUtils';
|
|
95
|
+
export type { TrackInfo } from './CodecUtils';
|
|
96
|
+
|
|
97
|
+
// Subtitle management (MistMetaPlayer feature backport)
|
|
98
|
+
export { SubtitleManager } from './SubtitleManager';
|
|
99
|
+
export type { SubtitleTrackInfo, SubtitleManagerConfig } from './SubtitleManager';
|
|
100
|
+
|
|
101
|
+
// Interaction controller for modern player gestures + keyboard (VOD/Clip features)
|
|
102
|
+
export { InteractionController } from './InteractionController';
|
|
103
|
+
export type { InteractionControllerConfig, InteractionState } from './InteractionController';
|
|
104
|
+
|
|
105
|
+
// Screen Wake Lock for preventing device sleep during video playback
|
|
106
|
+
export { ScreenWakeLockManager } from './ScreenWakeLockManager';
|
|
107
|
+
export type { ScreenWakeLockConfig } from './ScreenWakeLockManager';
|
|
108
|
+
|
|
109
|
+
// Seeking utilities - centralized seeking/live detection logic
|
|
110
|
+
export {
|
|
111
|
+
LATENCY_TIERS,
|
|
112
|
+
SPEED_PRESETS,
|
|
113
|
+
DEFAULT_BUFFER_WINDOW_SEC,
|
|
114
|
+
getLatencyTier,
|
|
115
|
+
isMediaStreamSource,
|
|
116
|
+
supportsPlaybackRate,
|
|
117
|
+
calculateSeekableRange,
|
|
118
|
+
canSeekStream,
|
|
119
|
+
calculateLiveThresholds,
|
|
120
|
+
calculateIsNearLive,
|
|
121
|
+
isLiveContent,
|
|
122
|
+
} from './SeekingUtils';
|
|
123
|
+
export type {
|
|
124
|
+
LatencyTier,
|
|
125
|
+
LiveThresholds,
|
|
126
|
+
SeekableRange,
|
|
127
|
+
SeekableRangeParams,
|
|
128
|
+
CanSeekParams,
|
|
129
|
+
} from './SeekingUtils';
|
|
130
|
+
|
|
131
|
+
// Time formatting utilities
|
|
132
|
+
export {
|
|
133
|
+
formatTime,
|
|
134
|
+
formatClockTime,
|
|
135
|
+
formatTimeDisplay,
|
|
136
|
+
formatTooltipTime,
|
|
137
|
+
formatDuration,
|
|
138
|
+
parseTime,
|
|
139
|
+
} from './TimeFormat';
|
|
140
|
+
export type { TimeDisplayParams } from './TimeFormat';
|