@stinkycomputing/web-live-player 0.1.2 → 0.1.4

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.
@@ -0,0 +1,55 @@
1
+ import { BaseCaptureSink, CaptureSinkConfig, SerializedPacket } from './capture-sink';
2
+
3
+ /**
4
+ * Track configuration for MoQ publishing
5
+ */
6
+ export interface MoQTrackConfig {
7
+ trackName: string;
8
+ priority?: number;
9
+ }
10
+ /**
11
+ * MoQ-specific sink configuration
12
+ */
13
+ export interface MoQSinkConfig extends CaptureSinkConfig {
14
+ /** MoQ relay URL */
15
+ relayUrl: string;
16
+ /** Namespace for the streams */
17
+ namespace: string;
18
+ /** Video track configuration */
19
+ videoTrack?: MoQTrackConfig;
20
+ /** Audio track configuration */
21
+ audioTrack?: MoQTrackConfig;
22
+ /** Additional data tracks (e.g., for chat messages) */
23
+ dataTracks?: MoQTrackConfig[];
24
+ /** Reconnection delay in ms */
25
+ reconnectionDelay?: number;
26
+ }
27
+ /**
28
+ * Capture sink that sends data over MoQ
29
+ */
30
+ export declare class MoQCaptureSink extends BaseCaptureSink {
31
+ private moqConfig;
32
+ private session;
33
+ private connecting;
34
+ private disposed;
35
+ private currentVideoGroup;
36
+ private audioFrameCount;
37
+ private static readonly AUDIO_FRAMES_PER_GROUP;
38
+ constructor(config: MoQSinkConfig);
39
+ connect(): Promise<void>;
40
+ disconnect(): Promise<void>;
41
+ send(packet: SerializedPacket): void;
42
+ private setupEventListeners;
43
+ dispose(): void;
44
+ /**
45
+ * Send custom data on a data track (e.g., chat messages)
46
+ * Each data message starts a new group.
47
+ * @param trackName The data track name to send on
48
+ * @param data The data to send
49
+ */
50
+ sendData(trackName: string, data: Uint8Array): void;
51
+ }
52
+ /**
53
+ * Factory function to create a MoQ capture sink
54
+ */
55
+ export declare function createMoQSink(config: MoQSinkConfig): MoQCaptureSink;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Video Encoder Worker
3
+ *
4
+ * Handles video encoding in a separate thread using WebCodecs VideoEncoder.
5
+ * Supports keyframe requests and configurable GOP (Group of Pictures).
6
+ */
7
+ export {};
@@ -0,0 +1,35 @@
1
+ import { BaseCaptureSink, CaptureSinkConfig, SerializedPacket } from './capture-sink';
2
+
3
+ /**
4
+ * WebSocket-specific sink configuration
5
+ */
6
+ export interface WebSocketSinkConfig extends CaptureSinkConfig {
7
+ /** WebSocket URL to connect to */
8
+ url: string;
9
+ /** Connection timeout in ms */
10
+ connectionTimeout?: number;
11
+ /** Whether to automatically reconnect on disconnect */
12
+ autoReconnect?: boolean;
13
+ /** Delay between reconnection attempts in ms */
14
+ reconnectDelay?: number;
15
+ }
16
+ /**
17
+ * Capture sink that sends data over WebSocket
18
+ */
19
+ export declare class WebSocketCaptureSink extends BaseCaptureSink {
20
+ private websocket?;
21
+ private wsConfig;
22
+ private reconnectTimer?;
23
+ private disposed;
24
+ constructor(config: WebSocketSinkConfig);
25
+ connect(): Promise<void>;
26
+ disconnect(): Promise<void>;
27
+ send(packet: SerializedPacket): void;
28
+ private scheduleReconnect;
29
+ private clearReconnectTimer;
30
+ dispose(): void;
31
+ }
32
+ /**
33
+ * Factory function to create a WebSocket capture sink
34
+ */
35
+ export declare function createWebSocketSink(config: WebSocketSinkConfig): WebSocketCaptureSink;
package/dist/index.d.ts CHANGED
@@ -12,10 +12,10 @@ export * from './sources/stream-source';
12
12
  export { BasePlayer } from './player/base-player';
13
13
  export type { BasePlayerConfig } from './player/base-player';
14
14
  export { LiveVideoPlayer, createPlayer } from './player/live-player';
15
- export type { PlayerConfig, PlayerStats, PlayerState } from './player/live-player';
15
+ export type { PlayerConfig, PlayerStats, PlayerState, BandwidthStats } from './player/live-player';
16
16
  export { FileVideoPlayer, createFilePlayer } from './player/file-player';
17
17
  export type { FilePlayerConfig, FilePlayerState, FilePlayerStats, FilePlayMode } from './player/file-player';
18
- export { createStandaloneMoQSource, StandaloneMoQSource } from './sources/standalone-moq-source';
18
+ export { createMoQSource, MoQSource } from './sources/moq-source';
19
19
  export { WebSocketSource, createWebSocketSource } from './sources/websocket-source';
