@stinkycomputing/web-live-player 0.1.3 → 0.1.5
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 +428 -402
- package/dist/assets/audio-encoder.worker-c5c829bb.js +114 -0
- package/dist/assets/video-encoder.worker-a613b1f0.js +91 -0
- package/dist/audio/live-audio-player.d.ts +5 -3
- package/dist/capture/audio-encoder.worker.d.ts +7 -0
- package/dist/capture/capture-sink.d.ts +105 -0
- package/dist/capture/capture-types.d.ts +120 -0
- package/dist/capture/index.d.ts +17 -0
- package/dist/capture/media-capture.d.ts +95 -0
- package/dist/capture/media-encoder.d.ts +65 -0
- package/dist/capture/moq-sink.d.ts +65 -0
- package/dist/capture/video-encoder.worker.d.ts +7 -0
- package/dist/capture/websocket-sink.d.ts +35 -0
- package/dist/decoders/decoder-interface.d.ts +3 -3
- package/dist/decoders/wasm-decoder.d.ts +3 -7
- package/dist/decoders/webcodecs-decoder.d.ts +5 -5
- package/dist/index.d.ts +3 -4
- package/dist/player/live-player.d.ts +4 -1
- package/dist/protocol/codec-utils.d.ts +6 -4
- package/dist/sources/moq-source.d.ts +44 -0
- package/dist/sources/standalone-moq-source.d.ts +10 -10
- package/dist/sources/stream-source.d.ts +2 -2
- package/dist/sources/websocket-source.d.ts +4 -35
- package/dist/web-live-player.cjs +3 -3
- package/dist/web-live-player.mjs +20407 -4891
- package/package.json +58 -57
- package/dist/protocol/sesame-binary-protocol.d.ts +0 -98
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { BaseCaptureSink, CaptureSinkConfig, SerializedPacket } from './capture-sink';
|
|
2
|
+
import { MoqSessionBroadcaster } from 'stinky-moq-js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Track configuration for MoQ publishing
|
|
6
|
+
*/
|
|
7
|
+
export interface MoQTrackConfig {
|
|
8
|
+
trackName: string;
|
|
9
|
+
priority?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* MoQ-specific sink configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface MoQSinkConfig extends CaptureSinkConfig {
|
|
15
|
+
/** MoQ relay URL (required if session is not provided) */
|
|
16
|
+
relayUrl?: string;
|
|
17
|
+
/** Namespace for the streams (required if session is not provided) */
|
|
18
|
+
namespace?: string;
|
|
19
|
+
/** Video track configuration */
|
|
20
|
+
videoTrack?: MoQTrackConfig;
|
|
21
|
+
/** Audio track configuration */
|
|
22
|
+
audioTrack?: MoQTrackConfig;
|
|
23
|
+
/** Additional data tracks (e.g., for chat messages) */
|
|
24
|
+
dataTracks?: MoQTrackConfig[];
|
|
25
|
+
/** Reconnection delay in ms */
|
|
26
|
+
reconnectionDelay?: number;
|
|
27
|
+
/** External MoQ session to use (if provided, relayUrl and namespace are ignored) */
|
|
28
|
+
session?: MoqSessionBroadcaster;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Capture sink that sends data over MoQ
|
|
32
|
+
*/
|
|
33
|
+
export declare class MoQCaptureSink extends BaseCaptureSink {
|
|
34
|
+
private moqConfig;
|
|
35
|
+
private session;
|
|
36
|
+
private connecting;
|
|
37
|
+
private disposed;
|
|
38
|
+
private sessionOwned;
|
|
39
|
+
private currentVideoGroup;
|
|
40
|
+
private audioFrameCount;
|
|
41
|
+
private static readonly AUDIO_FRAMES_PER_GROUP;
|
|
42
|
+
constructor(config: MoQSinkConfig);
|
|
43
|
+
connect(): Promise<void>;
|
|
44
|
+
disconnect(): Promise<void>;
|
|
45
|
+
send(packet: SerializedPacket): void;
|
|
46
|
+
private setupEventListeners;
|
|
47
|
+
dispose(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Set an external MoQ session (dependency injection)
|
|
50
|
+
* Similar to LiveVideoPlayer.setStreamSource()
|
|
51
|
+
* @param session - MoqSessionBroadcaster instance to use for broadcasting
|
|
52
|
+
*/
|
|
53
|
+
setMoQSession(session: MoqSessionBroadcaster): void;
|
|
54
|
+
/**
|
|
55
|
+
* Send custom data on a data track (e.g., chat messages)
|
|
56
|
+
* Each data message starts a new group.
|
|
57
|
+
* @param trackName The data track name to send on
|
|
58
|
+
* @param data The data to send
|
|
59
|
+
*/
|
|
60
|
+
sendData(trackName: string, data: Uint8Array): void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Factory function to create a MoQ capture sink
|
|
64
|
+
*/
|
|
65
|
+
export declare function createMoQSink(config: MoQSinkConfig): MoQCaptureSink;
|
|
@@ -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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMediaCodecData, ParsedFrame } from '@stinkycomputing/sesame-api-client';
|
|
2
2
|
import { YUVFrame } from '../types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -34,12 +34,12 @@ export interface IVideoDecoder {
|
|
|
34
34
|
* Configure the decoder for a specific codec
|
|
35
35
|
* @param codecData - Codec configuration from stream header
|
|
36
36
|
*/
|
|
37
|
-
configure(codecData:
|
|
37
|
+
configure(codecData: IMediaCodecData): Promise<void>;
|
|
38
38
|
/**
|
|
39
39
|
* Decode a binary packet from the stream
|
|
40
40
|
* @param data - Parsed stream data containing header and payload
|
|
41
41
|
*/
|
|
42
|
-
decodeBinary(data:
|
|
42
|
+
decodeBinary(data: ParsedFrame): void;
|
|
43
43
|
/**
|
|
44
44
|
* Flush pending frames (synchronous reset)
|
|
45
45
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ParsedData } from '../protocol/sesame-binary-protocol';
|
|
2
1
|
import { YUVFrame } from '../types';
|
|
3
2
|
import { IVideoDecoder } from './decoder-interface';
|
|
3
|
+
import { ParsedFrame } from '@stinkycomputing/sesame-api-client';
|
|
4
4
|
|
|
5
5
|
export type { YUVFrame } from '../types';
|
|
6
6
|
export interface WasmDecoderConfig {
|
|
@@ -27,15 +27,11 @@ export declare class WasmDecoder implements IVideoDecoder {
|
|
|
27
27
|
/**
|
|
28
28
|
* Configure the decoder (initializes the worker)
|
|
29
29
|
*/
|
|
30
|
-
configure(_codecData:
|
|
31
|
-
codec_type: number;
|
|
32
|
-
width: number;
|
|
33
|
-
height: number;
|
|
34
|
-
}): Promise<void>;
|
|
30
|
+
configure(_codecData: any): Promise<void>;
|
|
35
31
|
/**
|
|
36
32
|
* Decode a binary packet (same interface as WebCodecsDecoder)
|
|
37
33
|
*/
|
|
38
|
-
decodeBinary(data:
|
|
34
|
+
decodeBinary(data: ParsedFrame): void;
|
|
39
35
|
/**
|
|
40
36
|
* Process next frame from queue
|
|
41
37
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ParsedFrame, IMediaCodecData } from '@stinkycomputing/sesame-api-client';
|
|
2
2
|
import { Logger } from '../types';
|
|
3
3
|
import { IVideoDecoder } from './decoder-interface';
|
|
4
4
|
|
|
@@ -40,9 +40,9 @@ export declare class WebCodecsDecoder implements IVideoDecoder {
|
|
|
40
40
|
get state(): string;
|
|
41
41
|
private createDecoder;
|
|
42
42
|
/**
|
|
43
|
-
* Configure the decoder for a specific codec (from
|
|
43
|
+
* Configure the decoder for a specific codec (from IMediaCodecData)
|
|
44
44
|
*/
|
|
45
|
-
configure(codecData:
|
|
45
|
+
configure(codecData: IMediaCodecData, preferHardware?: boolean): Promise<void>;
|
|
46
46
|
/**
|
|
47
47
|
* Configure the decoder with VideoDecoderConfig directly
|
|
48
48
|
*/
|
|
@@ -52,13 +52,13 @@ export declare class WebCodecsDecoder implements IVideoDecoder {
|
|
|
52
52
|
*/
|
|
53
53
|
private configureWithConfig;
|
|
54
54
|
/**
|
|
55
|
-
* Configure with
|
|
55
|
+
* Configure with IMediaCodecData (from binary protocol)
|
|
56
56
|
*/
|
|
57
57
|
private configureWithCodecData;
|
|
58
58
|
/**
|
|
59
59
|
* Decode a binary packet
|
|
60
60
|
*/
|
|
61
|
-
decodeBinary(data:
|
|
61
|
+
decodeBinary(data: ParsedFrame): void;
|
|
62
62
|
/**
|
|
63
63
|
* Decode a sample (from file demuxer)
|
|
64
64
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export { LiveVideoPlayer, createPlayer } from './player/live-player';
|
|
|
15
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 {
|
|
18
|
+
export { createMoQSource, MoQSource } from './sources/moq-source';
|
|
19
19
|
export { WebSocketSource, createWebSocketSource } from './sources/websocket-source';
|
|
20
|
-
export type { WebSocketSourceConfig
|
|
20
|
+
export type { WebSocketSourceConfig } from './sources/websocket-source';
|
|
21
21
|
export { MP4FileSource } from './sources/mp4-file-source';
|
|
22
22
|
export type { MP4FileInfo, DecodableSample, MP4FileSourceEvents } from './sources/mp4-file-source';
|
|
23
23
|
export { WebCodecsDecoder } from './decoders/webcodecs-decoder';
|
|
@@ -31,5 +31,4 @@ 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
33
|
export type { FrameTiming, LatencyStats, SchedulerStatus, SchedulerConfig, PacketTimingEntry } from './scheduling/frame-scheduler';
|
|
34
|
-
export
|
|
35
|
-
export type { ParsedData, HeaderData, HeaderCodecData } from './protocol/sesame-binary-protocol';
|
|
34
|
+
export * from './capture';
|
|
@@ -88,6 +88,9 @@ export declare class LiveVideoPlayer extends BasePlayer<PlayerState> {
|
|
|
88
88
|
private streamWidth;
|
|
89
89
|
private streamHeight;
|
|
90
90
|
private estimatedFrameRate;
|
|
91
|
+
private lastVideoTimestampUs;
|
|
92
|
+
private fpsEstimateSamples;
|
|
93
|
+
private static readonly FPS_SAMPLE_COUNT;
|
|
91
94
|
private audioContext;
|
|
92
95
|
private audioPlayer;
|
|
93
96
|
private ownsAudioContext;
|
|
@@ -125,7 +128,7 @@ export declare class LiveVideoPlayer extends BasePlayer<PlayerState> {
|
|
|
125
128
|
* Convenience method to connect to a MoQ-like session
|
|
126
129
|
*
|
|
127
130
|
* Note: For audio support, the MoQ session must also be subscribed to the audio track.
|
|
128
|
-
* When using
|
|
131
|
+
* When using MoQSource, include both 'video' and 'audio' in subscriptions.
|
|
129
132
|
* When using Elmo's MoQSessionNode, add an audio track to the session config.
|
|
130
133
|
*
|
|
131
134
|
* @param session - MoQ session implementing IStreamSource (e.g., Elmo's MoQSessionNode)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMediaCodecData } from '@stinkycomputing/sesame-api-client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Timebase structure for timestamp conversion
|
|
@@ -10,11 +10,13 @@ export interface Timebase {
|
|
|
10
10
|
/**
|
|
11
11
|
* Rescale a timestamp from one timebase to another
|
|
12
12
|
*/
|
|
13
|
-
export declare function rescaleTime(pts: bigint
|
|
13
|
+
export declare function rescaleTime(pts: number | bigint | null | undefined | {
|
|
14
|
+
toString(): string;
|
|
15
|
+
}, source: Timebase, target: Timebase): number;
|
|
14
16
|
/**
|
|
15
17
|
* Check if codec data has changed
|
|
16
18
|
*/
|
|
17
|
-
export declare function codecDataChanged(current:
|
|
19
|
+
export declare function codecDataChanged(current: IMediaCodecData | undefined, newData: IMediaCodecData | undefined): boolean;
|
|
18
20
|
/**
|
|
19
21
|
* Get human-readable codec name
|
|
20
22
|
*/
|
|
@@ -22,4 +24,4 @@ export declare function getCodecName(codecType: number): string;
|
|
|
22
24
|
/**
|
|
23
25
|
* Get WebCodecs codec string for a given codec data
|
|
24
26
|
*/
|
|
25
|
-
export declare function getCodecString(codecData:
|
|
27
|
+
export declare function getCodecString(codecData: IMediaCodecData): string | null;
|
|
@@ -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
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
import { BaseStreamSource } from './stream-source';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Track configuration for
|
|
4
|
+
* Track configuration for MoQ source
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
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
|
|
12
|
+
* Configuration for MoQ source
|
|
13
13
|
*/
|
|
14
|
-
export interface
|
|
14
|
+
export interface MoQSourceConfig {
|
|
15
15
|
relayUrl: string;
|
|
16
16
|
namespace: string;
|
|
17
|
-
subscriptions:
|
|
17
|
+
subscriptions: MoQTrack[];
|
|
18
18
|
reconnectionDelay?: number;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Factory function to create a
|
|
21
|
+
* Factory function to create a MoQ source
|
|
22
22
|
*/
|
|
23
|
-
export declare function
|
|
23
|
+
export declare function createMoQSource(config: MoQSourceConfig): MoQSource;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* MoQ stream source implementation
|
|
26
26
|
*/
|
|
27
|
-
export declare class
|
|
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:
|
|
32
|
+
constructor(config: MoQSourceConfig);
|
|
33
33
|
/**
|
|
34
34
|
* Connect to the MoQ relay
|
|
35
35
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ParsedFrame } from '@stinkycomputing/sesame-api-client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Event data emitted when stream data is received
|
|
@@ -6,7 +6,7 @@ import { ParsedData } from '../protocol/sesame-binary-protocol';
|
|
|
6
6
|
export interface StreamDataEvent {
|
|
7
7
|
trackName: string;
|
|
8
8
|
streamType: 'video' | 'audio' | 'data';
|
|
9
|
-
data:
|
|
9
|
+
data: ParsedFrame;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* Handler type for stream data events
|
|
@@ -20,17 +20,7 @@ export interface WebSocketSourceConfig {
|
|
|
20
20
|
reconnectDelay?: number;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
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.
|
|
23
|
+
* WebSocket-based stream source for live video playback.
|
|
34
24
|
*
|
|
35
25
|
* @example
|
|
36
26
|
* ```typescript
|
|
@@ -50,8 +40,6 @@ export declare class WebSocketSource extends BaseStreamSource {
|
|
|
50
40
|
private messageWaiters;
|
|
51
41
|
private requestId;
|
|
52
42
|
private timeoutCheckInterval;
|
|
53
|
-
private ignoreCmdsBelow;
|
|
54
|
-
private isLiveStream;
|
|
55
43
|
private config;
|
|
56
44
|
private lastKeyframeRequest;
|
|
57
45
|
private currentTrackName;
|
|
@@ -72,32 +60,13 @@ export declare class WebSocketSource extends BaseStreamSource {
|
|
|
72
60
|
disconnect(): void;
|
|
73
61
|
/**
|
|
74
62
|
* Load a live stream by ID
|
|
63
|
+
* Note: Metadata is received via video stream codec data, not from this call
|
|
75
64
|
*/
|
|
76
|
-
loadLive(streamId: string): Promise<
|
|
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>;
|
|
65
|
+
loadLive(streamId: string): Promise<void>;
|
|
85
66
|
/**
|
|
86
|
-
* Request
|
|
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)
|
|
67
|
+
* Request a keyframe
|
|
95
68
|
*/
|
|
96
69
|
requestKeyframe(): void;
|
|
97
|
-
/**
|
|
98
|
-
* Flush pending requests (useful when seeking)
|
|
99
|
-
*/
|
|
100
|
-
flush(): void;
|
|
101
70
|
/**
|
|
102
71
|
* Dispose the stream source
|
|
103
72
|
*/
|