@livepeer-frameworks/player-core 0.0.4 → 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.
- package/README.md +21 -6
- package/dist/cjs/index.js +792 -146
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +792 -146
- package/dist/esm/index.js.map +1 -1
- package/dist/player.css +185 -373
- package/dist/types/core/GatewayClient.d.ts +3 -4
- package/dist/types/core/InteractionController.d.ts +12 -0
- package/dist/types/core/MetaTrackManager.d.ts +1 -1
- package/dist/types/core/PlayerController.d.ts +18 -2
- package/dist/types/core/PlayerInterface.d.ts +10 -0
- package/dist/types/core/SeekingUtils.d.ts +3 -1
- package/dist/types/core/StreamStateClient.d.ts +1 -1
- package/dist/types/players/HlsJsPlayer.d.ts +8 -0
- package/dist/types/players/MewsWsPlayer/index.d.ts +1 -1
- package/dist/types/players/VideoJsPlayer.d.ts +12 -4
- package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +1 -1
- package/dist/types/players/WebCodecsPlayer/index.d.ts +11 -0
- package/dist/types/players/WebCodecsPlayer/types.d.ts +25 -3
- package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +20 -2
- package/dist/types/types.d.ts +32 -1
- package/dist/types/vanilla/FrameWorksPlayer.d.ts +5 -5
- package/dist/types/vanilla/index.d.ts +3 -3
- package/dist/workers/decoder.worker.js +183 -6
- package/dist/workers/decoder.worker.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ABRController.ts +38 -36
- package/src/core/CodecUtils.ts +50 -47
- package/src/core/Disposable.ts +4 -4
- package/src/core/EventEmitter.ts +1 -1
- package/src/core/GatewayClient.ts +48 -48
- package/src/core/InteractionController.ts +89 -82
- package/src/core/LiveDurationProxy.ts +14 -16
- package/src/core/MetaTrackManager.ts +74 -66
- package/src/core/MistReporter.ts +72 -45
- package/src/core/MistSignaling.ts +59 -56
- package/src/core/PlayerController.ts +724 -375
- package/src/core/PlayerInterface.ts +89 -59
- package/src/core/PlayerManager.ts +118 -123
- package/src/core/PlayerRegistry.ts +59 -42
- package/src/core/QualityMonitor.ts +38 -31
- package/src/core/ScreenWakeLockManager.ts +8 -9
- package/src/core/SeekingUtils.ts +31 -22
- package/src/core/StreamStateClient.ts +75 -69
- package/src/core/SubtitleManager.ts +25 -23
- package/src/core/TelemetryReporter.ts +34 -31
- package/src/core/TimeFormat.ts +13 -17
- package/src/core/TimerManager.ts +25 -9
- package/src/core/UrlUtils.ts +20 -17
- package/src/core/detector.ts +44 -44
- package/src/core/index.ts +57 -48
- package/src/core/scorer.ts +137 -138
- package/src/core/selector.ts +2 -6
- package/src/global.d.ts +1 -1
- package/src/index.ts +46 -35
- package/src/players/DashJsPlayer.ts +175 -114
- package/src/players/HlsJsPlayer.ts +154 -76
- package/src/players/MewsWsPlayer/SourceBufferManager.ts +44 -39
- package/src/players/MewsWsPlayer/WebSocketManager.ts +9 -10
- package/src/players/MewsWsPlayer/index.ts +196 -154
- package/src/players/MewsWsPlayer/types.ts +21 -21
- package/src/players/MistPlayer.ts +46 -27
- package/src/players/MistWebRTCPlayer/index.ts +175 -129
- package/src/players/NativePlayer.ts +203 -143
- package/src/players/VideoJsPlayer.ts +200 -146
- package/src/players/WebCodecsPlayer/JitterBuffer.ts +6 -7
- package/src/players/WebCodecsPlayer/LatencyProfiles.ts +43 -43
- package/src/players/WebCodecsPlayer/RawChunkParser.ts +10 -10
- package/src/players/WebCodecsPlayer/SyncController.ts +46 -55
- package/src/players/WebCodecsPlayer/WebSocketController.ts +67 -69
- package/src/players/WebCodecsPlayer/index.ts +280 -220
- package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +12 -17
- package/src/players/WebCodecsPlayer/types.ts +81 -53
- package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +255 -192
- package/src/players/WebCodecsPlayer/worker/types.ts +33 -29
- package/src/players/index.ts +8 -8
- package/src/styles/animations.css +2 -1
- package/src/styles/player.css +182 -356
- package/src/styles/tailwind.css +473 -159
- package/src/types.ts +75 -33
- package/src/vanilla/FrameWorksPlayer.ts +34 -19
- package/src/vanilla/index.ts +7 -7
|
@@ -10,10 +10,10 @@ export type GatewayStatus = 'idle' | 'loading' | 'ready' | 'error';
|
|
|
10
10
|
export interface GatewayClientConfig {
|
|
11
11
|
/** Gateway GraphQL endpoint URL */
|
|
12
12
|
gatewayUrl: string;
|
|
13
|
-
/** Content type to resolve */
|
|
14
|
-
contentType: ContentType;
|
|
15
13
|
/** Content identifier (stream name) */
|
|
16
14
|
contentId: string;
|
|
15
|
+
/** Optional content type (no longer required for resolution) */
|
|
16
|
+
contentType?: ContentType;
|
|
17
17
|
/** Optional auth token for private streams */
|
|
18
18
|
authToken?: string;
|
|
19
19
|
/** Maximum retry attempts (default: 3) */
|
|
@@ -40,8 +40,7 @@ type CircuitBreakerState = 'closed' | 'open' | 'half-open';
|
|
|
40
40
|
* ```typescript
|
|
41
41
|
* const client = new GatewayClient({
|
|
42
42
|
* gatewayUrl: 'https://gateway.example.com/graphql',
|
|
43
|
-
*
|
|
44
|
-
* contentId: 'my-stream',
|
|
43
|
+
* contentId: 'pk_...', // playbackId (view key)
|
|
45
44
|
* });
|
|
46
45
|
*
|
|
47
46
|
* client.on('statusChange', ({ status }) => console.log('Status:', status));
|
|
@@ -12,6 +12,7 @@ export interface InteractionControllerConfig {
|
|
|
12
12
|
container: HTMLElement;
|
|
13
13
|
videoElement: HTMLVideoElement;
|
|
14
14
|
isLive: boolean;
|
|
15
|
+
isPaused?: () => boolean;
|
|
15
16
|
onPlayPause: () => void;
|
|
16
17
|
onSeek: (delta: number) => void;
|
|
17
18
|
onVolumeChange: (delta: number) => void;
|
|
@@ -21,7 +22,11 @@ export interface InteractionControllerConfig {
|
|
|
21
22
|
onLoopToggle?: () => void;
|
|
22
23
|
onSpeedChange: (speed: number, isHolding: boolean) => void;
|
|
23
24
|
onSeekPercent?: (percent: number) => void;
|
|
25
|
+
/** Optional: player-specific frame stepping (return true if handled) */
|
|
26
|
+
onFrameStep?: (direction: -1 | 1, seconds: number) => boolean | void;
|
|
24
27
|
speedHoldValue?: number;
|
|
28
|
+
/** Frame step duration in seconds (for prev/next frame shortcuts) */
|
|
29
|
+
frameStepSeconds?: number;
|
|
25
30
|
/** Idle timeout in ms (default 5000). Set to 0 to disable. */
|
|
26
31
|
idleTimeout?: number;
|
|
27
32
|
/** Callback fired when user becomes idle */
|
|
@@ -58,6 +63,9 @@ export declare class InteractionController {
|
|
|
58
63
|
private boundPointerCancel;
|
|
59
64
|
private boundContextMenu;
|
|
60
65
|
private boundMouseMove;
|
|
66
|
+
private boundDoubleClick;
|
|
67
|
+
private boundDocumentKeyDown;
|
|
68
|
+
private boundDocumentKeyUp;
|
|
61
69
|
constructor(config: InteractionControllerConfig);
|
|
62
70
|
/**
|
|
63
71
|
* Attach event listeners to container
|
|
@@ -85,8 +93,11 @@ export declare class InteractionController {
|
|
|
85
93
|
updateConfig(updates: Partial<InteractionControllerConfig>): void;
|
|
86
94
|
private handleKeyDown;
|
|
87
95
|
private handleKeyUp;
|
|
96
|
+
private shouldHandleKeyboard;
|
|
88
97
|
private handleSpaceDown;
|
|
89
98
|
private handleSpaceUp;
|
|
99
|
+
private handleDoubleClick;
|
|
100
|
+
private stepFrame;
|
|
90
101
|
private handlePointerDown;
|
|
91
102
|
private handlePointerUp;
|
|
92
103
|
private handlePointerCancel;
|
|
@@ -118,4 +129,5 @@ export declare class InteractionController {
|
|
|
118
129
|
resumeIdleTracking(): void;
|
|
119
130
|
private isInputElement;
|
|
120
131
|
private isControlElement;
|
|
132
|
+
private getFrameStepSeconds;
|
|
121
133
|
}
|
|
@@ -40,7 +40,7 @@ type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecti
|
|
|
40
40
|
* ```ts
|
|
41
41
|
* const manager = new MetaTrackManager({
|
|
42
42
|
* mistBaseUrl: 'https://mist.example.com',
|
|
43
|
-
* streamName: '
|
|
43
|
+
* streamName: 'pk_...', // playbackId (view key)
|
|
44
44
|
* });
|
|
45
45
|
*
|
|
46
46
|
* manager.subscribe('1', (event) => {
|
|
@@ -17,7 +17,7 @@ export interface PlayerControllerConfig {
|
|
|
17
17
|
/** Content identifier (stream name) */
|
|
18
18
|
contentId: string;
|
|
19
19
|
/** Content type */
|
|
20
|
-
contentType
|
|
20
|
+
contentType?: ContentType;
|
|
21
21
|
/** Pre-resolved endpoints (skip gateway) */
|
|
22
22
|
endpoints?: ContentEndpoints;
|
|
23
23
|
/** Gateway URL (for FrameWorks Gateway resolution) */
|
|
@@ -219,7 +219,7 @@ export declare function buildStreamInfoFromEndpoints(endpoints: ContentEndpoints
|
|
|
219
219
|
* @example
|
|
220
220
|
* ```typescript
|
|
221
221
|
* const controller = new PlayerController({
|
|
222
|
-
* contentId: '
|
|
222
|
+
* contentId: 'pk_...', // playbackId (view key)
|
|
223
223
|
* contentType: 'live',
|
|
224
224
|
* gatewayUrl: 'https://gateway.example.com/graphql',
|
|
225
225
|
* });
|
|
@@ -238,6 +238,7 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
238
238
|
private config;
|
|
239
239
|
private state;
|
|
240
240
|
private lastEmittedState;
|
|
241
|
+
private suppressPlayPauseEventsUntil;
|
|
241
242
|
private gatewayClient;
|
|
242
243
|
private streamStateClient;
|
|
243
244
|
private playerManager;
|
|
@@ -249,6 +250,10 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
249
250
|
private streamState;
|
|
250
251
|
/** Tracks parsed from MistServer JSON response (used for direct MistServer mode) */
|
|
251
252
|
private mistTracks;
|
|
253
|
+
/** Gateway-seeded metadata (used as base for Mist enrichment) */
|
|
254
|
+
private metadataSeed;
|
|
255
|
+
/** Merged metadata (gateway seed + Mist enrichment) */
|
|
256
|
+
private metadata;
|
|
252
257
|
private cleanupFns;
|
|
253
258
|
private isDestroyed;
|
|
254
259
|
private isAttached;
|
|
@@ -319,6 +324,10 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
319
324
|
getEndpoints(): ContentEndpoints | null;
|
|
320
325
|
/** Get content metadata (title, description, duration, etc.) */
|
|
321
326
|
getMetadata(): ContentMetadata | null;
|
|
327
|
+
private setMetadataSeed;
|
|
328
|
+
private refreshMergedMetadata;
|
|
329
|
+
private buildMetadataTracks;
|
|
330
|
+
private sanitizeMistInfo;
|
|
322
331
|
/** Get stream info (sources + tracks for player selection) */
|
|
323
332
|
getStreamInfo(): StreamInfo | null;
|
|
324
333
|
/** Get video element (null if not ready) */
|
|
@@ -381,6 +390,8 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
381
390
|
hasAudioTrack(): boolean;
|
|
382
391
|
/** Check if playback rate adjustment is supported */
|
|
383
392
|
canAdjustPlaybackRate(): boolean;
|
|
393
|
+
/** Resolve content type from config override or Gateway metadata */
|
|
394
|
+
private getResolvedContentType;
|
|
384
395
|
/** Check if source is WebRTC/MediaStream */
|
|
385
396
|
isWebRTCSource(): boolean;
|
|
386
397
|
/** Check if currently in fullscreen mode */
|
|
@@ -494,6 +505,7 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
494
505
|
private getEffectiveCurrentTime;
|
|
495
506
|
private getEffectiveDuration;
|
|
496
507
|
private getPlayerSeekableRange;
|
|
508
|
+
private getFrameStepSecondsFromTracks;
|
|
497
509
|
private deriveBufferWindowMsFromTracks;
|
|
498
510
|
/** Get current time */
|
|
499
511
|
getCurrentTime(): number;
|
|
@@ -501,6 +513,10 @@ export declare class PlayerController extends TypedEventEmitter<PlayerController
|
|
|
501
513
|
getDuration(): number;
|
|
502
514
|
/** Check if paused */
|
|
503
515
|
isPaused(): boolean;
|
|
516
|
+
/** Suppress play/pause-driven UI updates for a short window */
|
|
517
|
+
suppressPlayPauseEvents(ms?: number): void;
|
|
518
|
+
/** Check if play/pause UI updates should be suppressed */
|
|
519
|
+
shouldSuppressVideoEvents(): boolean;
|
|
504
520
|
/** Check if muted */
|
|
505
521
|
isMuted(): boolean;
|
|
506
522
|
/** Skip backward by specified seconds (default 10) */
|
|
@@ -42,6 +42,8 @@ export interface PlayerOptions {
|
|
|
42
42
|
height?: number;
|
|
43
43
|
/** Enable dev mode - for Legacy player, uses MistServer's dev skin with source selection */
|
|
44
44
|
devMode?: boolean;
|
|
45
|
+
/** Enable debug logging in player implementations */
|
|
46
|
+
debug?: boolean;
|
|
45
47
|
onReady?: (element: HTMLVideoElement) => void;
|
|
46
48
|
onError?: (error: string | Error) => void;
|
|
47
49
|
onPlay?: () => void;
|
|
@@ -52,6 +54,12 @@ export interface PlayerOptions {
|
|
|
52
54
|
onPlaying?: () => void;
|
|
53
55
|
onCanPlay?: () => void;
|
|
54
56
|
onDurationChange?: (duration: number) => void;
|
|
57
|
+
/** HLS.js configuration override (merged with defaults) */
|
|
58
|
+
hlsConfig?: Record<string, unknown>;
|
|
59
|
+
/** DASH.js configuration override (merged with defaults) */
|
|
60
|
+
dashConfig?: Record<string, unknown>;
|
|
61
|
+
/** Video.js VHS configuration override (merged with defaults) */
|
|
62
|
+
vhsConfig?: Record<string, unknown>;
|
|
55
63
|
}
|
|
56
64
|
export interface PlayerCapability {
|
|
57
65
|
/** Player name for display */
|
|
@@ -173,6 +181,8 @@ export interface IPlayer {
|
|
|
173
181
|
getCurrentQuality?(): string | null;
|
|
174
182
|
isLive?(): boolean;
|
|
175
183
|
jumpToLive?(): void;
|
|
184
|
+
/** Optional: frame step (direction -1/1, optional step seconds) */
|
|
185
|
+
frameStep?(direction: -1 | 1, seconds?: number): void;
|
|
176
186
|
requestPiP?(): Promise<void>;
|
|
177
187
|
/**
|
|
178
188
|
* Optional: Retrieve player-specific stats (e.g., WebRTC inbound-rtp)
|
|
@@ -30,6 +30,8 @@ export interface SeekableRangeParams {
|
|
|
30
30
|
mistStreamInfo?: MistStreamInfo;
|
|
31
31
|
currentTime: number;
|
|
32
32
|
duration: number;
|
|
33
|
+
/** Allow Mist track metadata for MediaStream sources (e.g., WebCodecs DVR) */
|
|
34
|
+
allowMediaStreamDvr?: boolean;
|
|
33
35
|
}
|
|
34
36
|
export interface CanSeekParams {
|
|
35
37
|
video: HTMLVideoElement | null;
|
|
@@ -87,7 +89,7 @@ export declare function supportsPlaybackRate(video: HTMLVideoElement | null): bo
|
|
|
87
89
|
* 1. Browser's video.seekable ranges (most accurate for MSE-based players)
|
|
88
90
|
* 2. Track firstms/lastms from MistServer metadata
|
|
89
91
|
* 3. buffer_window from MistServer signaling
|
|
90
|
-
* 4.
|
|
92
|
+
* 4. No fallback (treat as live-only when no reliable data)
|
|
91
93
|
*
|
|
92
94
|
* @param params - Calculation parameters
|
|
93
95
|
* @returns Seekable range with start and live edge
|
|
@@ -37,7 +37,7 @@ export interface StreamStateClientEvents {
|
|
|
37
37
|
* ```typescript
|
|
38
38
|
* const client = new StreamStateClient({
|
|
39
39
|
* mistBaseUrl: 'https://mist.example.com',
|
|
40
|
-
* streamName: '
|
|
40
|
+
* streamName: 'pk_...', // playbackId (view key)
|
|
41
41
|
* });
|
|
42
42
|
*
|
|
43
43
|
* client.on('stateChange', ({ state }) => console.log('State:', state));
|
|
@@ -29,6 +29,14 @@ export declare class HlsJsPlayerImpl extends BasePlayer {
|
|
|
29
29
|
* Uses HLS.js liveSyncPosition when available (more accurate)
|
|
30
30
|
*/
|
|
31
31
|
jumpToLive(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Provide a seekable range override for live streams.
|
|
34
|
+
* Uses liveSyncPosition as the live edge to avoid waiting for the absolute end.
|
|
35
|
+
*/
|
|
36
|
+
getSeekableRange(): {
|
|
37
|
+
start: number;
|
|
38
|
+
end: number;
|
|
39
|
+
} | null;
|
|
32
40
|
/**
|
|
33
41
|
* Get latency from live edge (for live streams)
|
|
34
42
|
*/
|
|
@@ -37,7 +37,7 @@ export declare class MewsWsPlayerImpl extends BasePlayer {
|
|
|
37
37
|
private analyticsTimer;
|
|
38
38
|
isMimeSupported(mimetype: string): boolean;
|
|
39
39
|
isBrowserSupported(mimetype: string, source: StreamSource, streamInfo: StreamInfo): boolean | string[];
|
|
40
|
-
initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions): Promise<HTMLVideoElement>;
|
|
40
|
+
initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions, streamInfo?: StreamInfo): Promise<HTMLVideoElement>;
|
|
41
41
|
/**
|
|
42
42
|
* Handle MediaSource sourceopen event.
|
|
43
43
|
* Ported from mews.js:143-148, 198-204, 885-902
|
|
@@ -21,10 +21,6 @@ export declare class VideoJsPlayerImpl extends BasePlayer {
|
|
|
21
21
|
private getVideoJsType;
|
|
22
22
|
setPlaybackRate(rate: number): void;
|
|
23
23
|
getCurrentTime(): number;
|
|
24
|
-
getSeekableRange(): {
|
|
25
|
-
start: number;
|
|
26
|
-
end: number;
|
|
27
|
-
} | null;
|
|
28
24
|
/**
|
|
29
25
|
* Seek to time using VideoJS API (fixes backwards seeking in HLS).
|
|
30
26
|
* Time should be in the corrected coordinate space (with firstms offset applied).
|
|
@@ -46,11 +42,23 @@ export declare class VideoJsPlayerImpl extends BasePlayer {
|
|
|
46
42
|
* Check if the stream is live
|
|
47
43
|
*/
|
|
48
44
|
isLiveStream(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the calculated duration for live streams
|
|
47
|
+
*/
|
|
48
|
+
getDuration(): number;
|
|
49
49
|
/**
|
|
50
50
|
* Jump to live edge
|
|
51
51
|
* Uses VideoJS liveTracker when available, otherwise LiveDurationProxy
|
|
52
52
|
*/
|
|
53
53
|
jumpToLive(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Provide a seekable range override for live streams.
|
|
56
|
+
* Uses VideoJS liveTracker seekableEnd as the live edge when available.
|
|
57
|
+
*/
|
|
58
|
+
getSeekableRange(): {
|
|
59
|
+
start: number;
|
|
60
|
+
end: number;
|
|
61
|
+
} | null;
|
|
54
62
|
/**
|
|
55
63
|
* Get latency from live edge (for live streams)
|
|
56
64
|
*/
|
|
@@ -35,6 +35,8 @@ export declare class WebCodecsPlayerImpl extends BasePlayer {
|
|
|
35
35
|
private debugging;
|
|
36
36
|
private verboseDebugging;
|
|
37
37
|
private streamType;
|
|
38
|
+
/** Payload format: 'avcc' for ws/video/raw, 'annexb' for ws/video/h264 */
|
|
39
|
+
private payloadFormat;
|
|
38
40
|
private workerUidCounter;
|
|
39
41
|
private workerListeners;
|
|
40
42
|
private _duration;
|
|
@@ -47,6 +49,12 @@ export declare class WebCodecsPlayerImpl extends BasePlayer {
|
|
|
47
49
|
private _framesDecoded;
|
|
48
50
|
private _bytesReceived;
|
|
49
51
|
private _messagesReceived;
|
|
52
|
+
private _isPaused;
|
|
53
|
+
private _suppressPlayPauseSync;
|
|
54
|
+
private _onVideoPlay?;
|
|
55
|
+
private _onVideoPause?;
|
|
56
|
+
private _pendingStepPause;
|
|
57
|
+
private _stepPauseTimeout;
|
|
50
58
|
private static codecCache;
|
|
51
59
|
/**
|
|
52
60
|
* Get cache key for a track's codec configuration
|
|
@@ -95,8 +103,11 @@ export declare class WebCodecsPlayerImpl extends BasePlayer {
|
|
|
95
103
|
private closePipeline;
|
|
96
104
|
play(): Promise<void>;
|
|
97
105
|
pause(): void;
|
|
106
|
+
private finishStepPause;
|
|
107
|
+
frameStep(direction: -1 | 1, _seconds?: number): void;
|
|
98
108
|
seek(time: number): void;
|
|
99
109
|
setPlaybackRate(rate: number): void;
|
|
110
|
+
isPaused(): boolean;
|
|
100
111
|
isLive(): boolean;
|
|
101
112
|
jumpToLive(): void;
|
|
102
113
|
/**
|
|
@@ -143,6 +143,8 @@ export interface CreatePipelineMessage {
|
|
|
143
143
|
track: TrackInfo;
|
|
144
144
|
opts: {
|
|
145
145
|
optimizeForLatency: boolean;
|
|
146
|
+
/** Payload format: 'avcc' (length-prefixed) or 'annexb' (start-code delimited) */
|
|
147
|
+
payloadFormat?: 'avcc' | 'annexb';
|
|
146
148
|
};
|
|
147
149
|
uid?: number;
|
|
148
150
|
}
|
|
@@ -181,9 +183,10 @@ export interface ClosePipelineMessage {
|
|
|
181
183
|
}
|
|
182
184
|
export interface FrameTimingMessage {
|
|
183
185
|
type: 'frametiming';
|
|
184
|
-
action: 'setSpeed' | 'reset';
|
|
186
|
+
action: 'setSpeed' | 'reset' | 'setPaused';
|
|
185
187
|
speed?: number;
|
|
186
188
|
tweak?: number;
|
|
189
|
+
paused?: boolean;
|
|
187
190
|
uid?: number;
|
|
188
191
|
}
|
|
189
192
|
export interface SeekWorkerMessage {
|
|
@@ -196,7 +199,19 @@ export interface DebuggingMessage {
|
|
|
196
199
|
value: boolean | 'verbose';
|
|
197
200
|
uid?: number;
|
|
198
201
|
}
|
|
199
|
-
export
|
|
202
|
+
export interface FrameStepMessage {
|
|
203
|
+
type: 'framestep';
|
|
204
|
+
direction: -1 | 1;
|
|
205
|
+
uid?: number;
|
|
206
|
+
}
|
|
207
|
+
export interface WriteFrameResponseMessage {
|
|
208
|
+
type: 'writeframe';
|
|
209
|
+
idx: number;
|
|
210
|
+
uid?: number;
|
|
211
|
+
status: 'ok' | 'error';
|
|
212
|
+
error?: string;
|
|
213
|
+
}
|
|
214
|
+
export type MainToWorkerMessage = CreatePipelineMessage | ConfigurePipelineMessage | ReceiveChunkMessage | SetWritableMessage | CreateGeneratorMessage | ClosePipelineMessage | FrameTimingMessage | SeekWorkerMessage | DebuggingMessage | FrameStepMessage | WriteFrameResponseMessage;
|
|
200
215
|
export interface AddTrackMessage {
|
|
201
216
|
type: 'addtrack';
|
|
202
217
|
idx: number;
|
|
@@ -228,6 +243,7 @@ export interface SendEventMessage {
|
|
|
228
243
|
type: 'sendevent';
|
|
229
244
|
kind: string;
|
|
230
245
|
message?: string;
|
|
246
|
+
time?: number;
|
|
231
247
|
idx?: number;
|
|
232
248
|
uid?: number;
|
|
233
249
|
}
|
|
@@ -243,7 +259,13 @@ export interface AckMessage {
|
|
|
243
259
|
status?: 'ok' | 'error';
|
|
244
260
|
error?: string;
|
|
245
261
|
}
|
|
246
|
-
export
|
|
262
|
+
export interface WriteFrameMessage {
|
|
263
|
+
type: 'writeframe';
|
|
264
|
+
idx: number;
|
|
265
|
+
frame: AudioData;
|
|
266
|
+
uid?: number;
|
|
267
|
+
}
|
|
268
|
+
export type WorkerToMainMessage = AddTrackMessage | RemoveTrackMessage | SetPlaybackRateMessage | ClosedMessage | LogMessage | SendEventMessage | StatsMessage | AckMessage | WriteFrameMessage;
|
|
247
269
|
export interface FrameTimingStats {
|
|
248
270
|
/** Timestamp when frame entered decoder (microseconds) */
|
|
249
271
|
in: number;
|
|
@@ -10,6 +10,8 @@ export interface CreateMessage {
|
|
|
10
10
|
track: TrackInfo;
|
|
11
11
|
opts: {
|
|
12
12
|
optimizeForLatency: boolean;
|
|
13
|
+
/** Payload format: 'avcc' (length-prefixed) or 'annexb' (start-code delimited) */
|
|
14
|
+
payloadFormat?: 'avcc' | 'annexb';
|
|
13
15
|
};
|
|
14
16
|
uid: number;
|
|
15
17
|
}
|
|
@@ -48,9 +50,10 @@ export interface CloseMessage {
|
|
|
48
50
|
}
|
|
49
51
|
export interface FrameTimingMessage {
|
|
50
52
|
type: 'frametiming';
|
|
51
|
-
action: 'setSpeed' | 'reset';
|
|
53
|
+
action: 'setSpeed' | 'reset' | 'setPaused';
|
|
52
54
|
speed?: number;
|
|
53
55
|
tweak?: number;
|
|
56
|
+
paused?: boolean;
|
|
54
57
|
uid: number;
|
|
55
58
|
}
|
|
56
59
|
export interface SeekMessage {
|
|
@@ -58,12 +61,17 @@ export interface SeekMessage {
|
|
|
58
61
|
seekTime: number;
|
|
59
62
|
uid: number;
|
|
60
63
|
}
|
|
64
|
+
export interface FrameStepMessage {
|
|
65
|
+
type: 'framestep';
|
|
66
|
+
direction: -1 | 1;
|
|
67
|
+
uid: number;
|
|
68
|
+
}
|
|
61
69
|
export interface DebuggingMessage {
|
|
62
70
|
type: 'debugging';
|
|
63
71
|
value: boolean | 'verbose';
|
|
64
72
|
uid: number;
|
|
65
73
|
}
|
|
66
|
-
export type MainToWorkerMessage = CreateMessage | ConfigureMessage | ReceiveMessage | SetWritableMessage | CreateGeneratorMessage | CloseMessage | FrameTimingMessage | SeekMessage | DebuggingMessage;
|
|
74
|
+
export type MainToWorkerMessage = CreateMessage | ConfigureMessage | ReceiveMessage | SetWritableMessage | CreateGeneratorMessage | CloseMessage | FrameTimingMessage | SeekMessage | FrameStepMessage | DebuggingMessage;
|
|
67
75
|
export interface AddTrackMessage {
|
|
68
76
|
type: 'addtrack';
|
|
69
77
|
idx: number;
|
|
@@ -97,6 +105,7 @@ export interface SendEventMessage {
|
|
|
97
105
|
type: 'sendevent';
|
|
98
106
|
kind: string;
|
|
99
107
|
message?: string;
|
|
108
|
+
time?: number;
|
|
100
109
|
idx?: number;
|
|
101
110
|
uid: number;
|
|
102
111
|
}
|
|
@@ -159,6 +168,13 @@ export interface PipelineState {
|
|
|
159
168
|
data: Uint8Array;
|
|
160
169
|
}>;
|
|
161
170
|
outputQueue: DecodedFrame[];
|
|
171
|
+
/** Recent video frames for backward/forward stepping (video only) */
|
|
172
|
+
frameHistory?: Array<{
|
|
173
|
+
frame: VideoFrame;
|
|
174
|
+
timestamp: number;
|
|
175
|
+
}>;
|
|
176
|
+
/** Cursor into frameHistory for step navigation */
|
|
177
|
+
historyCursor?: number | null;
|
|
162
178
|
stats: {
|
|
163
179
|
framesIn: number;
|
|
164
180
|
framesDecoded: number;
|
|
@@ -172,6 +188,8 @@ export interface PipelineState {
|
|
|
172
188
|
lastChunkBytes: string;
|
|
173
189
|
};
|
|
174
190
|
optimizeForLatency: boolean;
|
|
191
|
+
/** Payload format: 'avcc' (length-prefixed) or 'annexb' (start-code delimited) */
|
|
192
|
+
payloadFormat: 'avcc' | 'annexb';
|
|
175
193
|
}
|
|
176
194
|
export interface ScheduleResult {
|
|
177
195
|
/** Whether frame should be output now */
|
package/dist/types/types.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface PlayerOptions {
|
|
|
50
50
|
hlsConfig?: HlsJsConfig;
|
|
51
51
|
/** DASH.js configuration override (merged with defaults) */
|
|
52
52
|
dashConfig?: DashJsConfig;
|
|
53
|
+
/** Video.js VHS configuration override (merged with defaults) */
|
|
54
|
+
vhsConfig?: VhsConfig;
|
|
53
55
|
/** WebRTC configuration (ICE servers, etc.) */
|
|
54
56
|
rtcConfig?: RTCConfiguration;
|
|
55
57
|
/** String to append to all request URLs (auth tokens, tracking params) */
|
|
@@ -98,6 +100,21 @@ export interface DashJsConfig {
|
|
|
98
100
|
};
|
|
99
101
|
[key: string]: unknown;
|
|
100
102
|
}
|
|
103
|
+
/** Video.js VHS (http-streaming) configuration subset */
|
|
104
|
+
export interface VhsConfig {
|
|
105
|
+
/** Start with lowest quality for faster initial playback */
|
|
106
|
+
enableLowInitialPlaylist?: boolean;
|
|
107
|
+
/** Initial bandwidth estimate in bits per second (e.g., 5_000_000 for 5 Mbps) */
|
|
108
|
+
bandwidth?: number;
|
|
109
|
+
/** Persist bandwidth estimate in localStorage across sessions */
|
|
110
|
+
useBandwidthFromLocalStorage?: boolean;
|
|
111
|
+
/** Enable partial segment appends for lower latency */
|
|
112
|
+
handlePartialData?: boolean;
|
|
113
|
+
/** Time delta for live range safety calculations (seconds) */
|
|
114
|
+
liveRangeSafeTimeDelta?: number;
|
|
115
|
+
/** Pass-through for other VHS options */
|
|
116
|
+
[key: string]: unknown;
|
|
117
|
+
}
|
|
101
118
|
export type StreamProtocol = 'WHEP' | 'HLS' | 'DASH' | 'MP4' | 'WEBM' | 'RTMP' | 'MIST_HTML';
|
|
102
119
|
export interface OutputCapabilities {
|
|
103
120
|
supportsSeek: boolean;
|
|
@@ -138,7 +155,7 @@ export interface ContentMetadata {
|
|
|
138
155
|
durationSeconds?: number;
|
|
139
156
|
thumbnailUrl?: string;
|
|
140
157
|
createdAt?: string;
|
|
141
|
-
status?: 'AVAILABLE' | 'PROCESSING' | 'ERROR' | 'OFFLINE';
|
|
158
|
+
status?: 'AVAILABLE' | 'PROCESSING' | 'ERROR' | 'OFFLINE' | 'ONLINE' | 'INITIALIZING' | 'BOOTING' | 'WAITING_FOR_DATA' | 'SHUTTING_DOWN' | 'INVALID';
|
|
142
159
|
viewers?: number;
|
|
143
160
|
isLive?: boolean;
|
|
144
161
|
recordingSizeBytes?: number;
|
|
@@ -147,6 +164,19 @@ export interface ContentMetadata {
|
|
|
147
164
|
dvrStatus?: 'recording' | 'completed';
|
|
148
165
|
/** Native container format: mp4, m3u8, webm, etc. */
|
|
149
166
|
format?: string;
|
|
167
|
+
/** MistServer authoritative snapshot (merged into this metadata) */
|
|
168
|
+
mist?: MistStreamInfo;
|
|
169
|
+
/** Parsed track summary (derived from Mist metadata when available) */
|
|
170
|
+
tracks?: Array<{
|
|
171
|
+
type: 'video' | 'audio' | 'meta';
|
|
172
|
+
codec?: string;
|
|
173
|
+
width?: number;
|
|
174
|
+
height?: number;
|
|
175
|
+
bitrate?: number;
|
|
176
|
+
fps?: number;
|
|
177
|
+
channels?: number;
|
|
178
|
+
sampleRate?: number;
|
|
179
|
+
}>;
|
|
150
180
|
}
|
|
151
181
|
export interface ContentEndpoints {
|
|
152
182
|
primary: EndpointInfo;
|
|
@@ -360,4 +390,5 @@ export interface PlayerMetadata {
|
|
|
360
390
|
channels?: number;
|
|
361
391
|
sampleRate?: number;
|
|
362
392
|
}>;
|
|
393
|
+
mist?: MistStreamInfo;
|
|
363
394
|
}
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
9
|
-
* import { FrameWorksPlayer } from '@livepeer-frameworks/player/vanilla';
|
|
10
|
-
* import '@livepeer-frameworks/player/player.css';
|
|
9
|
+
* import { FrameWorksPlayer } from '@livepeer-frameworks/player-core/vanilla';
|
|
10
|
+
* import '@livepeer-frameworks/player-core/player.css';
|
|
11
11
|
*
|
|
12
12
|
* const player = new FrameWorksPlayer('#player', {
|
|
13
|
-
* contentId: '
|
|
13
|
+
* contentId: 'pk_...',
|
|
14
14
|
* contentType: 'live',
|
|
15
15
|
* gatewayUrl: 'https://gateway.example.com/graphql',
|
|
16
16
|
* onStateChange: (state) => console.log('State:', state),
|
|
@@ -30,7 +30,7 @@ export interface FrameWorksPlayerOptions {
|
|
|
30
30
|
/** Content identifier (stream name) */
|
|
31
31
|
contentId: string;
|
|
32
32
|
/** Content type */
|
|
33
|
-
contentType
|
|
33
|
+
contentType?: ContentType;
|
|
34
34
|
/** Pre-resolved endpoints (skip gateway) */
|
|
35
35
|
endpoints?: ContentEndpoints;
|
|
36
36
|
/** Gateway URL (required if endpoints not provided) */
|
|
@@ -57,7 +57,7 @@ export interface FrameWorksPlayerOptions {
|
|
|
57
57
|
}
|
|
58
58
|
interface LegacyConfig {
|
|
59
59
|
contentId: string;
|
|
60
|
-
contentType
|
|
60
|
+
contentType?: ContentType;
|
|
61
61
|
thumbnailUrl?: string | null;
|
|
62
62
|
options?: {
|
|
63
63
|
gatewayUrl?: string;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @example
|
|
5
5
|
* ```typescript
|
|
6
|
-
* import { FrameWorksPlayer } from '@livepeer-frameworks/player/vanilla';
|
|
7
|
-
* import '@livepeer-frameworks/player/player.css';
|
|
6
|
+
* import { FrameWorksPlayer } from '@livepeer-frameworks/player-core/vanilla';
|
|
7
|
+
* import '@livepeer-frameworks/player-core/player.css';
|
|
8
8
|
*
|
|
9
9
|
* const player = new FrameWorksPlayer('#player', {
|
|
10
|
-
* contentId: '
|
|
10
|
+
* contentId: 'pk_...',
|
|
11
11
|
* contentType: 'live',
|
|
12
12
|
* gatewayUrl: 'https://gateway.example.com/graphql',
|
|
13
13
|
* });
|