@livepeer-frameworks/player-core 0.0.3

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.
Files changed (120) hide show
  1. package/dist/cjs/index.js +19493 -0
  2. package/dist/cjs/index.js.map +1 -0
  3. package/dist/esm/index.js +19398 -0
  4. package/dist/esm/index.js.map +1 -0
  5. package/dist/player.css +2140 -0
  6. package/dist/types/core/ABRController.d.ts +164 -0
  7. package/dist/types/core/CodecUtils.d.ts +54 -0
  8. package/dist/types/core/Disposable.d.ts +61 -0
  9. package/dist/types/core/EventEmitter.d.ts +73 -0
  10. package/dist/types/core/GatewayClient.d.ts +144 -0
  11. package/dist/types/core/InteractionController.d.ts +121 -0
  12. package/dist/types/core/LiveDurationProxy.d.ts +102 -0
  13. package/dist/types/core/MetaTrackManager.d.ts +220 -0
  14. package/dist/types/core/MistReporter.d.ts +163 -0
  15. package/dist/types/core/MistSignaling.d.ts +148 -0
  16. package/dist/types/core/PlayerController.d.ts +665 -0
  17. package/dist/types/core/PlayerInterface.d.ts +230 -0
  18. package/dist/types/core/PlayerManager.d.ts +182 -0
  19. package/dist/types/core/PlayerRegistry.d.ts +27 -0
  20. package/dist/types/core/QualityMonitor.d.ts +184 -0
  21. package/dist/types/core/ScreenWakeLockManager.d.ts +70 -0
  22. package/dist/types/core/SeekingUtils.d.ts +142 -0
  23. package/dist/types/core/StreamStateClient.d.ts +108 -0
  24. package/dist/types/core/SubtitleManager.d.ts +111 -0
  25. package/dist/types/core/TelemetryReporter.d.ts +79 -0
  26. package/dist/types/core/TimeFormat.d.ts +97 -0
  27. package/dist/types/core/TimerManager.d.ts +83 -0
  28. package/dist/types/core/UrlUtils.d.ts +81 -0
  29. package/dist/types/core/detector.d.ts +149 -0
  30. package/dist/types/core/index.d.ts +49 -0
  31. package/dist/types/core/scorer.d.ts +167 -0
  32. package/dist/types/core/selector.d.ts +9 -0
  33. package/dist/types/index.d.ts +45 -0
  34. package/dist/types/lib/utils.d.ts +2 -0
  35. package/dist/types/players/DashJsPlayer.d.ts +102 -0
  36. package/dist/types/players/HlsJsPlayer.d.ts +70 -0
  37. package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +119 -0
  38. package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +60 -0
  39. package/dist/types/players/MewsWsPlayer/index.d.ts +220 -0
  40. package/dist/types/players/MewsWsPlayer/types.d.ts +89 -0
  41. package/dist/types/players/MistPlayer.d.ts +25 -0
  42. package/dist/types/players/MistWebRTCPlayer/index.d.ts +133 -0
  43. package/dist/types/players/NativePlayer.d.ts +143 -0
  44. package/dist/types/players/VideoJsPlayer.d.ts +59 -0
  45. package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +118 -0
  46. package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +64 -0
  47. package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +63 -0
  48. package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +174 -0
  49. package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +164 -0
  50. package/dist/types/players/WebCodecsPlayer/index.d.ts +149 -0
  51. package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +105 -0
  52. package/dist/types/players/WebCodecsPlayer/types.d.ts +395 -0
  53. package/dist/types/players/WebCodecsPlayer/worker/decoder.worker.d.ts +13 -0
  54. package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +197 -0
  55. package/dist/types/players/index.d.ts +14 -0
  56. package/dist/types/styles/index.d.ts +11 -0
  57. package/dist/types/types.d.ts +363 -0
  58. package/dist/types/vanilla/FrameWorksPlayer.d.ts +143 -0
  59. package/dist/types/vanilla/index.d.ts +19 -0
  60. package/dist/workers/decoder.worker.js +989 -0
  61. package/dist/workers/decoder.worker.js.map +1 -0
  62. package/package.json +80 -0
  63. package/src/core/ABRController.ts +550 -0
  64. package/src/core/CodecUtils.ts +257 -0
  65. package/src/core/Disposable.ts +120 -0
  66. package/src/core/EventEmitter.ts +113 -0
  67. package/src/core/GatewayClient.ts +439 -0
  68. package/src/core/InteractionController.ts +712 -0
  69. package/src/core/LiveDurationProxy.ts +270 -0
  70. package/src/core/MetaTrackManager.ts +753 -0
  71. package/src/core/MistReporter.ts +543 -0
  72. package/src/core/MistSignaling.ts +346 -0
  73. package/src/core/PlayerController.ts +2829 -0
  74. package/src/core/PlayerInterface.ts +432 -0
  75. package/src/core/PlayerManager.ts +900 -0
  76. package/src/core/PlayerRegistry.ts +149 -0
  77. package/src/core/QualityMonitor.ts +597 -0
  78. package/src/core/ScreenWakeLockManager.ts +163 -0
  79. package/src/core/SeekingUtils.ts +364 -0
  80. package/src/core/StreamStateClient.ts +457 -0
  81. package/src/core/SubtitleManager.ts +297 -0
  82. package/src/core/TelemetryReporter.ts +308 -0
  83. package/src/core/TimeFormat.ts +205 -0
  84. package/src/core/TimerManager.ts +209 -0
  85. package/src/core/UrlUtils.ts +179 -0
  86. package/src/core/detector.ts +382 -0
  87. package/src/core/index.ts +140 -0
  88. package/src/core/scorer.ts +553 -0
  89. package/src/core/selector.ts +16 -0
  90. package/src/global.d.ts +11 -0
  91. package/src/index.ts +75 -0
  92. package/src/lib/utils.ts +6 -0
  93. package/src/players/DashJsPlayer.ts +642 -0
  94. package/src/players/HlsJsPlayer.ts +483 -0
  95. package/src/players/MewsWsPlayer/SourceBufferManager.ts +572 -0
  96. package/src/players/MewsWsPlayer/WebSocketManager.ts +241 -0
  97. package/src/players/MewsWsPlayer/index.ts +1065 -0
  98. package/src/players/MewsWsPlayer/types.ts +106 -0
  99. package/src/players/MistPlayer.ts +188 -0
  100. package/src/players/MistWebRTCPlayer/index.ts +703 -0
  101. package/src/players/NativePlayer.ts +820 -0
  102. package/src/players/VideoJsPlayer.ts +643 -0
  103. package/src/players/WebCodecsPlayer/JitterBuffer.ts +299 -0
  104. package/src/players/WebCodecsPlayer/LatencyProfiles.ts +151 -0
  105. package/src/players/WebCodecsPlayer/RawChunkParser.ts +151 -0
  106. package/src/players/WebCodecsPlayer/SyncController.ts +456 -0
  107. package/src/players/WebCodecsPlayer/WebSocketController.ts +564 -0
  108. package/src/players/WebCodecsPlayer/index.ts +1650 -0
  109. package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +379 -0
  110. package/src/players/WebCodecsPlayer/types.ts +542 -0
  111. package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +1360 -0
  112. package/src/players/WebCodecsPlayer/worker/types.ts +276 -0
  113. package/src/players/index.ts +22 -0
  114. package/src/styles/animations.css +21 -0
  115. package/src/styles/index.ts +52 -0
  116. package/src/styles/player.css +2126 -0
  117. package/src/styles/tailwind.css +1015 -0
  118. package/src/types.ts +421 -0
  119. package/src/vanilla/FrameWorksPlayer.ts +367 -0
  120. package/src/vanilla/index.ts +22 -0
