@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 ADDED
@@ -0,0 +1,323 @@
1
+ # Web Live Player
2
+
3
+ A framework-agnostic video streaming library with support for MoQ (Media over QUIC) and WebSocket backends.
4
+
5
+ ## Features
6
+
7
+ - **WebCodecs-based decoding** - Hardware-accelerated video decoding
8
+ - **MoQ support** - Native Media over QUIC protocol support via `stinky-moq-js`
9
+ - **Pluggable stream sources** - Use dependency injection to provide video data from any transport
10
+ - **Frame scheduling** - Automatic buffering and drift correction for smooth playback
11
+ - **No framework dependencies** - Works with vanilla JS, React, Three.js, or any other framework
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @stinkycomputing/web-live-player
17
+ ```
18
+
19
+ For MoQ support, also install:
20
+
21
+ ```bash
22
+ npm install stinky-moq-js
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Using with MoQ (Standalone)
28
+
29
+ ```typescript
30
+ import { createPlayer, createStandaloneMoQSource } from '@stinkycomputing/web-live-player';
31
+
32
+ // Create player
33
+ const player = createPlayer({
34
+ preferredDecoder: 'webcodecs-hw',
35
+ bufferSizeFrames: 3,
36
+ });
37
+
38
+ // Create MoQ source
39
+ const moqSource = createStandaloneMoQSource({
40
+ relayUrl: 'https://moq-relay.example.com',
41
+ namespace: 'live/stream',
42
+ subscriptions: [
43
+ { trackName: 'video', streamType: 'video' },
44
+ ],
45
+ });
46
+
47
+ // Connect and play
48
+ await moqSource.connect();
49
+ player.setStreamSource(moqSource);
50
+ player.setTrackFilter('video');
51
+ player.play();
52
+
53
+ // Render loop
54
+ function render(timestamp) {
55
+ const frame = player.getVideoFrame(timestamp);
56
+ if (frame) {
57
+ ctx.drawImage(frame, 0, 0);
58
+ }
59
+ requestAnimationFrame(render);
60
+ }
61
+ requestAnimationFrame(render);
62
+ ```
63
+
64
+ ### Using with Elmo's MoQSession
65
+
66
+ ```typescript
67
+ import { createPlayer } from '@stinkycomputing/web-live-player';
68
+ import { MoQDiscoveryUtils } from '@elmo/core';
69
+
70
+ // Find session from Elmo's node tree
71
+ // MoQSessionNode implements IStreamSource directly
72
+ const session = MoQDiscoveryUtils.findMoQSession(currentNode, 'my-session');
73
+
74
+ // Create and configure player - session can be used directly as stream source
75
+ const player = createPlayer();
76
+ player.setStreamSource(session);
77
+ player.setTrackFilter('video-track');
78
+ player.play();
79
+ ```
80
+
81
+ ### Custom Stream Source
82
+
83
+ ```typescript
84
+ import { createPlayer, IStreamSource, BaseStreamSource } from '@stinkycomputing/web-live-player';
85
+
86
+ class MyCustomSource extends BaseStreamSource {
87
+ async connect() {
88
+ // Your connection logic
89
+ this._connected = true;
90
+ this.emit('connected');
91
+ }
92
+
93
+ // Call this when you receive video data
94
+ handleVideoData(trackName: string, data: ParsedData) {
95
+ this.emit('data', {
96
+ trackName,
97
+ streamType: 'video',
98
+ data,
99
+ });
100
+ }
101
+ }
102
+
103
+ const source = new MyCustomSource();
104
+ await source.connect();
105
+
106
+ const player = createPlayer();
107
+ player.setStreamSource(source);
108
+ player.play();
109
+ ```
110
+
111
+ ## API Reference
112
+
113
+ ### `createPlayer(config?)`
114
+
115
+ Creates a new player instance.
116
+
117
+ **Config options:**
118
+ - `preferredDecoder`: `'webcodecs-hw'` | `'webcodecs-sw'` | `'wasm'` - Decoder preference
119
+ - `bufferSizeFrames`: `number` - Target buffer size (default: 3)
120
+ - `debugLogging`: `boolean` - Enable debug logging
121
+
122
+ ### `LiveVideoPlayer`
123
+
124
+ Main player class.
125
+
126
+ **Methods:**
127
+ - `setStreamSource(source: IStreamSource)` - Set the stream data source
128
+ - `setTrackFilter(trackName: string)` - Filter for specific track
129
+ - `play()` - Start playback
130
+ - `pause()` - Pause playback
131
+ - `getVideoFrame(timestampMs: number)` - Get frame for current render timestamp
132
+ - `getStats()` - Get playback statistics
133
+ - `dispose()` - Clean up resources
134
+
135
+ **Events:**
136
+ - `frame` - Emitted when a frame is decoded
137
+ - `metadata` - Emitted when stream metadata is received
138
+ - `statechange` - Emitted when player state changes
139
+ - `error` - Emitted on errors
140
+
141
+ ### `IStreamSource`
142
+
143
+ Interface for stream data sources.
144
+
145
+ **Events to emit:**
146
+ - `data` - Stream data event with `{ trackName, streamType, data }`
147
+ - `connected` - When connected
148
+ - `disconnected` - When disconnected
149
+ - `error` - On errors
150
+
151
+ ## Rendering Frames to Canvas
152
+
153
+ The player returns `VideoFrame` objects that can be rendered in multiple ways:
154
+
155
+ ### Basic Canvas Rendering
156
+
157
+ ```typescript
158
+ const canvas = document.getElementById('video-canvas') as HTMLCanvasElement;
159
+ const ctx = canvas.getContext('2d')!;
160
+
161
+ function render(timestamp: number) {
162
+ const frame = player.getVideoFrame(timestamp);
163
+ if (frame) {
164
+ // Resize canvas to match video dimensions
165
+ if (canvas.width !== frame.displayWidth || canvas.height !== frame.displayHeight) {
166
+ canvas.width = frame.displayWidth;
167
+ canvas.height = frame.displayHeight;
168
+ }
169
+
170
+ // Draw the frame
171
+ ctx.drawImage(frame, 0, 0);
172
+
173
+ // IMPORTANT: Close the frame when done to release memory
174
+ frame.close();
175
+ }
176
+ requestAnimationFrame(render);
177
+ }
178
+ requestAnimationFrame(render);
179
+ ```
180
+
181
+ ### WebGL / Three.js Rendering
182
+
183
+ For GPU-accelerated rendering (e.g., in Three.js):
184
+
185
+ ```typescript
186
+ // Create a texture
187
+ const texture = new THREE.Texture();
188
+ texture.minFilter = THREE.LinearFilter;
189
+ texture.magFilter = THREE.LinearFilter;
190
+ texture.colorSpace = THREE.SRGBColorSpace;
191
+
192
+ // In your render loop
193
+ function render(timestamp: number) {
194
+ const frame = player.getVideoFrame(timestamp);
195
+ if (frame) {
196
+ // Update texture with the VideoFrame
197
+ texture.image = frame;
198
+ texture.needsUpdate = true;
199
+
200
+ // Close previous frame if stored
201
+ if (lastFrame) lastFrame.close();
202
+ lastFrame = frame;
203
+ }
204
+
205
+ renderer.render(scene, camera);
206
+ requestAnimationFrame(render);
207
+ }
208
+ ```
209
+
210
+ ### Handling YUV Frames (WASM Decoder)
211
+
212
+ When using the WASM decoder, the library automatically converts YUV frames to `VideoFrame` objects using the browser's native I420 support. The GPU handles YUV→RGB conversion, so you can use the same rendering code regardless of decoder:
213
+
214
+ ```typescript
215
+ // The player always returns VideoFrame, even with WASM decoder
216
+ const frame = player.getVideoFrame(timestamp);
217
+ if (frame) {
218
+ ctx.drawImage(frame, 0, 0);
219
+ frame.close();
220
+ }
221
+ ```
222
+
223
+ If you need raw YUV data for custom processing, you can access the `WasmDecoder` directly:
224
+
225
+ ```typescript
226
+ import { WasmDecoder } from '@stinkycomputing/web-live-player';
227
+
228
+ const decoder = new WasmDecoder({
229
+ onFrameDecoded: (yuvFrame) => {
230
+ // yuvFrame has: { y, u, v, width, height, stride, chromaStride, chromaHeight, timestamp }
231
+ // Process raw YUV data here
232
+ },
233
+ });
234
+ ```
235
+
236
+ ### Best Practices
237
+
238
+ 1. **Always close VideoFrames** - Call `frame.close()` when done to prevent memory leaks
239
+ 2. **Check for null frames** - `getVideoFrame()` returns null when no frame is ready
240
+ 3. **Use performance.now()** - Pass accurate timestamps for proper frame scheduling
241
+ 4. **Handle resize** - Update canvas dimensions when video dimensions change
242
+
243
+
244
+ ## Bundler Configuration
245
+
246
+ ### WASM Decoder (tinyh264)
247
+
248
+ The WASM decoder uses `tinyh264` which requires special bundler configuration for its Web Worker and WASM assets.
249
+
250
+ #### Vite
251
+
252
+ Add the following to your `vite.config.ts`:
253
+
254
+ ```typescript
255
+ import { defineConfig } from 'vite';
256
+
257
+ export default defineConfig({
258
+ // Handle tinyh264's .asset files as URLs
259
+ assetsInclude: ['**/*.asset'],
260
+
261
+ // Ensure worker files are bundled correctly
262
+ worker: {
263
+ format: 'es',
264
+ },
265
+ });
266
+ ```
267
+
268
+ #### Webpack
269
+
270
+ For Webpack, you may need to configure asset handling:
271
+
272
+ ```javascript
273
+ module.exports = {
274
+ module: {
275
+ rules: [
276
+ {
277
+ test: /\.asset$/,
278
+ type: 'asset/resource',
279
+ },
280
+ ],
281
+ },
282
+ };
283
+ ```
284
+
285
+ ### WebCodecs Decoder (Recommended)
286
+
287
+ If you only need WebCodecs-based decoding (hardware or software), no special bundler configuration is required. Simply use:
288
+
289
+ ```typescript
290
+ const player = createPlayer({
291
+ preferredDecoder: 'webcodecs-hw', // or 'webcodecs-sw'
292
+ });
293
+ ```
294
+
295
+ ## Demo
296
+
297
+ Run the demo application:
298
+
299
+ ```bash
300
+ cd video-player
301
+ npm install
302
+ npm run dev
303
+ ```
304
+
305
+ Open http://localhost:3001 to see the demo.
306
+
307
+ ## Building
308
+
309
+ Build the library:
310
+
311
+ ```bash
312
+ npm run build
313
+ ```
314
+
315
+ Build the demo:
316
+
317
+ ```bash
318
+ npm run build:demo
319
+ ```
320
+
321
+ ## License
322
+
323
+ MIT
@@ -0,0 +1,60 @@
1
+ /**
2
+ * File Audio Player
3
+ *
4
+ * Decodes and plays audio from MP4 files using WebCodecs AudioDecoder
5
+ * and AudioWorklet for real-time playback.
6
+ */
7
+ export interface AudioPlayerConfig {
8
+ sampleRate?: number;
9
+ channels?: number;
10
+ }
11
+ export declare class FileAudioPlayer {
12
+ private ctx;
13
+ private decoder;
14
+ private workletNode;
15
+ private gainNode;
16
+ private initialized;
17
+ private targetSampleRate;
18
+ private codecConfig;
19
+ constructor(context: AudioContext, config?: AudioPlayerConfig);
20
+ /**
21
+ * Initialize the audio player with codec info from MP4
22
+ */
23
+ init(codec: string, sampleRate: number, numberOfChannels: number, description?: Uint8Array): Promise<void>;
24
+ /**
25
+ * Handle decoded audio frame
26
+ */
27
+ private handleDecodedFrame;
28
+ /**
29
+ * Resample audio to target sample rate
30
+ */
31
+ private resampleAudio;
32
+ /**
33
+ * Decode an audio sample
34
+ */
35
+ decode(data: Uint8Array, timestamp: number, duration: number): void;
36
+ /**
37
+ * Start audio playback
38
+ */
39
+ start(): void;
40
+ /**
41
+ * Stop audio playback
42
+ */
43
+ stop(): void;
44
+ /**
45
+ * Clear audio buffers
46
+ */
47
+ clear(): void;
48
+ /**
49
+ * Reset timing for seamless loop (clears worklet buffer)
50
+ */
51
+ resetTiming(): void;
52
+ /**
53
+ * Set volume (0-1)
54
+ */
55
+ setVolume(volume: number): void;
56
+ /**
57
+ * Dispose of resources
58
+ */
59
+ dispose(): void;
60
+ }
@@ -0,0 +1,64 @@
1
+ import { HeaderCodecData } from '../protocol/sesame-binary-protocol';
2
+
3
+ export interface LiveAudioConfig {
4
+ bufferDelayMs?: number;
5
+ }
6
+ export declare class LiveAudioPlayer {
7
+ private ctx;
8
+ private decoder;
9
+ private workletNode;
10
+ private gainNode;
11
+ private initialized;
12
+ private targetSampleRate;
13
+ private startTime;
14
+ private bufferDelayMs;
15
+ constructor(context: AudioContext, config?: LiveAudioConfig);
16
+ /**
17
+ * Initialize with codec info from stream header
18
+ */
19
+ init(codecData?: HeaderCodecData): Promise<void>;
20
+ /**
21
+ * Build decoder config based on codec type
22
+ */
23
+ private buildDecoderConfig;
24
+ /**
25
+ * Handle decoded audio frame
26
+ */
27
+ private handleDecodedFrame;
28
+ /**
29
+ * Resample audio to target sample rate
30
+ */
31
+ private resampleAudio;
32
+ /**
33
+ * Queue encoded audio data for decoding
34
+ */
35
+ decode(data: Uint8Array, pts?: bigint): void;
36
+ /**
37
+ * Set buffer delay for A/V sync
38
+ */
39
+ setBufferDelay(delayMs: number): void;
40
+ /**
41
+ * Start audio playback
42
+ */
43
+ start(): void;
44
+ /**
45
+ * Stop audio playback
46
+ */
47
+ stop(): void;
48
+ /**
49
+ * Clear audio buffers (for seek/reset)
50
+ */
51
+ clear(): void;
52
+ /**
53
+ * Reset timing reference
54
+ */
55
+ resetTiming(): void;
56
+ /**
57
+ * Set volume (0-1)
58
+ */
59
+ setVolume(volume: number): void;
60
+ /**
61
+ * Dispose resources
62
+ */
63
+ dispose(): void;
64
+ }
@@ -0,0 +1,63 @@
1
+ import { ParsedData, HeaderCodecData } from '../protocol/sesame-binary-protocol';
2
+ import { YUVFrame } from '../types';
3
+
4
+ /**
5
+ * Decoder state (matches WebCodecs VideoDecoder states)
6
+ */
7
+ export type DecoderState = 'unconfigured' | 'configuring' | 'configured' | 'closed';
8
+ /**
9
+ * Frame output from a decoder - can be VideoFrame or YUVFrame
10
+ */
11
+ export type DecodedFrame = VideoFrame | YUVFrame;
12
+ /**
13
+ * Configuration options for decoder initialization
14
+ */
15
+ export interface VideoDecoderOptions {
16
+ /** Callback for decoded frames */
17
+ onFrameDecoded?: (frame: DecodedFrame) => void;
18
+ /** Callback for errors */
19
+ onError?: (error: Error) => void;
20
+ /** Callback when decoder queue overflows */
21
+ onQueueOverflow?: (queueSize: number) => void;
22
+ /** Maximum decoder queue size before overflow callback */
23
+ maxQueueSize?: number;
24
+ }
25
+ /**
26
+ * Common interface for video decoders
27
+ */
28
+ export interface IVideoDecoder {
29
+ /**
30
+ * Current decoder state
31
+ */
32
+ readonly state: DecoderState | string;
33
+ /**
34
+ * Configure the decoder for a specific codec
35
+ * @param codecData - Codec configuration from stream header
36
+ */
37
+ configure(codecData: HeaderCodecData): Promise<void>;
38
+ /**
39
+ * Decode a binary packet from the stream
40
+ * @param data - Parsed stream data containing header and payload
41
+ */
42
+ decodeBinary(data: ParsedData): void;
43
+ /**
44
+ * Flush pending frames (synchronous reset)
45
+ */
46
+ flush(): void;
47
+ /**
48
+ * Reset the decoder to configured state (ready for new keyframe)
49
+ */
50
+ reset(): void;
51
+ /**
52
+ * Dispose the decoder and release resources
53
+ */
54
+ dispose(): void;
55
+ }
56
+ /**
57
+ * Type guard to check if a frame is a VideoFrame
58
+ */
59
+ export declare function isVideoFrame(frame: DecodedFrame): frame is VideoFrame;
60
+ /**
61
+ * Type guard to check if a frame is a YUVFrame
62
+ */
63
+ export declare function isYUVFrame(frame: DecodedFrame): frame is YUVFrame;
@@ -0,0 +1,68 @@
1
+ import { ParsedData } from '../protocol/sesame-binary-protocol';
2
+ import { YUVFrame } from '../types';
3
+ import { IVideoDecoder } from './decoder-interface';
4
+
5
+ export type { YUVFrame } from '../types';
6
+ export interface WasmDecoderConfig {
7
+ onFrameDecoded?: (frame: YUVFrame) => void;
8
+ onError?: (error: Error) => void;
9
+ onQueueOverflow?: (queueSize: number) => void;
10
+ maxQueueSize?: number;
11
+ }
12
+ export declare class WasmDecoder implements IVideoDecoder {
13
+ private worker?;
14
+ private _queueSize;
15
+ private pendingTimestamps;
16
+ private pendingFrames;
17
+ private maxQueueSize;
18
+ private onFrameDecoded?;
19
+ private onError?;
20
+ private onQueueOverflow?;
21
+ configured: boolean;
22
+ constructor(config?: WasmDecoderConfig);
23
+ get queueSize(): number;
24
+ /**
25
+ * Get decoder state (for compatibility with WebCodecsDecoder)
26
+ */
27
+ get state(): string;
28
+ /**
29
+ * Configure the decoder (initializes the worker)
30
+ */
31
+ configure(_codecData: {
32
+ codec_type: number;
33
+ width: number;
34
+ height: number;
35
+ }): Promise<void>;
36
+ /**
37
+ * Decode a binary packet (same interface as WebCodecsDecoder)
38
+ */
39
+ decodeBinary(data: ParsedData): void;
40
+ /**
41
+ * Process next frame from queue
42
+ */
43
+ private decodeNext;
44
+ /**
45
+ * Send frame to worker for decoding
46
+ */
47
+ private decode;
48
+ /**
49
+ * Handle decoded picture from worker
50
+ */
51
+ private handlePictureReady;
52
+ /**
53
+ * Flush the decoder (clear pending frames)
54
+ */
55
+ flush(): void;
56
+ /**
57
+ * Synchronous flush
58
+ */
59
+ flushSync(): void;
60
+ /**
61
+ * Reset the decoder (same as flush for WASM decoder)
62
+ */
63
+ reset(): void;
64
+ /**
65
+ * Dispose of the decoder
66
+ */
67
+ dispose(): void;
68
+ }
@@ -0,0 +1,82 @@
1
+ import { ParsedData, HeaderCodecData } from '../protocol/sesame-binary-protocol';
2
+ import { Logger } from '../types';
3
+ import { IVideoDecoder } from './decoder-interface';
4
+
5
+ export interface DecoderConfig {
6
+ preferHardware?: boolean;
7
+ logger?: Logger;
8
+ onFrameDecoded?: (frame: VideoFrame) => void;
9
+ /** Alias for onFrameDecoded */
10
+ onFrame?: (frame: VideoFrame) => void;
11
+ onError?: (error: Error) => void;
12
+ onQueueOverflow?: (queueSize: number) => void;
13
+ maxQueueSize?: number;
14
+ }
15
+ /**
16
+ * Sample data for decoding (from file demuxer)
17
+ */
18
+ export interface SampleData {
19
+ data: Uint8Array;
20
+ timestamp: number;
21
+ duration?: number;
22
+ isKeyframe: boolean;
23
+ }
24
+ /**
25
+ * WebCodecs-based video decoder
26
+ */
27
+ export declare class WebCodecsDecoder implements IVideoDecoder {
28
+ private decoder;
29
+ private config;
30
+ private flushing;
31
+ private logger;
32
+ private maxQueueSize;
33
+ onFrameDecoded?: (frame: VideoFrame) => void;
34
+ onError?: (error: Error) => void;
35
+ onQueueOverflow?: (queueSize: number) => void;
36
+ chunksSentToDecoder: number;
37
+ framesDecoded: number;
38
+ constructor(options?: DecoderConfig);
39
+ get decodeQueueSize(): number;
40
+ get state(): string;
41
+ private createDecoder;
42
+ /**
43
+ * Configure the decoder for a specific codec (from HeaderCodecData)
44
+ */
45
+ configure(codecData: HeaderCodecData, preferHardware?: boolean): Promise<void>;
46
+ /**
47
+ * Configure the decoder with VideoDecoderConfig directly
48
+ */
49
+ configure(config: VideoDecoderConfig): Promise<void>;
50
+ /**
51
+ * Configure with VideoDecoderConfig
52
+ */
53
+ private configureWithConfig;
54
+ /**
55
+ * Configure with HeaderCodecData (from binary protocol)
56
+ */
57
+ private configureWithCodecData;
58
+ /**
59
+ * Decode a binary packet
60
+ */
61
+ decodeBinary(data: ParsedData): void;
62
+ /**
63
+ * Decode a sample (from file demuxer)
64
+ */
65
+ decode(sample: SampleData): void;
66
+ /**
67
+ * Flush the decoder (async - waits for pending frames)
68
+ */
69
+ flush(): Promise<void>;
70
+ /**
71
+ * Synchronous flush - resets decoder immediately (used for overflow recovery)
72
+ */
73
+ flushSync(): void;
74
+ /**
75
+ * Reset the decoder
76
+ */
77
+ reset(): void;
78
+ /**
79
+ * Dispose the decoder
80
+ */
81
+ dispose(): void;
82
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Web Live Player - A framework-agnostic video streaming library
3
+ *
4
+ * Supports multiple stream sources through dependency injection:
5
+ * - MoQSession (from Elmo or standalone)
6
+ * - WebSocket connections
7
+ * - Custom stream sources
8
+ * - MP4 file playback (client-side demuxing with mp4box)
9
+ */
10
+ export * from './types';
11
+ export * from './sources/stream-source';
12
+ export { BasePlayer } from './player/base-player';
13
+ export type { BasePlayerConfig } from './player/base-player';
14
+ export { LiveVideoPlayer, createPlayer } from './player/live-player';
15
+ export type { PlayerConfig, PlayerStats, PlayerState } from './player/live-player';
16
+ export { FileVideoPlayer, createFilePlayer } from './player/file-player';
17
+ export type { FilePlayerConfig, FilePlayerState, FilePlayerStats, FilePlayMode } from './player/file-player';
18
+ export { createStandaloneMoQSource, StandaloneMoQSource } from './sources/standalone-moq-source';
19
+ export { WebSocketSource, createWebSocketSource } from './sources/websocket-source';
20
+ export type { WebSocketSourceConfig, VideoMetadata } from './sources/websocket-source';
21
+ export { MP4FileSource } from './sources/mp4-file-source';
22
+ export type { MP4FileInfo, DecodableSample, MP4FileSourceEvents } from './sources/mp4-file-source';
23
+ export { WebCodecsDecoder } from './decoders/webcodecs-decoder';
24
+ export type { SampleData } from './decoders/webcodecs-decoder';
25
+ export { WasmDecoder } from './decoders/wasm-decoder';
26
+ export type { YUVFrame, WasmDecoderConfig } from './decoders/wasm-decoder';
27
+ export type { IVideoDecoder, DecoderState, DecodedFrame, VideoDecoderOptions } from './decoders/decoder-interface';
28
+ export { isVideoFrame, isYUVFrame } from './decoders/decoder-interface';
29
+ export { FileAudioPlayer } from './audio/file-audio-player';
30
+ export { LiveAudioPlayer } from './audio/live-audio-player';
31
+ export type { LiveAudioConfig } from './audio/live-audio-player';
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';
35
+ export type { ParsedData, HeaderData, HeaderCodecData } from './protocol/sesame-binary-protocol';