20
20
  export type { WebSocketSourceConfig, VideoMetadata } from './sources/websocket-source';
21
21
  export { MP4FileSource } from './sources/mp4-file-source';
@@ -30,6 +30,7 @@ export { FileAudioPlayer } from './audio/file-audio-player';
30
30
  export { LiveAudioPlayer } from './audio/live-audio-player';
31
31
  export type { LiveAudioConfig } from './audio/live-audio-player';
32
32
  export { FrameScheduler } from './scheduling/frame-scheduler';
33
- export type { FrameTiming, LatencyStats, SchedulerStatus, SchedulerConfig } from './scheduling/frame-scheduler';
34
- export { SesameBinaryProtocol } from './protocol/sesame-binary-protocol';
33
+ export type { FrameTiming, LatencyStats, SchedulerStatus, SchedulerConfig, PacketTimingEntry } from './scheduling/frame-scheduler';
34
+ export { SesameBinaryProtocol, FLAG_IS_KEYFRAME, FLAG_HAS_CODEC_DATA, PacketType } from './protocol/sesame-binary-protocol';
35
35
  export type { ParsedData, HeaderData, HeaderCodecData } from './protocol/sesame-binary-protocol';
36
+ export * from './capture';
@@ -21,6 +21,14 @@ export interface PlayerConfig {
21
21
  * Player state
22
22
  */
23
23
  export type PlayerState = 'idle' | 'playing' | 'paused' | 'error';
24
+ /**
25
+ * Bandwidth statistics
26
+ */
27
+ export interface BandwidthStats {
28
+ videoBytesPerSecond: number;
29
+ audioBytesPerSecond: number;
30
+ totalBytesPerSecond: number;
31
+ }
24
32
  /**
25
33
  * Player statistics
26
34
  */
@@ -36,6 +44,7 @@ export interface PlayerStats {
36
44
  streamHeight: number;
37
45
  frameRate: number;
38
46
  latency: LatencyStats | null;
47
+ bandwidth: BandwidthStats | null;
39
48
  }
40
49
  /**
41
50
  * Player event types
@@ -79,11 +88,21 @@ export declare class LiveVideoPlayer extends BasePlayer<PlayerState> {
79
88
  private streamWidth;
80
89
  private streamHeight;
81
90
  private estimatedFrameRate;
91
+ private lastVideoTimestampUs;
92
+ private fpsEstimateSamples;
93
+ private static readonly FPS_SAMPLE_COUNT;
82
94
  private audioContext;
83
95
  private audioPlayer;
84
96
  private ownsAudioContext;
85
97
  private audioCodecData;
86
98
  private arrivalTimes;
99
+ private keyframeStatus;
100
+ private videoBytesReceived;
101
+ private audioBytesReceived;
102
+ private lastBandwidthUpdateTime;
103
+ private lastVideoBytesReceived;
104
+ private lastAudioBytesReceived;
105
+ private currentBandwidth;
87
106
  constructor(config?: PlayerConfig);
88
107
  /**
89
108
  * Enable or disable debug logging at runtime
@@ -109,7 +128,7 @@ export declare class LiveVideoPlayer extends BasePlayer<PlayerState> {
109
128
  * Convenience method to connect to a MoQ-like session
110
129
  *
111
130
  * Note: For audio support, the MoQ session must also be subscribed to the audio track.
112
- * When using StandaloneMoQSource, include both 'video' and 'audio' in subscriptions.
131
+ * When using MoQSource, include both 'video' and 'audio' in subscriptions.
113
132
  * When using Elmo's MoQSessionNode, add an audio track to the session config.
114
133
  *
115
134
  * @param session - MoQ session implementing IStreamSource (e.g., Elmo's MoQSessionNode)
@@ -164,6 +183,14 @@ export declare class LiveVideoPlayer extends BasePlayer<PlayerState> {
164
183
  * Get player statistics
165
184
  */
166
185
  getStats(): PlayerStats;
186
+ /**
187
+ * Update bandwidth statistics
188
+ */
189
+ private updateBandwidthStats;
190
+ /**
191
+ * Get packet timing history for visualization/debugging
192
+ */
193
+ getPacketTimingHistory(): import('..').PacketTimingEntry[];
167
194
  /**
168
195
  * Subscribe to player events (typed overload)
169
196
  */
@@ -42,6 +42,23 @@ export interface SchedulerStatus {
42
42
  driftCorrections: number;
43
43
  latency: LatencyStats | null;
44
44
  }
45
+ /**
46
+ * Packet timing entry for visualization
47
+ */
48
+ export interface PacketTimingEntry {
49
+ /** Time packet arrived (performance.now()) */
50
+ arrivalTime: number;
51
+ /** Time since previous packet (ms) */
52
+ intervalMs: number;
53
+ /** Stream timestamp (us) */
54
+ streamTimestampUs: number;
55
+ /** Whether this was a keyframe */
56
+ isKeyframe: boolean;
57
+ /** Decode latency (ms) */
58
+ decodeLatencyMs: number;
59
+ /** Whether frame was dropped */
60
+ wasDropped: boolean;
61
+ }
45
62
  export interface SchedulerConfig<T> {
46
63
  /** Target buffer delay in milliseconds (0 = bypass mode, always return latest) */
47
64
  bufferDelayMs?: number;
@@ -81,6 +98,9 @@ export declare class FrameScheduler<T> {
81
98
  private dequeueCount;
82
99
  private latencyHistory;
83
100
  private latencyHistorySize;
101
+ private packetTimingHistory;
102
+ private packetTimingHistorySize;
103
+ private lastPacketArrivalTime;
84
104
  private stats;
85
105
  private logger;
86
106
  private onFrameDropped?;
@@ -90,7 +110,7 @@ export declare class FrameScheduler<T> {
90
110
  /** Effective drift threshold - scales with buffer target for low-latency mode */
91
111
  private get effectiveDriftThresholdMs();
92
112
  /** Enqueue a decoded frame with timing information */
93
- enqueue(frame: T, timestampUs: number, timing: FrameTiming): void;
113
+ enqueue(frame: T, timestampUs: number, timing: FrameTiming, isKeyframe?: boolean): void;
94
114
  /** Dequeue frame for rendering at given real time (milliseconds) */
95
115
  dequeue(realTimeMs: number): T | null;
96
116
  /** Bypass mode: return latest frame, drop rest */
@@ -119,4 +139,6 @@ export declare class FrameScheduler<T> {
119
139
  logStatus(): void;
120
140
  /** Reset statistics */
121
141
  resetStats(): void;
142
+ /** Get packet timing history for visualization */
143
+ getPacketTimingHistory(): PacketTimingEntry[];
122
144
  }
@@ -0,0 +1,44 @@
1
+ import { BaseStreamSource } from './stream-source';
2
+
3
+ /**
4
+ * Track configuration for MoQ source
5
+ */
6
+ export interface MoQTrack {
7
+ trackName: string;
8
+ priority?: number;
9
+ streamType: 'video' | 'audio' | 'data';
10
+ }
11
+ /**
12
+ * Configuration for MoQ source
13
+ */
14
+ export interface MoQSourceConfig {
15
+ relayUrl: string;
16
+ namespace: string;
17
+ subscriptions: MoQTrack[];
18
+ reconnectionDelay?: number;
19
+ }
20
+ /**
21
+ * Factory function to create a MoQ source
22
+ */
23
+ export declare function createMoQSource(config: MoQSourceConfig): MoQSource;
24
+ /**
25
+ * MoQ stream source implementation
26
+ */
27
+ export declare class MoQSource extends BaseStreamSource {
28
+ private config;
29
+ private session;
30
+ private trackTypeMap;
31
+ private connecting;
32
+ constructor(config: MoQSourceConfig);
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
+ }
@@ -18,6 +18,7 @@ export interface MP4FileInfo {
18
18
  bitrate?: number;
19
19
  audioChannels?: number;
20
20
  audioSampleRate?: number;
21
+ isMoovAtStart?: boolean;
21
22
  }
22
23
  /**
23
24
  * Sample ready for decoding
@@ -1,35 +1,35 @@
1
1
  import { BaseStreamSource } from './stream-source';
2
2
 
3
3
  /**
4
- * Track configuration for standalone MoQ source
4
+ * Track configuration for MoQ source
5
5
  */
6
- export interface StandaloneMoQTrack {
6
+ export interface MoQTrack {
7
7
  trackName: string;
8
8
  priority?: number;
9
9
  streamType: 'video' | 'audio' | 'data';
10
10
  }
11
11
  /**
12
- * Configuration for standalone MoQ source
12
+ * Configuration for MoQ source
13
13
  */
14
- export interface StandaloneMoQConfig {
14
+ export interface MoQSourceConfig {
15
15
  relayUrl: string;
16
16
  namespace: string;
17
- subscriptions: StandaloneMoQTrack[];
17
+ subscriptions: MoQTrack[];
18
18
  reconnectionDelay?: number;
19
19
  }
20
20
  /**
21
- * Factory function to create a standalone MoQ source
21
+ * Factory function to create a MoQ source
22
22
  */
23
- export declare function createStandaloneMoQSource(config: StandaloneMoQConfig): StandaloneMoQSource;
23
+ export declare function createMoQSource(config: MoQSourceConfig): MoQSource;
24
24
  /**
25
- * Standalone MoQ stream source implementation
25
+ * MoQ stream source implementation
26
26
  */
27
- export declare class StandaloneMoQSource extends BaseStreamSource {
27
+ export declare class MoQSource extends BaseStreamSource {
28
28
  private config;
29
29
  private session;
30
30
  private trackTypeMap;
31
31
  private connecting;
32
- constructor(config: StandaloneMoQConfig);
32
+ constructor(config: MoQSourceConfig);
33
33
  /**
34
34
  * Connect to the MoQ relay
35
35
  */