@stinkycomputing/web-live-player 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +323 -0
- package/dist/audio/file-audio-player.d.ts +60 -0
- package/dist/audio/live-audio-player.d.ts +64 -0
- package/dist/decoders/decoder-interface.d.ts +63 -0
- package/dist/decoders/wasm-decoder.d.ts +68 -0
- package/dist/decoders/wasm-worker/H264NALDecoder.worker.d.ts +1 -0
- package/dist/decoders/webcodecs-decoder.d.ts +82 -0
- package/dist/index.d.ts +35 -0
- package/dist/player/base-player.d.ts +54 -0
- package/dist/player/base-player.test.d.ts +8 -0
- package/dist/player/file-player.d.ts +200 -0
- package/dist/player/live-player.d.ts +219 -0
- package/dist/protocol/codec-utils.d.ts +25 -0
- package/dist/protocol/sesame-binary-protocol.d.ts +98 -0
- package/dist/scheduling/frame-scheduler.d.ts +122 -0
- package/dist/scheduling/frame-scheduler.test.d.ts +11 -0
- package/dist/sources/mp4-file-source.d.ts +143 -0
- package/dist/sources/standalone-moq-source.d.ts +44 -0
- package/dist/sources/stream-source.d.ts +73 -0
- package/dist/sources/websocket-source.d.ts +120 -0
- package/dist/types.d.ts +58 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/web-live-player.cjs +234 -0
- package/dist/web-live-player.mjs +9559 -0
- package/package.json +54 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Manages frame buffering and synchronization between stream framerate
|
|
5
|
+
* and display refresh rate.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Frame timing information for latency tracking
|
|
9
|
+
*/
|
|
10
|
+
export interface FrameTiming {
|
|
11
|
+
/** When encoded data arrived (performance.now()) */
|
|
12
|
+
arrivalTime: number;
|
|
13
|
+
/** When decode completed (performance.now()) */
|
|
14
|
+
decodeTime: number;
|
|
15
|
+
/** When frame was displayed (performance.now()) */
|
|
16
|
+
displayTime?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Latency statistics
|
|
20
|
+
*/
|
|
21
|
+
export interface LatencyStats {
|
|
22
|
+
/** Time from arrival to decode completion (ms) */
|
|
23
|
+
decodeLatency: number;
|
|
24
|
+
/** Time from decode to display (ms) */
|
|
25
|
+
bufferLatency: number;
|
|
26
|
+
/** Total time from arrival to display (ms) */
|
|
27
|
+
totalLatency: number;
|
|
28
|
+
/** Average latencies over recent frames */
|
|
29
|
+
avgDecodeLatency: number;
|
|
30
|
+
avgBufferLatency: number;
|
|
31
|
+
avgTotalLatency: number;
|
|
32
|
+
}
|
|
33
|
+
export interface SchedulerStatus {
|
|
34
|
+
currentBufferSize: number;
|
|
35
|
+
currentBufferMs: number;
|
|
36
|
+
avgBufferMs: number;
|
|
37
|
+
targetBufferMs: number;
|
|
38
|
+
streamFrameDurationUs: number | null;
|
|
39
|
+
droppedFrames: number;
|
|
40
|
+
totalEnqueuedFrames: number;
|
|
41
|
+
totalDequeuedFrames: number;
|
|
42
|
+
driftCorrections: number;
|
|
43
|
+
latency: LatencyStats | null;
|
|
44
|
+
}
|
|
45
|
+
export interface SchedulerConfig<T> {
|
|
46
|
+
/** Target buffer delay in milliseconds (0 = bypass mode, always return latest) */
|
|
47
|
+
bufferDelayMs?: number;
|
|
48
|
+
/** Maximum buffer size in frames before overflow */
|
|
49
|
+
maxBufferSize?: number;
|
|
50
|
+
/** How often to check drift (every N dequeues) */
|
|
51
|
+
driftCheckInterval?: number;
|
|
52
|
+
/** Drift threshold in milliseconds before correction */
|
|
53
|
+
driftCorrectionThresholdMs?: number;
|
|
54
|
+
/** Logger function */
|
|
55
|
+
logger?: (message: string) => void;
|
|
56
|
+
/** Callback when frame is dropped */
|
|
57
|
+
onFrameDropped?: (frame: T, reason: 'overflow' | 'skip') => void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* FrameScheduler - Simplified implementation
|
|
61
|
+
*
|
|
62
|
+
* Core algorithm:
|
|
63
|
+
* 1. On first dequeue with frames, record (realTime, streamTime) as start point
|
|
64
|
+
* 2. On each dequeue:
|
|
65
|
+
* - Calculate expected stream time = startStreamTime + (currentRealTime - startRealTime) - bufferDelay
|
|
66
|
+
* - Find frame with timestamp <= expectedStreamTime
|
|
67
|
+
* - Drop old frames, return best match
|
|
68
|
+
* 3. Periodically adjust start point to correct drift
|
|
69
|
+
*/
|
|
70
|
+
export declare class FrameScheduler<T> {
|
|
71
|
+
private buffer;
|
|
72
|
+
private bufferDelayMs;
|
|
73
|
+
private maxBufferSize;
|
|
74
|
+
private startRealTimeUs;
|
|
75
|
+
private startStreamTimeUs;
|
|
76
|
+
private frameDurationUs;
|
|
77
|
+
private lastFrameTimestamp;
|
|
78
|
+
private bufferSizeHistory;
|
|
79
|
+
private driftCheckInterval;
|
|
80
|
+
private driftThresholdMs;
|
|
81
|
+
private dequeueCount;
|
|
82
|
+
private latencyHistory;
|
|
83
|
+
private latencyHistorySize;
|
|
84
|
+
private stats;
|
|
85
|
+
private logger;
|
|
86
|
+
private onFrameDropped?;
|
|
87
|
+
constructor(config?: SchedulerConfig<T>);
|
|
88
|
+
/** Buffer delay in microseconds */
|
|
89
|
+
private get bufferDelayUs();
|
|
90
|
+
/** Effective drift threshold - scales with buffer target for low-latency mode */
|
|
91
|
+
private get effectiveDriftThresholdMs();
|
|
92
|
+
/** Enqueue a decoded frame with timing information */
|
|
93
|
+
enqueue(frame: T, timestampUs: number, timing: FrameTiming): void;
|
|
94
|
+
/** Dequeue frame for rendering at given real time (milliseconds) */
|
|
95
|
+
dequeue(realTimeMs: number): T | null;
|
|
96
|
+
/** Bypass mode: return latest frame, drop rest */
|
|
97
|
+
private dequeueLatest;
|
|
98
|
+
/** Record latency for a frame */
|
|
99
|
+
private recordLatency;
|
|
100
|
+
/** Get current latency stats */
|
|
101
|
+
getLatencyStats(): LatencyStats | null;
|
|
102
|
+
/** Find index of last frame with timestamp <= target */
|
|
103
|
+
private findBestFrameIndex;
|
|
104
|
+
/** Drop N frames from front of buffer */
|
|
105
|
+
private dropFrames;
|
|
106
|
+
/** Track buffer size for drift detection */
|
|
107
|
+
private trackBufferSize;
|
|
108
|
+
/** Correct timing drift by adjusting start point */
|
|
109
|
+
private correctDrift;
|
|
110
|
+
/** Clear buffer */
|
|
111
|
+
clear(): void;
|
|
112
|
+
/** Set buffer delay in milliseconds */
|
|
113
|
+
setBufferDelay(delayMs: number): void;
|
|
114
|
+
/** Get current buffer delay in milliseconds */
|
|
115
|
+
getBufferDelay(): number;
|
|
116
|
+
/** Get status */
|
|
117
|
+
getStatus(): SchedulerStatus;
|
|
118
|
+
/** Log status */
|
|
119
|
+
logStatus(): void;
|
|
120
|
+
/** Reset statistics */
|
|
121
|
+
resetStats(): void;
|
|
122
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameScheduler Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the critical frame scheduling and buffering logic.
|
|
5
|
+
* The scheduler is responsible for:
|
|
6
|
+
* - Buffering frames to handle network jitter
|
|
7
|
+
* - Synchronizing stream time to real time
|
|
8
|
+
* - Detecting and correcting drift
|
|
9
|
+
* - Dropping frames appropriately when falling behind
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MP4 File Source - Client-side MP4 demuxing using mp4box.js
|
|
3
|
+
*
|
|
4
|
+
* Loads MP4 files and extracts video/audio samples for decoding.
|
|
5
|
+
* Works entirely in the browser without a backend server.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* File metadata extracted from MP4
|
|
9
|
+
*/
|
|
10
|
+
export interface MP4FileInfo {
|
|
11
|
+
duration: number;
|
|
12
|
+
timescale: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
videoCodec: string;
|
|
16
|
+
audioCodec?: string;
|
|
17
|
+
frameRate?: number;
|
|
18
|
+
bitrate?: number;
|
|
19
|
+
audioChannels?: number;
|
|
20
|
+
audioSampleRate?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sample ready for decoding
|
|
24
|
+
*/
|
|
25
|
+
export interface DecodableSample {
|
|
26
|
+
data: Uint8Array;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
duration: number;
|
|
29
|
+
isKeyframe: boolean;
|
|
30
|
+
type: 'video' | 'audio';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Event handlers for MP4FileSource
|
|
34
|
+
*/
|
|
35
|
+
export interface MP4FileSourceEvents {
|
|
36
|
+
onReady?: (info: MP4FileInfo) => void;
|
|
37
|
+
onSamples?: (samples: DecodableSample[]) => void;
|
|
38
|
+
onError?: (error: Error) => void;
|
|
39
|
+
onProgress?: (loaded: number, total: number) => void;
|
|
40
|
+
onEnded?: () => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* MP4 File Source - Demuxes MP4 files in the browser
|
|
44
|
+
*/
|
|
45
|
+
export declare class MP4FileSource {
|
|
46
|
+
private mp4File;
|
|
47
|
+
private fileInfo;
|
|
48
|
+
private videoTrackId;
|
|
49
|
+
private audioTrackId;
|
|
50
|
+
private videoTrack;
|
|
51
|
+
private audioTrack;
|
|
52
|
+
private nextVideoSampleIndex;
|
|
53
|
+
private nextAudioSampleIndex;
|
|
54
|
+
private totalVideoSamples;
|
|
55
|
+
private totalAudioSamples;
|
|
56
|
+
private samplesRequested;
|
|
57
|
+
private fileSize;
|
|
58
|
+
private loadedBytes;
|
|
59
|
+
private videoDescription;
|
|
60
|
+
private audioDescription;
|
|
61
|
+
private events;
|
|
62
|
+
constructor(events?: MP4FileSourceEvents);
|
|
63
|
+
/**
|
|
64
|
+
* Get the extracted file info
|
|
65
|
+
*/
|
|
66
|
+
getFileInfo(): MP4FileInfo | null;
|
|
67
|
+
/**
|
|
68
|
+
* Get the video codec description (for VideoDecoder.configure)
|
|
69
|
+
*/
|
|
70
|
+
getVideoDescription(): Uint8Array | null;
|
|
71
|
+
/**
|
|
72
|
+
* Get the audio codec description (for AudioDecoder.configure)
|
|
73
|
+
*/
|
|
74
|
+
getAudioDescription(): Uint8Array | null;
|
|
75
|
+
/**
|
|
76
|
+
* Load an MP4 file from a URL
|
|
77
|
+
*/
|
|
78
|
+
loadFromUrl(url: string): Promise<MP4FileInfo>;
|
|
79
|
+
/**
|
|
80
|
+
* Load an MP4 file from a File object (e.g., from file input)
|
|
81
|
+
*/
|
|
82
|
+
loadFromFile(file: File): Promise<MP4FileInfo>;
|
|
83
|
+
/**
|
|
84
|
+
* Load from a ReadableStreamDefaultReader (for progressive loading)
|
|
85
|
+
* Uses WritableStream pattern for proper mp4box integration.
|
|
86
|
+
*/
|
|
87
|
+
private loadFromStream;
|
|
88
|
+
/**
|
|
89
|
+
* Load from a complete ArrayBuffer
|
|
90
|
+
*/
|
|
91
|
+
private loadFromArrayBuffer;
|
|
92
|
+
/**
|
|
93
|
+
* Initialize the mp4box ISOFile
|
|
94
|
+
*/
|
|
95
|
+
private initMP4File;
|
|
96
|
+
/**
|
|
97
|
+
* Handle file ready event
|
|
98
|
+
*/
|
|
99
|
+
private handleFileReady;
|
|
100
|
+
/**
|
|
101
|
+
* Request samples to be extracted
|
|
102
|
+
*/
|
|
103
|
+
private requestSamples;
|
|
104
|
+
/**
|
|
105
|
+
* Handle samples from mp4box
|
|
106
|
+
*/
|
|
107
|
+
private handleSamples;
|
|
108
|
+
/**
|
|
109
|
+
* Seek to a specific time in seconds
|
|
110
|
+
* Returns the actual seek time (may be different due to keyframe alignment)
|
|
111
|
+
*/
|
|
112
|
+
seek(timeSeconds: number): number;
|
|
113
|
+
/**
|
|
114
|
+
* Get current position info
|
|
115
|
+
*/
|
|
116
|
+
getPosition(): {
|
|
117
|
+
currentSample: number;
|
|
118
|
+
totalSamples: number;
|
|
119
|
+
progress: number;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Stop extraction
|
|
123
|
+
*/
|
|
124
|
+
stop(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Resume extraction
|
|
127
|
+
*/
|
|
128
|
+
start(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Dispose and clean up
|
|
131
|
+
*/
|
|
132
|
+
dispose(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Serialize avcC box content for WebCodecs description
|
|
135
|
+
* Format: AVCDecoderConfigurationRecord
|
|
136
|
+
*/
|
|
137
|
+
private serializeAvcC;
|
|
138
|
+
/**
|
|
139
|
+
* Serialize hvcC box content for WebCodecs description
|
|
140
|
+
* Format: HEVCDecoderConfigurationRecord
|
|
141
|
+
*/
|
|
142
|
+
private serializeHvcC;
|
|
143
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BaseStreamSource } from './stream-source';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Track configuration for standalone MoQ source
|
|
5
|
+
*/
|
|
6
|
+
export interface StandaloneMoQTrack {
|
|
7
|
+
trackName: string;
|
|
8
|
+
priority?: number;
|
|
9
|
+
streamType: 'video' | 'audio' | 'data';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for standalone MoQ source
|
|
13
|
+
*/
|
|
14
|
+
export interface StandaloneMoQConfig {
|
|
15
|
+
relayUrl: string;
|
|
16
|
+
namespace: string;
|
|
17
|
+
subscriptions: StandaloneMoQTrack[];
|
|
18
|
+
reconnectionDelay?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Factory function to create a standalone MoQ source
|
|
22
|
+
*/
|
|
23
|
+
export declare function createStandaloneMoQSource(config: StandaloneMoQConfig): StandaloneMoQSource;
|
|
24
|
+
/**
|
|
25
|
+
* Standalone MoQ stream source implementation
|
|
26
|
+
*/
|
|
27
|
+
export declare class StandaloneMoQSource extends BaseStreamSource {
|
|
28
|
+
private config;
|
|
29
|
+
private session;
|
|
30
|
+
private trackTypeMap;
|
|
31
|
+
private connecting;
|
|
32
|
+
constructor(config: StandaloneMoQConfig);
|
|
33
|
+
/**
|
|
34
|
+
* Connect to the MoQ relay
|
|
35
|
+
*/
|
|
36
|
+
connect(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Disconnect from the MoQ relay
|
|
39
|
+
*/
|
|
40
|
+
disconnect(): Promise<void>;
|
|
41
|
+
private setupEventListeners;
|
|
42
|
+
private handleIncomingData;
|
|
43
|
+
dispose(): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ParsedData } from '../protocol/sesame-binary-protocol';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Event data emitted when stream data is received
|
|
5
|
+
*/
|
|
6
|
+
export interface StreamDataEvent {
|
|
7
|
+
trackName: string;
|
|
8
|
+
streamType: 'video' | 'audio' | 'data';
|
|
9
|
+
data: ParsedData;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Handler type for stream data events
|
|
13
|
+
*/
|
|
14
|
+
export type StreamDataHandler = (event: StreamDataEvent) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Handler type for error events
|
|
17
|
+
*/
|
|
18
|
+
export type StreamErrorHandler = (error: Error) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Handler type for connection state events
|
|
21
|
+
*/
|
|
22
|
+
export type StreamConnectionHandler = () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Stream source event types
|
|
25
|
+
*/
|
|
26
|
+
export type StreamSourceEvent = 'data' | 'error' | 'connected' | 'disconnected';
|
|
27
|
+
/**
|
|
28
|
+
* Interface for stream data sources.
|
|
29
|
+
* Implement this interface to provide video/audio data to the player
|
|
30
|
+
* from any transport mechanism.
|
|
31
|
+
*/
|
|
32
|
+
export interface IStreamSource {
|
|
33
|
+
/**
|
|
34
|
+
* Subscribe to stream events
|
|
35
|
+
*/
|
|
36
|
+
on(event: 'data', handler: StreamDataHandler): void;
|
|
37
|
+
on(event: 'error', handler: StreamErrorHandler): void;
|
|
38
|
+
on(event: 'connected', handler: StreamConnectionHandler): void;
|
|
39
|
+
on(event: 'disconnected', handler: StreamConnectionHandler): void;
|
|
40
|
+
/**
|
|
41
|
+
* Unsubscribe from stream events
|
|
42
|
+
*/
|
|
43
|
+
off(event: StreamSourceEvent, handler: Function): void;
|
|
44
|
+
/**
|
|
45
|
+
* Current connection state (optional)
|
|
46
|
+
*/
|
|
47
|
+
readonly connected?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Request a keyframe from the stream (for live streams)
|
|
50
|
+
*/
|
|
51
|
+
requestKeyframe?(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Dispose the stream source and clean up resources
|
|
54
|
+
*/
|
|
55
|
+
dispose?(): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Base class for implementing stream sources with event handling
|
|
59
|
+
*/
|
|
60
|
+
export declare abstract class BaseStreamSource implements IStreamSource {
|
|
61
|
+
protected handlers: Map<string, Set<Function>>;
|
|
62
|
+
protected _connected: boolean;
|
|
63
|
+
get connected(): boolean;
|
|
64
|
+
on(event: 'data', handler: StreamDataHandler): void;
|
|
65
|
+
on(event: 'error', handler: StreamErrorHandler): void;
|
|
66
|
+
on(event: 'connected', handler: StreamConnectionHandler): void;
|
|
67
|
+
on(event: 'disconnected', handler: StreamConnectionHandler): void;
|
|
68
|
+
off(event: StreamSourceEvent, handler: Function): void;
|
|
69
|
+
protected emit(event: 'data', data: StreamDataEvent): void;
|
|
70
|
+
protected emit(event: 'error', error: Error): void;
|
|
71
|
+
protected emit(event: 'connected' | 'disconnected'): void;
|
|
72
|
+
dispose(): void;
|
|
73
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { BaseStreamSource } from './stream-source';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for WebSocket stream source
|
|
5
|
+
*/
|
|
6
|
+
export interface WebSocketSourceConfig {
|
|
7
|
+
/** WebSocket URL (ws:// or wss://) */
|
|
8
|
+
url?: string;
|
|
9
|
+
/** Auto-construct URL from current page location */
|
|
10
|
+
useCurrentHost?: boolean;
|
|
11
|
+
/** API path for video endpoint */
|
|
12
|
+
apiPath?: string;
|
|
13
|
+
/** Client ID for the connection */
|
|
14
|
+
clientId?: string;
|
|
15
|
+
/** Connection timeout in milliseconds */
|
|
16
|
+
timeout?: number;
|
|
17
|
+
/** Enable automatic reconnection */
|
|
18
|
+
autoReconnect?: boolean;
|
|
19
|
+
/** Reconnection delay in milliseconds */
|
|
20
|
+
reconnectDelay?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Video metadata returned from the server
|
|
24
|
+
*/
|
|
25
|
+
export interface VideoMetadata {
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
frameRate?: number;
|
|
29
|
+
duration?: number;
|
|
30
|
+
codec?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* WebSocket-based stream source for live and file-based video playback.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const source = new WebSocketSource({ useCurrentHost: true });
|
|
38
|
+
* await source.connect();
|
|
39
|
+
* await source.loadLive('my-stream');
|
|
40
|
+
*
|
|
41
|
+
* source.on('data', (event) => {
|
|
42
|
+
* if (event.streamType === 'video') {
|
|
43
|
+
* // Handle video frame
|
|
44
|
+
* }
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare class WebSocketSource extends BaseStreamSource {
|
|
49
|
+
private webSocket;
|
|
50
|
+
private messageWaiters;
|
|
51
|
+
private requestId;
|
|
52
|
+
private timeoutCheckInterval;
|
|
53
|
+
private ignoreCmdsBelow;
|
|
54
|
+
private isLiveStream;
|
|
55
|
+
private config;
|
|
56
|
+
private lastKeyframeRequest;
|
|
57
|
+
private currentTrackName;
|
|
58
|
+
private reconnectTimeout;
|
|
59
|
+
private disposed;
|
|
60
|
+
constructor(config?: WebSocketSourceConfig);
|
|
61
|
+
/**
|
|
62
|
+
* Get the WebSocket URL based on configuration
|
|
63
|
+
*/
|
|
64
|
+
private getWebSocketUrl;
|
|
65
|
+
/**
|
|
66
|
+
* Connect to the WebSocket server
|
|
67
|
+
*/
|
|
68
|
+
connect(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Disconnect from the WebSocket server
|
|
71
|
+
*/
|
|
72
|
+
disconnect(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Load a live stream by ID
|
|
75
|
+
*/
|
|
76
|
+
loadLive(streamId: string): Promise<VideoMetadata>;
|
|
77
|
+
/**
|
|
78
|
+
* Load a video file
|
|
79
|
+
*/
|
|
80
|
+
loadFile(project: string, filename: string): Promise<VideoMetadata>;
|
|
81
|
+
/**
|
|
82
|
+
* Seek to a position in the video (file playback only)
|
|
83
|
+
*/
|
|
84
|
+
seek(positionMs: number): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Request more packets from the server (file playback)
|
|
87
|
+
*/
|
|
88
|
+
read(packetCount: number): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Unload the current stream
|
|
91
|
+
*/
|
|
92
|
+
unload(): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Request a keyframe (live streams only)
|
|
95
|
+
*/
|
|
96
|
+
requestKeyframe(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Flush pending requests (useful when seeking)
|
|
99
|
+
*/
|
|
100
|
+
flush(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Dispose the stream source
|
|
103
|
+
*/
|
|
104
|
+
dispose(): void;
|
|
105
|
+
private request;
|
|
106
|
+
private waitForResponse;
|
|
107
|
+
private handleMessage;
|
|
108
|
+
private handleResponse;
|
|
109
|
+
private handleBinaryData;
|
|
110
|
+
private handleDisconnect;
|
|
111
|
+
private scheduleReconnect;
|
|
112
|
+
private stopReconnect;
|
|
113
|
+
private startTimeoutChecker;
|
|
114
|
+
private stopTimeoutChecker;
|
|
115
|
+
private clearWaiters;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Factory function to create a WebSocket stream source
|
|
119
|
+
*/
|
|
120
|
+
export declare function createWebSocketSource(config?: WebSocketSourceConfig): WebSocketSource;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared type definitions for the video player library
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* YUV frame data from WASM decoder
|
|
6
|
+
*/
|
|
7
|
+
export interface YUVFrame {
|
|
8
|
+
y: Uint8Array;
|
|
9
|
+
u: Uint8Array;
|
|
10
|
+
v: Uint8Array;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
chromaStride: number;
|
|
14
|
+
chromaHeight: number;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
/** Compatibility with VideoFrame interface */
|
|
17
|
+
close: () => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Stream metadata received from the source
|
|
21
|
+
*/
|
|
22
|
+
export interface StreamMetadata {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
frameRate?: number;
|
|
26
|
+
codec?: string;
|
|
27
|
+
bitDepth?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Decoder type preference
|
|
31
|
+
*/
|
|
32
|
+
export type PreferredDecoder = 'webcodecs-hw' | 'webcodecs-sw' | 'wasm';
|
|
33
|
+
/**
|
|
34
|
+
* Logger interface for customizable logging
|
|
35
|
+
*/
|
|
36
|
+
export interface Logger {
|
|
37
|
+
debug(message: string): void;
|
|
38
|
+
info(message: string): void;
|
|
39
|
+
warn(message: string): void;
|
|
40
|
+
error(message: string): void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Default console logger
|
|
44
|
+
*/
|
|
45
|
+
export declare const consoleLogger: Logger;
|
|
46
|
+
/**
|
|
47
|
+
* Silent logger (no output)
|
|
48
|
+
*/
|
|
49
|
+
export declare const silentLogger: Logger;
|
|
50
|
+
/**
|
|
51
|
+
* Augment WebCodecs VideoDecoderConfig with latencyMode
|
|
52
|
+
* (not yet in standard TypeScript DOM types)
|
|
53
|
+
*/
|
|
54
|
+
declare global {
|
|
55
|
+
interface VideoDecoderConfig {
|
|
56
|
+
latencyMode?: 'quality' | 'realtime';
|
|
57
|
+
}
|
|
58
|
+
}
|