@@ -0,0 +1,143 @@
1
+ import { BasePlayer } from '../core/PlayerInterface';
2
+ import type { StreamSource, StreamInfo, PlayerOptions, PlayerCapability } from '../core/PlayerInterface';
3
+ /**
4
+ * Native Player Implementation
5
+ *
6
+ * Handles direct playback using native browser APIs:
7
+ * - HTML5 video element for direct media
8
+ * - WHEP (WebRTC HTTP Egress Protocol) for WebRTC streams
9
+ *
10
+ * Ported from reference html5.js with:
11
+ * - Live duration proxy for meaningful seek bar
12
+ * - Auto-recovery on long pause (reload after 5s)
13
+ * - MP3 seeking restriction
14
+ * - Dynamic source switching via setSource()
15
+ */
16
+ export declare class NativePlayerImpl extends BasePlayer {
17
+ readonly capability: PlayerCapability;
18
+ private peerConnection;
19
+ private sessionUrl;
20
+ private lastInboundStats;
21
+ private reconnectEnabled;
22
+ private reconnectAttempts;
23
+ private maxReconnectAttempts;
24
+ private reconnectTimer;
25
+ private currentWhepUrl;
26
+ private currentHeaders;
27
+ private currentIceServers;
28
+ private container;
29
+ private destroyed;
30
+ private liveDurationProxy;
31
+ private pausedAt;
32
+ private currentSourceUrl;
33
+ private currentMimeType;
34
+ private isMP3Source;
35
+ private liveSeekEnabled;
36
+ private liveSeekOffsetSec;
37
+ private liveSeekBaseUrl;
38
+ private liveSeekListeners;
39
+ private liveSeekTimer;
40
+ private pendingLiveSeekOffset;
41
+ private static readonly PAUSE_RECOVERY_THRESHOLD;
42
+ private static readonly LIVE_SEEK_DEBOUNCE_MS;
43
+ isMimeSupported(mimetype: string): boolean;
44
+ isBrowserSupported(mimetype: string, source: StreamSource, streamInfo: StreamInfo): boolean | string[];
45
+ private translateCodecForHtml5;
46
+ private getAndroidVersion;
47
+ initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions, streamInfo?: StreamInfo): Promise<HTMLVideoElement>;
48
+ /**
49
+ * Setup live duration proxy for meaningful seek bar on live streams
50
+ * Ported from reference html5.js:194-202
51
+ */
52
+ private setupLiveDurationProxy;
53
+ /**
54
+ * Setup auto-recovery on long pause
55
+ * Ported from reference html5.js:227-239
56
+ *
57
+ * If the stream has been paused for more than 5 seconds,
58
+ * reload the stream on play to recover from stale buffer.
59
+ */
60
+ private setupAutoRecovery;
61
+ /**
62
+ * Set a new source URL dynamically
63
+ * Ported from reference html5.js:276-281
64
+ */
65
+ setSource(url: string): void;
66
+ /**
67
+ * Override seek for MP3 files (seeking not supported)
68
+ * Ported from reference html5.js:185-191
69
+ */
70
+ seek(time: number): void;
71
+ /**
72
+ * Get the calculated duration (live-aware)
73
+ */
74
+ getDuration(): number;
75
+ getCurrentTime(): number;
76
+ getSeekableRange(): {
77
+ start: number;
78
+ end: number;
79
+ } | null;
80
+ getBufferedRanges(): TimeRanges | null;
81
+ /**
82
+ * Check if current stream is live
83
+ */
84
+ isLive(): boolean;
85
+ /**
86
+ * Get live latency in seconds
87
+ */
88
+ getLiveLatency(): number;
89
+ /**
90
+ * Jump to live edge
91
+ */
92
+ jumpToLive(): void;
93
+ destroy(): Promise<void>;
94
+ private stripStartUnixParam;
95
+ private buildLiveSeekUrl;
96
+ private applyLiveSeekOffset;
97
+ private createTimeRanges;
98
+ private scheduleLiveSeekOffset;
99
+ /**
100
+ * Get WebRTC-specific stats including RTT, packet loss, jitter, bitrate
101
+ */
102
+ getStats(): Promise<{
103
+ type: 'webrtc';
104
+ video?: {
105
+ bytesReceived: number;
106
+ packetsReceived: number;
107
+ packetsLost: number;
108
+ packetLossRate: number;
109
+ jitter: number;
110
+ framesDecoded: number;
111
+ framesDropped: number;
112
+ frameDropRate: number;
113
+ frameWidth: number;
114
+ frameHeight: number;
115
+ framesPerSecond: number;
116
+ bitrate: number;
117
+ jitterBufferDelay: number;
118
+ };
119
+ audio?: {
120
+ bytesReceived: number;
121
+ packetsReceived: number;
122
+ packetsLost: number;
123
+ packetLossRate: number;
124
+ jitter: number;
125
+ bitrate: number;
126
+ };
127
+ network?: {
128
+ rtt: number;
129
+ availableOutgoingBitrate: number;
130
+ availableIncomingBitrate: number;
131
+ bytesSent: number;
132
+ bytesReceived: number;
133
+ };
134
+ timestamp: number;
135
+ } | undefined>;
136
+ getLatency(): Promise<{
137
+ estimatedMs: number;
138
+ jitterBufferMs: number;
139
+ rttMs: number;
140
+ } | undefined>;
141
+ private startWhep;
142
+ }
143
+ export { NativePlayerImpl as DirectPlaybackPlayerImpl };
@@ -0,0 +1,59 @@
1
+ import { BasePlayer } from '../core/PlayerInterface';
2
+ import type { StreamSource, StreamInfo, PlayerOptions, PlayerCapability } from '../core/PlayerInterface';
3
+ export declare class VideoJsPlayerImpl extends BasePlayer {
4
+ readonly capability: PlayerCapability;
5
+ private videojsPlayer;
6
+ private container;
7
+ private destroyed;
8
+ private timeCorrection;
9
+ private proxyElement;
10
+ private currentStreamInfo;
11
+ private liveDurationProxy;
12
+ isMimeSupported(mimetype: string): boolean;
13
+ isBrowserSupported(mimetype: string, source: StreamSource, streamInfo: StreamInfo): boolean | string[];
14
+ initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions, streamInfo?: StreamInfo): Promise<HTMLVideoElement>;
15
+ /**
16
+ * Creates a Proxy wrapper around the video element that corrects
17
+ * currentTime/duration/buffered using the firstms offset from MistServer.
18
+ * This ensures timestamps align with MistServer's track metadata.
19
+ */
20
+ private createTimeCorrectedProxy;
21
+ private getVideoJsType;
22
+ setPlaybackRate(rate: number): void;
23
+ getCurrentTime(): number;
24
+ getSeekableRange(): {
25
+ start: number;
26
+ end: number;
27
+ } | null;
28
+ /**
29
+ * Seek to time using VideoJS API (fixes backwards seeking in HLS).
30
+ * Time should be in the corrected coordinate space (with firstms offset applied).
31
+ */
32
+ seek(time: number): void;
33
+ /**
34
+ * Get VideoJS-specific stats for playback monitoring
35
+ */
36
+ getStats(): Promise<{
37
+ type: 'videojs';
38
+ buffered: number;
39
+ currentTime: number;
40
+ duration: number;
41
+ readyState: number;
42
+ networkState: number;
43
+ playbackRate: number;
44
+ } | undefined>;
45
+ /**
46
+ * Check if the stream is live
47
+ */
48
+ isLiveStream(): boolean;
49
+ /**
50
+ * Jump to live edge
51
+ * Uses VideoJS liveTracker when available, otherwise LiveDurationProxy
52
+ */
53
+ jumpToLive(): void;
54
+ /**
55
+ * Get latency from live edge (for live streams)
56
+ */
57
+ getLiveLatency(): number;
58
+ destroy(): Promise<void>;
59
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * JitterBuffer - Network Jitter Estimation
3
+ *
4
+ * Tracks network jitter to inform buffer sizing decisions.
5
+ * Ported from legacy rawws.js JitterTracker with improvements:
6
+ * - Per-track jitter tracking (audio/video can differ)
7
+ * - TypeScript types
8
+ * - Better edge case handling
9
+ *
10
+ * Algorithm:
11
+ * 1. Track arrival time vs media time for last N chunks
12
+ * 2. Calculate jitter = (mediaTimePassed / speed) - clockTimePassed
13
+ * 3. Maintain sliding window of peak jitter per second
14
+ * 4. Weighted average: (avgPeak + maxPeak * 2) / 3 + 1ms
15
+ * 5. Limit lowering rate to prevent oscillation
16
+ */
17
+ import type { JitterState } from './types';
18
+ export interface JitterTrackerOptions {
19
+ /** Initial jitter estimate (ms) */
20
+ initialJitter?: number;
21
+ /** Sliding window size for chunks */
22
+ chunkWindowSize?: number;
23
+ /** Sliding window size for peaks */
24
+ peakWindowSize?: number;
25
+ }
26
+ /**
27
+ * JitterTracker - Estimates network jitter for a single track
28
+ */
29
+ export declare class JitterTracker {
30
+ /** Sliding window of chunk timings */
31
+ private chunks;
32
+ /** Current playback speed (1 = realtime) */
33
+ private speed;
34
+ /** Last time a peak was recorded */
35
+ private lastPeakTime;
36
+ /** Maximum jitter observed in current interval */
37
+ private currentPeak;
38
+ /** Sliding window of peak jitter values */
39
+ private peaks;
40
+ /** Weighted average jitter estimate */
41
+ private maxJitter;
42
+ /** Configuration */
43
+ private readonly chunkWindowSize;
44
+ private readonly peakWindowSize;
45
+ constructor(options?: JitterTrackerOptions);
46
+ /**
47
+ * Add a received chunk to jitter calculation
48
+ *
49
+ * @param mediaTime - Media timestamp from chunk (ms)
50
+ * @param receiveTime - Wall clock time (performance.now())
51
+ */
52
+ addChunk(mediaTime: number, receiveTime?: number): void;
53
+ /**
54
+ * Calculate current instantaneous jitter
55
+ */
56
+ private calculateJitter;
57
+ /**
58
+ * Record current peak and update weighted average
59
+ */
60
+ private recordPeak;
61
+ /**
62
+ * Get current jitter estimate (ms)
63
+ */
64
+ get(): number;
65
+ /**
66
+ * Get detailed jitter state
67
+ */
68
+ getState(): JitterState;
69
+ /**
70
+ * Set playback speed for jitter calculation
71
+ */
72
+ setSpeed(speed: number | 'auto'): void;
73
+ /**
74
+ * Reset jitter tracking (e.g., after seek)
75
+ */
76
+ reset(): void;
77
+ /**
78
+ * Full reset including learned jitter estimate
79
+ */
80
+ fullReset(): void;
81
+ }
82
+ /**
83
+ * MultiTrackJitterTracker - Manages jitter tracking for multiple tracks
84
+ */
85
+ export declare class MultiTrackJitterTracker {
86
+ private trackers;
87
+ private globalSpeed;
88
+ private options;
89
+ constructor(options?: JitterTrackerOptions);
90
+ /**
91
+ * Add a chunk for a specific track
92
+ */
93
+ addChunk(trackIndex: number, mediaTime: number, receiveTime?: number): void;
94
+ /**
95
+ * Get maximum jitter across all tracks
96
+ */
97
+ getMax(): number;
98
+ /**
99
+ * Get jitter for a specific track
100
+ */
101
+ getForTrack(trackIndex: number): number;
102
+ /**
103
+ * Set playback speed for all trackers
104
+ */
105
+ setSpeed(speed: number | 'auto'): void;
106
+ /**
107
+ * Reset all trackers
108
+ */
109
+ reset(): void;
110
+ /**
111
+ * Remove a track's tracker
112
+ */
113
+ removeTrack(trackIndex: number): void;
114
+ /**
115
+ * Clear all trackers
116
+ */
117
+ clear(): void;
118
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Latency Profiles for WebCodecs Player
3
+ *
4
+ * Presets for trading off latency vs stability.
5
+ *
6
+ * Buffer calculation: desiredBuffer = keepAway + serverDelay + (jitter * jitterMultiplier)
7
+ *
8
+ * Speed tweaking:
9
+ * - If buffer > desired * speedUpThreshold → speed up to maxSpeedUp
10
+ * - If buffer < desired * speedDownThreshold → slow down to minSpeedDown
11
+ */
12
+ import type { LatencyProfile, LatencyProfileName } from './types';
13
+ /**
14
+ * Ultra-low latency profile
15
+ * Target: <200ms end-to-end latency
16
+ * Use case: Real-time conferencing, remote control
17
+ * Trade-offs: May stutter on poor networks
18
+ */
19
+ export declare const ULTRA_LOW_PROFILE: LatencyProfile;
20
+ /**
21
+ * Low latency profile
22
+ * Target: ~300-500ms end-to-end latency
23
+ * Use case: Live sports, gaming streams
24
+ * Trade-offs: Balanced latency/stability
25
+ */
26
+ export declare const LOW_PROFILE: LatencyProfile;
27
+ /**
28
+ * Balanced profile
29
+ * Target: ~500-1000ms end-to-end latency
30
+ * Use case: General live streaming
31
+ * Trade-offs: Prioritizes stability over latency
32
+ */
33
+ export declare const BALANCED_PROFILE: LatencyProfile;
34
+ /**
35
+ * Quality priority profile
36
+ * Target: ~1-2s end-to-end latency
37
+ * Use case: VOD, recorded content, poor networks
38
+ * Trade-offs: Maximum stability, higher latency
39
+ */
40
+ export declare const QUALITY_PROFILE: LatencyProfile;
41
+ /**
42
+ * All available latency profiles
43
+ */
44
+ export declare const LATENCY_PROFILES: Record<LatencyProfileName, LatencyProfile>;
45
+ /**
46
+ * Get a latency profile by name
47
+ * @param name - Profile name
48
+ * @returns The profile, or 'low' as default
49
+ */
50
+ export declare function getLatencyProfile(name?: LatencyProfileName): LatencyProfile;
51
+ /**
52
+ * Merge a custom partial profile with a base profile
53
+ * @param base - Base profile name or profile object
54
+ * @param custom - Partial overrides
55
+ * @returns Merged profile
56
+ */
57
+ export declare function mergeLatencyProfile(base: LatencyProfileName | LatencyProfile, custom?: Partial<LatencyProfile>): LatencyProfile;
58
+ /**
59
+ * Select appropriate profile based on stream type
60
+ * @param isLive - Whether the stream is live
61
+ * @param preferLowLatency - Whether to prefer low latency (e.g., WebRTC source)
62
+ * @returns Recommended profile name
63
+ */
64
+ export declare function selectDefaultProfile(isLive: boolean, preferLowLatency?: boolean): LatencyProfileName;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * RawChunkParser - Binary Frame Header Parser
3
+ *
4
+ * Parses the 12-byte binary header from MistServer's raw WebSocket stream.
5
+ *
6
+ * Header format:
7
+ * Byte 0: Track index (uint8)
8
+ * Byte 1: Chunk type: 0=delta, 1=key, 2=init
9
+ * Bytes 2-9: Timestamp in milliseconds (uint64 big-endian)
10
+ * Bytes 10-11: Offset in milliseconds (int16 big-endian, signed)
11
+ *
12
+ * The offset is server-calculated and used for A/V synchronization.
13
+ * Combined presentation time = timestamp + offset
14
+ */
15
+ import type { RawChunk } from './types';
16
+ /**
17
+ * Parse a raw binary chunk from MistServer
18
+ *
19
+ * @param data - ArrayBuffer containing header + frame data
20
+ * @returns Parsed RawChunk object
21
+ * @throws Error if data is too short
22
+ */
23
+ export declare function parseRawChunk(data: ArrayBuffer): RawChunk;
24
+ /**
25
+ * Calculate the presentation timestamp for a chunk
26
+ * This combines the server timestamp with the sync offset
27
+ *
28
+ * @param chunk - Parsed raw chunk
29
+ * @returns Presentation timestamp in microseconds (for WebCodecs API)
30
+ */
31
+ export declare function getPresentationTimestamp(chunk: RawChunk): number;
32
+ /**
33
+ * Check if this chunk is a keyframe
34
+ */
35
+ export declare function isKeyframe(chunk: RawChunk): boolean;
36
+ /**
37
+ * Check if this chunk contains codec initialization data
38
+ */
39
+ export declare function isInitData(chunk: RawChunk): boolean;
40
+ /**
41
+ * Format chunk for debug logging
42
+ */
43
+ export declare function formatChunkForLog(chunk: RawChunk): string;
44
+ /**
45
+ * RawChunkParser class for stateful parsing with validation
46
+ */
47
+ export declare class RawChunkParser {
48
+ private debug;
49
+ constructor(options?: {
50
+ debug?: boolean;
51
+ });
52
+ /**
53
+ * Parse binary data from WebSocket
54
+ *
55
+ * @param data - ArrayBuffer from WebSocket message
56
+ * @returns Parsed chunk or null if invalid
57
+ */
58
+ parse(data: ArrayBuffer): RawChunk | null;
59
+ /**
60
+ * Set debug mode
61
+ */
62
+ setDebug(enabled: boolean | 'verbose'): void;
63
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * SyncController - Buffer Management & Playback Timing
3
+ *
4
+ * Orchestrates:
5
+ * - Buffer level monitoring
6
+ * - Adaptive playback speed (catchup/slowdown)
7
+ * - Jitter tracking integration
8
+ * - Server delay estimation
9
+ * - Seek coordination
10
+ *
11
+ * Based on legacy rawws.js FrameTiming + buffer management with improvements:
12
+ * - Post-decode drift correction
13
+ * - Better seek cancellation
14
+ * - TypeScript types
15
+ */
16
+ import type { LatencyProfile, SyncState, TrackInfo } from './types';
17
+ /** Events emitted by SyncController */
18
+ export interface SyncControllerEvents {
19
+ speedchange: {
20
+ speed: number;
21
+ reason: 'catchup' | 'slowdown' | 'normal';
22
+ };
23
+ bufferlow: {
24
+ current: number;
25
+ desired: number;
26
+ };
27
+ bufferhigh: {
28
+ current: number;
29
+ desired: number;
30
+ };
31
+ underrun: void;
32
+ livecatchup: {
33
+ fastForwardMs: number;
34
+ };
35
+ seekstart: {
36
+ seekId: number;
37
+ time: number;
38
+ };
39
+ seekcomplete: {
40
+ seekId: number;
41
+ };
42
+ }
43
+ type EventListener<K extends keyof SyncControllerEvents> = (data: SyncControllerEvents[K]) => void;
44
+ /**
45
+ * SyncController - Manages playback synchronization
46
+ */
47
+ export declare class SyncController {
48
+ private profile;
49
+ private jitterTracker;
50
+ private listeners;
51
+ private mainSpeed;
52
+ private tweakSpeed;
53
+ private lastBufferCheck;
54
+ private bufferCheckInterval;
55
+ private serverDelays;
56
+ private maxServerDelaysSamples;
57
+ private lastLiveCatchup;
58
+ private liveCatchupCooldown;
59
+ private liveCatchupThresholdMs;
60
+ private liveCatchupRequestMs;
61
+ private serverTime;
62
+ private localTimeAtServerUpdate;
63
+ private seekState;
64
+ private isLive;
65
+ private onSpeedChange?;
66
+ private onFastForwardRequest?;
67
+ constructor(options?: {
68
+ profile?: LatencyProfile;
69
+ isLive?: boolean;
70
+ onSpeedChange?: (main: number, tweak: number) => void;
71
+ onFastForwardRequest?: (ms: number) => void;
72
+ });
73
+ /**
74
+ * Update latency profile
75
+ */
76
+ setProfile(profile: LatencyProfile): void;
77
+ /**
78
+ * Update stream type (live vs VOD)
79
+ */
80
+ setLive(isLive: boolean): void;
81
+ /**
82
+ * Record a chunk arrival for jitter tracking
83
+ */
84
+ recordChunkArrival(trackIndex: number, mediaTimeMs: number): void;
85
+ /**
86
+ * Update server time from on_time message
87
+ */
88
+ updateServerTime(currentTime: number): void;
89
+ /**
90
+ * Record server delay measurement
91
+ */
92
+ recordServerDelay(delayMs: number): void;
93
+ /**
94
+ * Get current server delay estimate
95
+ */
96
+ getServerDelay(): number;
97
+ /**
98
+ * Get estimated current server time (interpolated)
99
+ */
100
+ getEstimatedServerTime(): number;
101
+ /**
102
+ * Calculate desired buffer size based on profile + jitter + server delay
103
+ * Matches MistServer mews.js pattern with Chrome-specific handling
104
+ */
105
+ getDesiredBuffer(): number;
106
+ /**
107
+ * Evaluate buffer state and adjust playback speed if needed
108
+ *
109
+ * @param currentBufferMs - Current buffer level in milliseconds
110
+ * @returns Updated sync state
111
+ */
112
+ evaluateBuffer(currentBufferMs: number): SyncState;
113
+ /**
114
+ * Get current sync state
115
+ */
116
+ getState(currentBufferMs?: number): SyncState;
117
+ /**
118
+ * Get combined playback speed (main * tweak)
119
+ */
120
+ getCombinedSpeed(): number;
121
+ /**
122
+ * Set main playback speed (user-controlled)
123
+ */
124
+ setMainSpeed(speed: number): void;
125
+ /**
126
+ * Set tweak speed (automatic adjustment)
127
+ */
128
+ private setTweakSpeed;
129
+ /**
130
+ * Notify external listeners of speed change
131
+ */
132
+ private notifySpeedChange;
133
+ /**
134
+ * Request additional data from server
135
+ */
136
+ private requestFastForward;
137
+ /**
138
+ * Start a seek operation
139
+ * Returns a seek ID that can be used to check if seek is still active
140
+ */
141
+ startSeek(targetTimeMs: number): number;
142
+ /**
143
+ * Check if a seek is still the active one
144
+ */
145
+ isSeekActive(seekId: number): boolean;
146
+ /**
147
+ * Complete a seek operation
148
+ */
149
+ completeSeek(seekId: number): void;
150
+ /**
151
+ * Cancel any active seek
152
+ */
153
+ cancelSeek(): void;
154
+ /**
155
+ * Check if currently seeking
156
+ */
157
+ isSeeking(): boolean;
158
+ /**
159
+ * Register a new track
160
+ */
161
+ addTrack(trackIndex: number, track: TrackInfo): void;
162
+ /**
163
+ * Remove a track
164
+ */
165
+ removeTrack(trackIndex: number): void;
166
+ /**
167
+ * Reset all state
168
+ */
169
+ reset(): void;
170
+ on<K extends keyof SyncControllerEvents>(event: K, listener: EventListener<K>): void;
171
+ off<K extends keyof SyncControllerEvents>(event: K, listener: EventListener<K>): void;
172
+ private emit;
173
+ }
174
+ export {};