@rivmux/runtime-worker 0.5.0 → 1.0.0-rc.1

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 CHANGED
@@ -1,3 +1,9 @@
1
1
  # Rivmux Runtime Worker
2
2
 
3
- Dedicated Worker runtime package for Rivmux media loading and playback orchestration.
3
+ `@rivmux/runtime-worker` Rivmux 主包使用的 Dedicated Worker 运行时,负责 HTTP-FLV 加载、WASM 转封装核心、MSE SourceBuffer、播放延迟控制、重连和生命周期清理。
4
+
5
+ 该包提供 Worker 脚本、WASM 资产和内部生命周期客户端,普通用户不应直接依赖。用户接入请使用 `rivmux`,以获得稳定的播放器 API、类型和错误语义。
6
+
7
+ 当前运行时固定为 Worker MSE;配置在初始化命令中确定,运行期间不支持动态选项更新。播放器公共初始化事件由 facade 暴露为 `initialized`,Worker 内部消息名称不属于公共 API。
8
+
9
+ 维护时需保证 Worker/WASM 资产来自同一次构建,并保持与 `@rivmux/protocol` 的消息契约一致。应用部署必须验证资产 URL、CSP/CORS 和缓存策略,并确保 Worker 与 WASM 资产来自同一版本。
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { NormalizedRivmuxPlayerOptions, PlayerError, WorkerCommand, WorkerMessage } from "@rivmux/protocol";
2
2
  //#region src/index.d.ts
3
- type WorkerLike = Pick<Worker, 'addEventListener' | 'postMessage' | 'removeEventListener' | 'terminate'>;
4
- type RuntimeWorkerFactory = (options: NormalizedRivmuxPlayerOptions) => WorkerLike;
5
- type WorkerClientHooks = {
3
+ export type WorkerLike = Pick<Worker, 'addEventListener' | 'postMessage' | 'removeEventListener' | 'terminate'>;
4
+ export type RuntimeWorkerFactory = (options: NormalizedRivmuxPlayerOptions) => WorkerLike;
5
+ export type WorkerClientHooks = {
6
6
  onMessage(message: WorkerMessage): void;
7
7
  onError(error: PlayerError): void;
8
8
  };
@@ -12,42 +12,48 @@ type WorkerClientHooks = {
12
12
  * Vite rewrites this static URL during the client build and emits the matching
13
13
  * binary next to the application assets.
14
14
  */
15
- declare function getBundledWasmUrl(): string;
16
- declare class WorkerClient {
15
+ export declare function getBundledWasmUrl(): string;
16
+ export declare class WorkerClient {
17
17
  private readonly worker;
18
18
  private readonly hooks;
19
19
  private readonly handleMessage;
20
20
  private readonly handleError;
21
21
  private pendingAttach?;
22
+ private pendingStart?;
22
23
  private pendingStop?;
23
24
  private pendingDestroy?;
24
25
  private workerReady;
25
26
  private queuedCommands;
26
27
  private attachTimer?;
28
+ private startedTimer?;
27
29
  private stoppedTimer?;
28
30
  private destroyedTimer?;
29
31
  constructor(worker: WorkerLike, hooks: WorkerClientHooks);
30
32
  post(command: WorkerCommand): void;
31
33
  waitForMediaSourceHandle(command: WorkerCommand): Promise<void>;
32
34
  waitForStopped(command: WorkerCommand): Promise<void>;
35
+ waitForStarted(command: WorkerCommand): Promise<void>;
33
36
  waitForDestroyed(command: WorkerCommand): Promise<void>;
34
37
  dispose(): void;
35
38
  private handleWorkerMessage;
36
39
  private rejectPendingForWorkerError;
37
40
  private resolveAttach;
38
41
  private resolveStop;
42
+ private resolveStart;
39
43
  private resolveDestroy;
40
44
  private rejectAttach;
41
45
  private rejectStop;
46
+ private rejectStart;
42
47
  private rejectAll;
43
48
  private flushQueuedCommands;
44
49
  private startTimeout;
45
50
  private failClient;
51
+ private notifyMessage;
46
52
  private clearAttachTimer;
47
53
  private clearStoppedTimer;
54
+ private clearStartedTimer;
48
55
  private clearDestroyedTimer;
49
56
  }
50
- declare function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike;
57
+ export declare function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike;
51
58
  //#endregion
52
- export { RuntimeWorkerFactory, WorkerClient, WorkerClientHooks, WorkerLike, createRuntimeWorker, getBundledWasmUrl };
53
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;KAIY,aAAa,KAAK;KAElB,wBAAwB,SAAS,kCAAkC;KAOnE;EACV,UAAU,SAAS;EACnB,QAAQ,OAAO;;;;;;;;iBASD;cAMH;mBACM;mBACA;mBACA;mBAGA;UAIT;UACA;UACA;UACA;UACA;UACA;UACA;UACA;cAEI,QAAQ,YAAY,OAAO;EAOvC,KAAK,SAAS;EASd,yBAAyB,SAAS,gBAAgB;EAYlD,eAAe,SAAS,gBAAgB;EAYxC,iBAAiB,SAAS,gBAAgB;EAY1C;UAOQ;UA+BA;UAQA;UAMA;UAMA;UAMA;UAMA;UAMA;UAaA;UAaA;UAQA;UAKA;UAOA;UAOA;;iBAQM,oBAAoB,SAAS,gCAAgC"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;YAIY,aAAa,KAAK;YAElB,wBAAwB,SAAS,kCAAkC;YAOnE;EACV,UAAU,SAAS;EACnB,QAAQ,OAAO;;;;;;;;wBASD;qBAMH;mBACM;mBACA;mBACA;mBAGA;UAIT;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;EAEI,YAAA,QAAQ,YAAY,OAAO;EAOvC,KAAK,SAAS;EASd,yBAAyB,SAAS,gBAAgB;EAYlD,eAAe,SAAS,gBAAgB;EAYxC,eAAe,SAAS,gBAAgB;EAYxC,iBAAiB,SAAS,gBAAgB;EAY1C;UAOQ;UA4CA;UAQA;UAMA;UAMA;UAMA;UAMA;UAMA;UAMA;UAMA;UAgBA;UAaA;UAQA;UASA;UAQA;UAOA;UAOA;UAOA;;wBA0BM,oBAAoB,SAAS,gCAAgC"}
package/dist/index.js CHANGED
@@ -21,11 +21,13 @@ var WorkerClient = class {
21
21
  this.failClient(error);
22
22
  };
23
23
  pendingAttach;
24
+ pendingStart;
24
25
  pendingStop;
25
26
  pendingDestroy;
26
27
  workerReady = false;
27
28
  queuedCommands = [];
28
29
  attachTimer;
30
+ startedTimer;
29
31
  stoppedTimer;
30
32
  destroyedTimer;
31
33
  constructor(worker, hooks) {
@@ -63,6 +65,17 @@ var WorkerClient = class {
63
65
  this.post(command);
64
66
  });
65
67
  }
68
+ waitForStarted(command) {
69
+ if (this.pendingStart !== void 0) return Promise.reject(createRuntimeWorkerError("RIVMUX_START_IN_PROGRESS", "A start request is already pending.", false));
70
+ return new Promise((resolve, reject) => {
71
+ this.pendingStart = {
72
+ resolve,
73
+ reject
74
+ };
75
+ this.startedTimer = this.startTimeout("RIVMUX_START_TIMEOUT", "Timed out waiting for worker start.", reject);
76
+ this.post(command);
77
+ });
78
+ }
66
79
  waitForDestroyed(command) {
67
80
  if (this.pendingDestroy !== void 0) return Promise.reject(createRuntimeWorkerError("RIVMUX_DESTROY_IN_PROGRESS", "A destroy request is already pending.", false));
68
81
  return new Promise((resolve, reject) => {
@@ -85,23 +98,37 @@ var WorkerClient = class {
85
98
  this.flushQueuedCommands();
86
99
  return;
87
100
  }
88
- this.hooks.onMessage(message);
89
101
  if (message.type === "media-source-handle") {
90
102
  this.resolveAttach();
103
+ this.notifyMessage(message);
104
+ return;
105
+ }
106
+ if (message.type === "started") {
107
+ this.resolveStart();
108
+ this.notifyMessage(message);
91
109
  return;
92
110
  }
93
111
  if (message.type === "stopped") {
94
112
  this.rejectAttach(createRuntimeWorkerError("RIVMUX_ATTACH_CANCELLED", "Media source attachment was cancelled by stop.", false));
113
+ this.rejectStart(createRuntimeWorkerError("RIVMUX_START_CANCELLED", "Start was cancelled by stop.", false));
95
114
  this.resolveStop();
115
+ this.notifyMessage(message);
96
116
  return;
97
117
  }
98
118
  if (message.type === "destroyed") {
99
119
  this.resolveDestroy();
100
120
  this.rejectAttach(createRuntimeWorkerError("RIVMUX_ATTACH_CANCELLED", "Media source attachment was cancelled by destroy.", false));
121
+ this.rejectStart(createRuntimeWorkerError("RIVMUX_START_CANCELLED", "Start was cancelled by destroy.", false));
101
122
  this.rejectStop(createRuntimeWorkerError("RIVMUX_STOP_CANCELLED", "Stop was superseded by destroy.", false));
123
+ this.notifyMessage(message);
124
+ return;
125
+ }
126
+ if (message.type === "error") {
127
+ this.rejectPendingForWorkerError(message.error);
128
+ this.notifyMessage(message);
102
129
  return;
103
130
  }
104
- if (message.type === "error") this.rejectPendingForWorkerError(message.error);
131
+ this.notifyMessage(message);
105
132
  }
106
133
  rejectPendingForWorkerError(error) {
107
134
  if (!error.terminal) return;
@@ -117,6 +144,11 @@ var WorkerClient = class {
117
144
  this.pendingStop?.resolve();
118
145
  this.pendingStop = void 0;
119
146
  }
147
+ resolveStart() {
148
+ this.clearStartedTimer();
149
+ this.pendingStart?.resolve();
150
+ this.pendingStart = void 0;
151
+ }
120
152
  resolveDestroy() {
121
153
  this.clearDestroyedTimer();
122
154
  this.pendingDestroy?.resolve();
@@ -132,15 +164,23 @@ var WorkerClient = class {
132
164
  this.pendingStop?.reject(error);
133
165
  this.pendingStop = void 0;
134
166
  }
167
+ rejectStart(error) {
168
+ this.clearStartedTimer();
169
+ this.pendingStart?.reject(error);
170
+ this.pendingStart = void 0;
171
+ }
135
172
  rejectAll(error) {
136
173
  this.queuedCommands = [];
137
174
  this.clearAttachTimer();
175
+ this.clearStartedTimer();
138
176
  this.clearStoppedTimer();
139
177
  this.clearDestroyedTimer();
140
178
  this.pendingAttach?.reject(error);
179
+ this.pendingStart?.reject(error);
141
180
  this.pendingStop?.reject(error);
142
181
  this.pendingDestroy?.reject(error);
143
182
  this.pendingAttach = void 0;
183
+ this.pendingStart = void 0;
144
184
  this.pendingStop = void 0;
145
185
  this.pendingDestroy = void 0;
146
186
  }
@@ -160,7 +200,18 @@ var WorkerClient = class {
160
200
  }
161
201
  failClient(error) {
162
202
  this.rejectAll(error);
163
- this.hooks.onError(error);
203
+ try {
204
+ this.hooks.onError(error);
205
+ } catch (hookError) {
206
+ reportHookError(hookError);
207
+ }
208
+ }
209
+ notifyMessage(message) {
210
+ try {
211
+ this.hooks.onMessage(message);
212
+ } catch (error) {
213
+ reportHookError(error);
214
+ }
164
215
  }
165
216
  clearAttachTimer() {
166
217
  if (this.attachTimer !== void 0) {
@@ -174,6 +225,12 @@ var WorkerClient = class {
174
225
  this.stoppedTimer = void 0;
175
226
  }
176
227
  }
228
+ clearStartedTimer() {
229
+ if (this.startedTimer !== void 0) {
230
+ clearTimeout(this.startedTimer);
231
+ this.startedTimer = void 0;
232
+ }
233
+ }
177
234
  clearDestroyedTimer() {
178
235
  if (this.destroyedTimer !== void 0) {
179
236
  clearTimeout(this.destroyedTimer);
@@ -181,6 +238,18 @@ var WorkerClient = class {
181
238
  }
182
239
  }
183
240
  };
241
+ function reportHookError(error) {
242
+ try {
243
+ const reportError = globalThis.reportError;
244
+ if (typeof reportError === "function") {
245
+ reportError(error);
246
+ return;
247
+ }
248
+ } catch {}
249
+ try {
250
+ globalThis.console?.error(error);
251
+ } catch {}
252
+ }
184
253
  function createRuntimeWorker(options) {
185
254
  const url = options.runtime.workerUrl === void 0 ? new URL("./rivmux-runtime-worker.js", import.meta.url) : options.runtime.workerUrl;
186
255
  return new Worker(url, {
@@ -189,17 +258,35 @@ function createRuntimeWorker(options) {
189
258
  });
190
259
  }
191
260
  function createRuntimeWorkerError(code, message, terminal, cause) {
192
- return cause === void 0 ? {
261
+ if (cause === void 0) return {
193
262
  kind: "runtime",
194
263
  code,
195
264
  message,
196
265
  terminal
197
- } : {
266
+ };
267
+ return {
198
268
  kind: "runtime",
199
269
  code,
200
270
  message,
201
271
  terminal,
202
- cause
272
+ cause: serializeCause(cause)
273
+ };
274
+ }
275
+ function serializeCause(cause) {
276
+ if (cause instanceof Error) return {
277
+ name: cause.name,
278
+ message: cause.message
279
+ };
280
+ if (typeof cause === "object" && cause !== null) {
281
+ const value = cause;
282
+ return {
283
+ name: typeof value.name === "string" ? value.name : "Error",
284
+ message: typeof value.message === "string" ? value.message : String(cause)
285
+ };
286
+ }
287
+ return {
288
+ name: "Error",
289
+ message: String(cause)
203
290
  };
204
291
  }
205
292
  //#endregion
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { NormalizedRivmuxPlayerOptions, PlayerError, WorkerCommand, WorkerMessage } from '@rivmux/protocol'\n\nconst bundledWasmUrl = new URL('./rivmux-transmux-core.wasm', import.meta.url)\n\nexport type WorkerLike = Pick<Worker, 'addEventListener' | 'postMessage' | 'removeEventListener' | 'terminate'>\n\nexport type RuntimeWorkerFactory = (options: NormalizedRivmuxPlayerOptions) => WorkerLike\n\ntype PendingRequest = {\n resolve: () => void\n reject: (error: PlayerError) => void\n}\n\nexport type WorkerClientHooks = {\n onMessage(message: WorkerMessage): void\n onError(error: PlayerError): void\n}\n\n/**\n * Returns the packaged WASM asset URL for the application bundler to track.\n *\n * Vite rewrites this static URL during the client build and emits the matching\n * binary next to the application assets.\n */\nexport function getBundledWasmUrl(): string {\n return bundledWasmUrl.href\n}\n\nconst REQUEST_TIMEOUT_MS = 5000\n\nexport class WorkerClient {\n private readonly worker: WorkerLike\n private readonly hooks: WorkerClientHooks\n private readonly handleMessage = (event: MessageEvent<WorkerMessage>): void => {\n this.handleWorkerMessage(event.data)\n }\n private readonly handleError = (event: ErrorEvent): void => {\n const error = createRuntimeWorkerError('RIVMUX_WORKER_ERROR', event.message || 'Worker runtime failed.', true, event.error)\n this.failClient(error)\n }\n private pendingAttach?: PendingRequest\n private pendingStop?: PendingRequest\n private pendingDestroy?: PendingRequest\n private workerReady = false\n private queuedCommands: WorkerCommand[] = []\n private attachTimer?: ReturnType<typeof setTimeout>\n private stoppedTimer?: ReturnType<typeof setTimeout>\n private destroyedTimer?: ReturnType<typeof setTimeout>\n\n constructor(worker: WorkerLike, hooks: WorkerClientHooks) {\n this.worker = worker\n this.hooks = hooks\n this.worker.addEventListener('message', this.handleMessage as EventListener)\n this.worker.addEventListener('error', this.handleError as EventListener)\n }\n\n post(command: WorkerCommand): void {\n if (!this.workerReady) {\n this.queuedCommands.push(command)\n return\n }\n\n this.worker.postMessage(command)\n }\n\n waitForMediaSourceHandle(command: WorkerCommand): Promise<void> {\n if (this.pendingAttach !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_ATTACH_IN_PROGRESS', 'A media source attach request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingAttach = { resolve, reject }\n this.attachTimer = this.startTimeout('RIVMUX_ATTACH_TIMEOUT', 'Timed out waiting for worker MediaSourceHandle.', reject)\n this.post(command)\n })\n }\n\n waitForStopped(command: WorkerCommand): Promise<void> {\n if (this.pendingStop !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_STOP_IN_PROGRESS', 'A stop request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingStop = { resolve, reject }\n this.stoppedTimer = this.startTimeout('RIVMUX_STOP_TIMEOUT', 'Timed out waiting for worker stop.', reject)\n this.post(command)\n })\n }\n\n waitForDestroyed(command: WorkerCommand): Promise<void> {\n if (this.pendingDestroy !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_DESTROY_IN_PROGRESS', 'A destroy request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingDestroy = { resolve, reject }\n this.destroyedTimer = this.startTimeout('RIVMUX_DESTROY_TIMEOUT', 'Timed out waiting for worker destroy.', reject)\n this.post(command)\n })\n }\n\n dispose(): void {\n this.rejectAll(createRuntimeWorkerError('RIVMUX_WORKER_DISPOSED', 'Worker client was disposed.', true))\n this.worker.removeEventListener('message', this.handleMessage as EventListener)\n this.worker.removeEventListener('error', this.handleError as EventListener)\n this.worker.terminate()\n }\n\n private handleWorkerMessage(message: WorkerMessage): void {\n if (message.type === 'worker-ready') {\n this.flushQueuedCommands()\n return\n }\n\n this.hooks.onMessage(message)\n\n if (message.type === 'media-source-handle') {\n this.resolveAttach()\n return\n }\n\n if (message.type === 'stopped') {\n this.rejectAttach(createRuntimeWorkerError('RIVMUX_ATTACH_CANCELLED', 'Media source attachment was cancelled by stop.', false))\n this.resolveStop()\n return\n }\n\n if (message.type === 'destroyed') {\n this.resolveDestroy()\n this.rejectAttach(createRuntimeWorkerError('RIVMUX_ATTACH_CANCELLED', 'Media source attachment was cancelled by destroy.', false))\n this.rejectStop(createRuntimeWorkerError('RIVMUX_STOP_CANCELLED', 'Stop was superseded by destroy.', false))\n return\n }\n\n if (message.type === 'error') {\n this.rejectPendingForWorkerError(message.error)\n }\n }\n\n private rejectPendingForWorkerError(error: PlayerError): void {\n if (!error.terminal) {\n return\n }\n\n this.rejectAll(error)\n }\n\n private resolveAttach(): void {\n this.clearAttachTimer()\n this.pendingAttach?.resolve()\n this.pendingAttach = undefined\n }\n\n private resolveStop(): void {\n this.clearStoppedTimer()\n this.pendingStop?.resolve()\n this.pendingStop = undefined\n }\n\n private resolveDestroy(): void {\n this.clearDestroyedTimer()\n this.pendingDestroy?.resolve()\n this.pendingDestroy = undefined\n }\n\n private rejectAttach(error: PlayerError): void {\n this.clearAttachTimer()\n this.pendingAttach?.reject(error)\n this.pendingAttach = undefined\n }\n\n private rejectStop(error: PlayerError): void {\n this.clearStoppedTimer()\n this.pendingStop?.reject(error)\n this.pendingStop = undefined\n }\n\n private rejectAll(error: PlayerError): void {\n this.queuedCommands = []\n this.clearAttachTimer()\n this.clearStoppedTimer()\n this.clearDestroyedTimer()\n this.pendingAttach?.reject(error)\n this.pendingStop?.reject(error)\n this.pendingDestroy?.reject(error)\n this.pendingAttach = undefined\n this.pendingStop = undefined\n this.pendingDestroy = undefined\n }\n\n private flushQueuedCommands(): void {\n if (this.workerReady) {\n return\n }\n\n this.workerReady = true\n const commands = this.queuedCommands\n this.queuedCommands = []\n for (const command of commands) {\n this.worker.postMessage(command)\n }\n }\n\n private startTimeout(code: string, message: string, reject: (error: PlayerError) => void): ReturnType<typeof setTimeout> {\n return setTimeout(() => {\n const error = createRuntimeWorkerError(code, message, true)\n reject(error)\n this.failClient(error)\n }, REQUEST_TIMEOUT_MS)\n }\n\n private failClient(error: PlayerError): void {\n this.rejectAll(error)\n this.hooks.onError(error)\n }\n\n private clearAttachTimer(): void {\n if (this.attachTimer !== undefined) {\n clearTimeout(this.attachTimer)\n this.attachTimer = undefined\n }\n }\n\n private clearStoppedTimer(): void {\n if (this.stoppedTimer !== undefined) {\n clearTimeout(this.stoppedTimer)\n this.stoppedTimer = undefined\n }\n }\n\n private clearDestroyedTimer(): void {\n if (this.destroyedTimer !== undefined) {\n clearTimeout(this.destroyedTimer)\n this.destroyedTimer = undefined\n }\n }\n}\n\nexport function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike {\n const url = options.runtime.workerUrl === undefined ? new URL('./rivmux-runtime-worker.js', import.meta.url) : options.runtime.workerUrl\n\n return new Worker(url, {\n name: 'rivmux-runtime-worker',\n type: 'module',\n })\n}\n\nfunction createRuntimeWorkerError(code: string, message: string, terminal: boolean, cause?: unknown): PlayerError {\n return cause === undefined ? { kind: 'runtime', code, message, terminal } : { kind: 'runtime', code, message, terminal, cause }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { NormalizedRivmuxPlayerOptions, PlayerError, WorkerCommand, WorkerMessage } from '@rivmux/protocol'\n\nconst bundledWasmUrl = new URL('./rivmux-transmux-core.wasm', import.meta.url)\n\nexport type WorkerLike = Pick<Worker, 'addEventListener' | 'postMessage' | 'removeEventListener' | 'terminate'>\n\nexport type RuntimeWorkerFactory = (options: NormalizedRivmuxPlayerOptions) => WorkerLike\n\ntype PendingRequest = {\n resolve: () => void\n reject: (error: PlayerError) => void\n}\n\nexport type WorkerClientHooks = {\n onMessage(message: WorkerMessage): void\n onError(error: PlayerError): void\n}\n\n/**\n * Returns the packaged WASM asset URL for the application bundler to track.\n *\n * Vite rewrites this static URL during the client build and emits the matching\n * binary next to the application assets.\n */\nexport function getBundledWasmUrl(): string {\n return bundledWasmUrl.href\n}\n\nconst REQUEST_TIMEOUT_MS = 5000\n\nexport class WorkerClient {\n private readonly worker: WorkerLike\n private readonly hooks: WorkerClientHooks\n private readonly handleMessage = (event: MessageEvent<WorkerMessage>): void => {\n this.handleWorkerMessage(event.data)\n }\n private readonly handleError = (event: ErrorEvent): void => {\n const error = createRuntimeWorkerError('RIVMUX_WORKER_ERROR', event.message || 'Worker runtime failed.', true, event.error)\n this.failClient(error)\n }\n private pendingAttach?: PendingRequest\n private pendingStart?: PendingRequest\n private pendingStop?: PendingRequest\n private pendingDestroy?: PendingRequest\n private workerReady = false\n private queuedCommands: WorkerCommand[] = []\n private attachTimer?: ReturnType<typeof setTimeout>\n private startedTimer?: ReturnType<typeof setTimeout>\n private stoppedTimer?: ReturnType<typeof setTimeout>\n private destroyedTimer?: ReturnType<typeof setTimeout>\n\n constructor(worker: WorkerLike, hooks: WorkerClientHooks) {\n this.worker = worker\n this.hooks = hooks\n this.worker.addEventListener('message', this.handleMessage as EventListener)\n this.worker.addEventListener('error', this.handleError as EventListener)\n }\n\n post(command: WorkerCommand): void {\n if (!this.workerReady) {\n this.queuedCommands.push(command)\n return\n }\n\n this.worker.postMessage(command)\n }\n\n waitForMediaSourceHandle(command: WorkerCommand): Promise<void> {\n if (this.pendingAttach !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_ATTACH_IN_PROGRESS', 'A media source attach request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingAttach = { resolve, reject }\n this.attachTimer = this.startTimeout('RIVMUX_ATTACH_TIMEOUT', 'Timed out waiting for worker MediaSourceHandle.', reject)\n this.post(command)\n })\n }\n\n waitForStopped(command: WorkerCommand): Promise<void> {\n if (this.pendingStop !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_STOP_IN_PROGRESS', 'A stop request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingStop = { resolve, reject }\n this.stoppedTimer = this.startTimeout('RIVMUX_STOP_TIMEOUT', 'Timed out waiting for worker stop.', reject)\n this.post(command)\n })\n }\n\n waitForStarted(command: WorkerCommand): Promise<void> {\n if (this.pendingStart !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_START_IN_PROGRESS', 'A start request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingStart = { resolve, reject }\n this.startedTimer = this.startTimeout('RIVMUX_START_TIMEOUT', 'Timed out waiting for worker start.', reject)\n this.post(command)\n })\n }\n\n waitForDestroyed(command: WorkerCommand): Promise<void> {\n if (this.pendingDestroy !== undefined) {\n return Promise.reject(createRuntimeWorkerError('RIVMUX_DESTROY_IN_PROGRESS', 'A destroy request is already pending.', false))\n }\n\n return new Promise((resolve, reject) => {\n this.pendingDestroy = { resolve, reject }\n this.destroyedTimer = this.startTimeout('RIVMUX_DESTROY_TIMEOUT', 'Timed out waiting for worker destroy.', reject)\n this.post(command)\n })\n }\n\n dispose(): void {\n this.rejectAll(createRuntimeWorkerError('RIVMUX_WORKER_DISPOSED', 'Worker client was disposed.', true))\n this.worker.removeEventListener('message', this.handleMessage as EventListener)\n this.worker.removeEventListener('error', this.handleError as EventListener)\n this.worker.terminate()\n }\n\n private handleWorkerMessage(message: WorkerMessage): void {\n if (message.type === 'worker-ready') {\n this.flushQueuedCommands()\n return\n }\n\n if (message.type === 'media-source-handle') {\n this.resolveAttach()\n this.notifyMessage(message)\n return\n }\n\n if (message.type === 'started') {\n this.resolveStart()\n this.notifyMessage(message)\n return\n }\n\n if (message.type === 'stopped') {\n this.rejectAttach(createRuntimeWorkerError('RIVMUX_ATTACH_CANCELLED', 'Media source attachment was cancelled by stop.', false))\n this.rejectStart(createRuntimeWorkerError('RIVMUX_START_CANCELLED', 'Start was cancelled by stop.', false))\n this.resolveStop()\n this.notifyMessage(message)\n return\n }\n\n if (message.type === 'destroyed') {\n this.resolveDestroy()\n this.rejectAttach(createRuntimeWorkerError('RIVMUX_ATTACH_CANCELLED', 'Media source attachment was cancelled by destroy.', false))\n this.rejectStart(createRuntimeWorkerError('RIVMUX_START_CANCELLED', 'Start was cancelled by destroy.', false))\n this.rejectStop(createRuntimeWorkerError('RIVMUX_STOP_CANCELLED', 'Stop was superseded by destroy.', false))\n this.notifyMessage(message)\n return\n }\n\n if (message.type === 'error') {\n this.rejectPendingForWorkerError(message.error)\n this.notifyMessage(message)\n return\n }\n\n this.notifyMessage(message)\n }\n\n private rejectPendingForWorkerError(error: PlayerError): void {\n if (!error.terminal) {\n return\n }\n\n this.rejectAll(error)\n }\n\n private resolveAttach(): void {\n this.clearAttachTimer()\n this.pendingAttach?.resolve()\n this.pendingAttach = undefined\n }\n\n private resolveStop(): void {\n this.clearStoppedTimer()\n this.pendingStop?.resolve()\n this.pendingStop = undefined\n }\n\n private resolveStart(): void {\n this.clearStartedTimer()\n this.pendingStart?.resolve()\n this.pendingStart = undefined\n }\n\n private resolveDestroy(): void {\n this.clearDestroyedTimer()\n this.pendingDestroy?.resolve()\n this.pendingDestroy = undefined\n }\n\n private rejectAttach(error: PlayerError): void {\n this.clearAttachTimer()\n this.pendingAttach?.reject(error)\n this.pendingAttach = undefined\n }\n\n private rejectStop(error: PlayerError): void {\n this.clearStoppedTimer()\n this.pendingStop?.reject(error)\n this.pendingStop = undefined\n }\n\n private rejectStart(error: PlayerError): void {\n this.clearStartedTimer()\n this.pendingStart?.reject(error)\n this.pendingStart = undefined\n }\n\n private rejectAll(error: PlayerError): void {\n this.queuedCommands = []\n this.clearAttachTimer()\n this.clearStartedTimer()\n this.clearStoppedTimer()\n this.clearDestroyedTimer()\n this.pendingAttach?.reject(error)\n this.pendingStart?.reject(error)\n this.pendingStop?.reject(error)\n this.pendingDestroy?.reject(error)\n this.pendingAttach = undefined\n this.pendingStart = undefined\n this.pendingStop = undefined\n this.pendingDestroy = undefined\n }\n\n private flushQueuedCommands(): void {\n if (this.workerReady) {\n return\n }\n\n this.workerReady = true\n const commands = this.queuedCommands\n this.queuedCommands = []\n for (const command of commands) {\n this.worker.postMessage(command)\n }\n }\n\n private startTimeout(code: string, message: string, reject: (error: PlayerError) => void): ReturnType<typeof setTimeout> {\n return setTimeout(() => {\n const error = createRuntimeWorkerError(code, message, true)\n reject(error)\n this.failClient(error)\n }, REQUEST_TIMEOUT_MS)\n }\n\n private failClient(error: PlayerError): void {\n this.rejectAll(error)\n try {\n this.hooks.onError(error)\n } catch (hookError) {\n reportHookError(hookError)\n }\n }\n\n private notifyMessage(message: WorkerMessage): void {\n try {\n this.hooks.onMessage(message)\n } catch (error) {\n reportHookError(error)\n }\n }\n\n private clearAttachTimer(): void {\n if (this.attachTimer !== undefined) {\n clearTimeout(this.attachTimer)\n this.attachTimer = undefined\n }\n }\n\n private clearStoppedTimer(): void {\n if (this.stoppedTimer !== undefined) {\n clearTimeout(this.stoppedTimer)\n this.stoppedTimer = undefined\n }\n }\n\n private clearStartedTimer(): void {\n if (this.startedTimer !== undefined) {\n clearTimeout(this.startedTimer)\n this.startedTimer = undefined\n }\n }\n\n private clearDestroyedTimer(): void {\n if (this.destroyedTimer !== undefined) {\n clearTimeout(this.destroyedTimer)\n this.destroyedTimer = undefined\n }\n }\n}\n\nfunction reportHookError(error: unknown): void {\n try {\n const reportError = (globalThis as typeof globalThis & { reportError?: (error: unknown) => void }).reportError\n if (typeof reportError === 'function') {\n reportError(error)\n return\n }\n } catch {\n // Fall through to the non-throwing console fallback.\n }\n\n try {\n globalThis.console?.error(error)\n } catch {\n // Hook error reporting must never affect worker lifecycle state.\n }\n}\n\nexport function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike {\n const url = options.runtime.workerUrl === undefined ? new URL('./rivmux-runtime-worker.js', import.meta.url) : options.runtime.workerUrl\n\n return new Worker(url, {\n name: 'rivmux-runtime-worker',\n type: 'module',\n })\n}\n\nfunction createRuntimeWorkerError(code: string, message: string, terminal: boolean, cause?: unknown): PlayerError {\n if (cause === undefined) {\n return { kind: 'runtime', code, message, terminal }\n }\n\n return {\n kind: 'runtime',\n code,\n message,\n terminal,\n cause: serializeCause(cause),\n }\n}\n\nfunction serializeCause(cause: unknown): { name: string; message: string } {\n if (cause instanceof Error) {\n return { name: cause.name, message: cause.message }\n }\n\n if (typeof cause === 'object' && cause !== null) {\n const value = cause as { name?: unknown; message?: unknown }\n return {\n name: typeof value.name === 'string' ? value.name : 'Error',\n message: typeof value.message === 'string' ? value.message : String(cause),\n }\n }\n\n return { name: 'Error', message: String(cause) }\n}\n"],"mappings":";AAEA,MAAM,iBAAiB,IAAI,IAAI,+BAA+B,YAAY,GAAG;;;;;;;AAsB7E,SAAgB,oBAA4B;CAC1C,OAAO,eAAe;AACxB;AAEA,MAAM,qBAAqB;AAE3B,IAAa,eAAb,MAA0B;CACxB;CACA;CACA,iBAAkC,UAA6C;EAC7E,KAAK,oBAAoB,MAAM,IAAI;CACrC;CACA,eAAgC,UAA4B;EAC1D,MAAM,QAAQ,yBAAyB,uBAAuB,MAAM,WAAW,0BAA0B,MAAM,MAAM,KAAK;EAC1H,KAAK,WAAW,KAAK;CACvB;CACA;CACA;CACA;CACA;CACA,cAAsB;CACtB,iBAA0C,CAAC;CAC3C;CACA;CACA;CACA;CAEA,YAAY,QAAoB,OAA0B;EACxD,KAAK,SAAS;EACd,KAAK,QAAQ;EACb,KAAK,OAAO,iBAAiB,WAAW,KAAK,aAA8B;EAC3E,KAAK,OAAO,iBAAiB,SAAS,KAAK,WAA4B;CACzE;CAEA,KAAK,SAA8B;EACjC,IAAI,CAAC,KAAK,aAAa;GACrB,KAAK,eAAe,KAAK,OAAO;GAChC;EACF;EAEA,KAAK,OAAO,YAAY,OAAO;CACjC;CAEA,yBAAyB,SAAuC;EAC9D,IAAI,KAAK,kBAAkB,KAAA,GACzB,OAAO,QAAQ,OAAO,yBAAyB,6BAA6B,qDAAqD,KAAK,CAAC;EAGzI,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAK,gBAAgB;IAAE;IAAS;GAAO;GACvC,KAAK,cAAc,KAAK,aAAa,yBAAyB,mDAAmD,MAAM;GACvH,KAAK,KAAK,OAAO;EACnB,CAAC;CACH;CAEA,eAAe,SAAuC;EACpD,IAAI,KAAK,gBAAgB,KAAA,GACvB,OAAO,QAAQ,OAAO,yBAAyB,2BAA2B,sCAAsC,KAAK,CAAC;EAGxH,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAK,cAAc;IAAE;IAAS;GAAO;GACrC,KAAK,eAAe,KAAK,aAAa,uBAAuB,sCAAsC,MAAM;GACzG,KAAK,KAAK,OAAO;EACnB,CAAC;CACH;CAEA,eAAe,SAAuC;EACpD,IAAI,KAAK,iBAAiB,KAAA,GACxB,OAAO,QAAQ,OAAO,yBAAyB,4BAA4B,uCAAuC,KAAK,CAAC;EAG1H,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAK,eAAe;IAAE;IAAS;GAAO;GACtC,KAAK,eAAe,KAAK,aAAa,wBAAwB,uCAAuC,MAAM;GAC3G,KAAK,KAAK,OAAO;EACnB,CAAC;CACH;CAEA,iBAAiB,SAAuC;EACtD,IAAI,KAAK,mBAAmB,KAAA,GAC1B,OAAO,QAAQ,OAAO,yBAAyB,8BAA8B,yCAAyC,KAAK,CAAC;EAG9H,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,KAAK,iBAAiB;IAAE;IAAS;GAAO;GACxC,KAAK,iBAAiB,KAAK,aAAa,0BAA0B,yCAAyC,MAAM;GACjH,KAAK,KAAK,OAAO;EACnB,CAAC;CACH;CAEA,UAAgB;EACd,KAAK,UAAU,yBAAyB,0BAA0B,+BAA+B,IAAI,CAAC;EACtG,KAAK,OAAO,oBAAoB,WAAW,KAAK,aAA8B;EAC9E,KAAK,OAAO,oBAAoB,SAAS,KAAK,WAA4B;EAC1E,KAAK,OAAO,UAAU;CACxB;CAEA,oBAA4B,SAA8B;EACxD,IAAI,QAAQ,SAAS,gBAAgB;GACnC,KAAK,oBAAoB;GACzB;EACF;EAEA,IAAI,QAAQ,SAAS,uBAAuB;GAC1C,KAAK,cAAc;GACnB,KAAK,cAAc,OAAO;GAC1B;EACF;EAEA,IAAI,QAAQ,SAAS,WAAW;GAC9B,KAAK,aAAa;GAClB,KAAK,cAAc,OAAO;GAC1B;EACF;EAEA,IAAI,QAAQ,SAAS,WAAW;GAC9B,KAAK,aAAa,yBAAyB,2BAA2B,kDAAkD,KAAK,CAAC;GAC9H,KAAK,YAAY,yBAAyB,0BAA0B,gCAAgC,KAAK,CAAC;GAC1G,KAAK,YAAY;GACjB,KAAK,cAAc,OAAO;GAC1B;EACF;EAEA,IAAI,QAAQ,SAAS,aAAa;GAChC,KAAK,eAAe;GACpB,KAAK,aAAa,yBAAyB,2BAA2B,qDAAqD,KAAK,CAAC;GACjI,KAAK,YAAY,yBAAyB,0BAA0B,mCAAmC,KAAK,CAAC;GAC7G,KAAK,WAAW,yBAAyB,yBAAyB,mCAAmC,KAAK,CAAC;GAC3G,KAAK,cAAc,OAAO;GAC1B;EACF;EAEA,IAAI,QAAQ,SAAS,SAAS;GAC5B,KAAK,4BAA4B,QAAQ,KAAK;GAC9C,KAAK,cAAc,OAAO;GAC1B;EACF;EAEA,KAAK,cAAc,OAAO;CAC5B;CAEA,4BAAoC,OAA0B;EAC5D,IAAI,CAAC,MAAM,UACT;EAGF,KAAK,UAAU,KAAK;CACtB;CAEA,gBAA8B;EAC5B,KAAK,iBAAiB;EACtB,KAAK,eAAe,QAAQ;EAC5B,KAAK,gBAAgB,KAAA;CACvB;CAEA,cAA4B;EAC1B,KAAK,kBAAkB;EACvB,KAAK,aAAa,QAAQ;EAC1B,KAAK,cAAc,KAAA;CACrB;CAEA,eAA6B;EAC3B,KAAK,kBAAkB;EACvB,KAAK,cAAc,QAAQ;EAC3B,KAAK,eAAe,KAAA;CACtB;CAEA,iBAA+B;EAC7B,KAAK,oBAAoB;EACzB,KAAK,gBAAgB,QAAQ;EAC7B,KAAK,iBAAiB,KAAA;CACxB;CAEA,aAAqB,OAA0B;EAC7C,KAAK,iBAAiB;EACtB,KAAK,eAAe,OAAO,KAAK;EAChC,KAAK,gBAAgB,KAAA;CACvB;CAEA,WAAmB,OAA0B;EAC3C,KAAK,kBAAkB;EACvB,KAAK,aAAa,OAAO,KAAK;EAC9B,KAAK,cAAc,KAAA;CACrB;CAEA,YAAoB,OAA0B;EAC5C,KAAK,kBAAkB;EACvB,KAAK,cAAc,OAAO,KAAK;EAC/B,KAAK,eAAe,KAAA;CACtB;CAEA,UAAkB,OAA0B;EAC1C,KAAK,iBAAiB,CAAC;EACvB,KAAK,iBAAiB;EACtB,KAAK,kBAAkB;EACvB,KAAK,kBAAkB;EACvB,KAAK,oBAAoB;EACzB,KAAK,eAAe,OAAO,KAAK;EAChC,KAAK,cAAc,OAAO,KAAK;EAC/B,KAAK,aAAa,OAAO,KAAK;EAC9B,KAAK,gBAAgB,OAAO,KAAK;EACjC,KAAK,gBAAgB,KAAA;EACrB,KAAK,eAAe,KAAA;EACpB,KAAK,cAAc,KAAA;EACnB,KAAK,iBAAiB,KAAA;CACxB;CAEA,sBAAoC;EAClC,IAAI,KAAK,aACP;EAGF,KAAK,cAAc;EACnB,MAAM,WAAW,KAAK;EACtB,KAAK,iBAAiB,CAAC;EACvB,KAAK,MAAM,WAAW,UACpB,KAAK,OAAO,YAAY,OAAO;CAEnC;CAEA,aAAqB,MAAc,SAAiB,QAAqE;EACvH,OAAO,iBAAiB;GACtB,MAAM,QAAQ,yBAAyB,MAAM,SAAS,IAAI;GAC1D,OAAO,KAAK;GACZ,KAAK,WAAW,KAAK;EACvB,GAAG,kBAAkB;CACvB;CAEA,WAAmB,OAA0B;EAC3C,KAAK,UAAU,KAAK;EACpB,IAAI;GACF,KAAK,MAAM,QAAQ,KAAK;EAC1B,SAAS,WAAW;GAClB,gBAAgB,SAAS;EAC3B;CACF;CAEA,cAAsB,SAA8B;EAClD,IAAI;GACF,KAAK,MAAM,UAAU,OAAO;EAC9B,SAAS,OAAO;GACd,gBAAgB,KAAK;EACvB;CACF;CAEA,mBAAiC;EAC/B,IAAI,KAAK,gBAAgB,KAAA,GAAW;GAClC,aAAa,KAAK,WAAW;GAC7B,KAAK,cAAc,KAAA;EACrB;CACF;CAEA,oBAAkC;EAChC,IAAI,KAAK,iBAAiB,KAAA,GAAW;GACnC,aAAa,KAAK,YAAY;GAC9B,KAAK,eAAe,KAAA;EACtB;CACF;CAEA,oBAAkC;EAChC,IAAI,KAAK,iBAAiB,KAAA,GAAW;GACnC,aAAa,KAAK,YAAY;GAC9B,KAAK,eAAe,KAAA;EACtB;CACF;CAEA,sBAAoC;EAClC,IAAI,KAAK,mBAAmB,KAAA,GAAW;GACrC,aAAa,KAAK,cAAc;GAChC,KAAK,iBAAiB,KAAA;EACxB;CACF;AACF;AAEA,SAAS,gBAAgB,OAAsB;CAC7C,IAAI;EACF,MAAM,cAAe,WAA8E;EACnG,IAAI,OAAO,gBAAgB,YAAY;GACrC,YAAY,KAAK;GACjB;EACF;CACF,QAAQ,CAER;CAEA,IAAI;EACF,WAAW,SAAS,MAAM,KAAK;CACjC,QAAQ,CAER;AACF;AAEA,SAAgB,oBAAoB,SAAoD;CACtF,MAAM,MAAM,QAAQ,QAAQ,cAAc,KAAA,IAAY,IAAI,IAAI,8BAA8B,YAAY,GAAG,IAAI,QAAQ,QAAQ;CAE/H,OAAO,IAAI,OAAO,KAAK;EACrB,MAAM;EACN,MAAM;CACR,CAAC;AACH;AAEA,SAAS,yBAAyB,MAAc,SAAiB,UAAmB,OAA8B;CAChH,IAAI,UAAU,KAAA,GACZ,OAAO;EAAE,MAAM;EAAW;EAAM;EAAS;CAAS;CAGpD,OAAO;EACL,MAAM;EACN;EACA;EACA;EACA,OAAO,eAAe,KAAK;CAC7B;AACF;AAEA,SAAS,eAAe,OAAmD;CACzE,IAAI,iBAAiB,OACnB,OAAO;EAAE,MAAM,MAAM;EAAM,SAAS,MAAM;CAAQ;CAGpD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAC/C,MAAM,QAAQ;EACd,OAAO;GACL,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;GACpD,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU,OAAO,KAAK;EAC3E;CACF;CAEA,OAAO;EAAE,MAAM;EAAS,SAAS,OAAO,KAAK;CAAE;AACjD"}
@@ -1,4 +1,4 @@
1
- import { NormalizedNetworkOptions, NormalizedRivmuxPlayerOptions, PlayerError, WorkerCommand, WorkerMessage } from "@rivmux/protocol";
1
+ import { NormalizedNetworkOptions, NormalizedRivmuxPlayerOptions, PlayerError, ReconnectReason, WorkerCommand, WorkerMessage } from "@rivmux/protocol";
2
2
  //#region src/latency/buffer-ranges.d.ts
3
3
  type BufferedRange = {
4
4
  start: number;
@@ -22,7 +22,8 @@ type StreamLoaderConfig = {
22
22
  network: NormalizedNetworkOptions;
23
23
  fetch?: typeof fetch;
24
24
  now?: () => number;
25
- sleep?: (ms: number, signal: AbortSignal) => Promise<void>;
25
+ setTimeout?: (callback: () => void, ms: number) => ReturnType<typeof setTimeout>;
26
+ clearTimeout?: (timer: ReturnType<typeof setTimeout>) => void;
26
27
  };
27
28
  type StreamLoader = {
28
29
  readonly closed: boolean;
@@ -118,7 +119,7 @@ type TransmuxCoreWasmConstructor = new () => {
118
119
  reset(): void;
119
120
  destroy(): void;
120
121
  };
121
- declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
122
+ export declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
122
123
  private readonly core;
123
124
  constructor(Core: TransmuxCoreWasmConstructor);
124
125
  pushChunk(chunk: Uint8Array): CoreEvent[];
@@ -126,7 +127,7 @@ declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
126
127
  reset(): void;
127
128
  destroy(): void;
128
129
  }
129
- declare function normalizeCoreEvents(value: unknown): CoreEvent[];
130
+ export declare function normalizeCoreEvents(value: unknown): CoreEvent[];
130
131
  //#endregion
131
132
  //#region src/runtime/types.d.ts
132
133
  type RuntimeMseCleanupOptions = {
@@ -162,13 +163,17 @@ type RuntimeWorkerDependencies = {
162
163
  createTransmuxCore?: (options: NormalizedRivmuxPlayerOptions) => TransmuxCoreHost | undefined | Promise<TransmuxCoreHost | undefined>;
163
164
  detectRuntime?: () => PlayerError | undefined;
164
165
  now?: () => number;
166
+ sleep?: (delayMs: number, signal: AbortSignal) => Promise<void>;
167
+ random?: () => number;
165
168
  };
166
169
  //#endregion
167
170
  //#region src/runtime/index.d.ts
168
- declare class RuntimeWorker {
171
+ export declare class RuntimeWorker {
169
172
  private readonly port;
170
173
  private readonly detectRuntime;
171
174
  private readonly now;
175
+ private readonly sleep;
176
+ private readonly random;
172
177
  private state;
173
178
  private url?;
174
179
  private options?;
@@ -184,6 +189,10 @@ declare class RuntimeWorker {
184
189
  private lifecycleGeneration;
185
190
  private lifecycleAbortController;
186
191
  private fatalCleanupPromise;
192
+ private recoveryPromise?;
193
+ private connectionAttempt;
194
+ private recoveryStartedAt?;
195
+ private pendingRecovery?;
187
196
  constructor(port: RuntimeWorkerPort, dependencies?: RuntimeWorkerDependencies);
188
197
  handleCommand(command: WorkerCommand): Promise<void>;
189
198
  private executeCommand;
@@ -193,6 +202,11 @@ declare class RuntimeWorker {
193
202
  private destroy;
194
203
  private startLoader;
195
204
  private closeLoader;
205
+ private scheduleRecovery;
206
+ private recover;
207
+ private markRecovered;
208
+ private waitForRecovery;
209
+ private resetRecoveryCycle;
196
210
  private postStats;
197
211
  private collectMseStats;
198
212
  private quotaCleanupCutoff;
@@ -210,24 +224,37 @@ declare class RuntimeWorker {
210
224
  }
211
225
  //#endregion
212
226
  //#region src/loader/http-flv-loader.d.ts
213
- declare class HttpFlvLoaderError extends Error {
227
+ type HttpFlvLoaderErrorPhase = 'open' | 'read';
228
+ type HttpFlvLoaderErrorOptions = {
229
+ phase: HttpFlvLoaderErrorPhase;
230
+ reason?: ReconnectReason;
231
+ status?: number;
232
+ cause?: unknown;
233
+ };
234
+ /** Structured failure raised by one HTTP-FLV connection. */
235
+ export declare class HttpFlvLoaderError extends Error {
214
236
  readonly code: string;
237
+ readonly phase: HttpFlvLoaderErrorPhase;
238
+ readonly reason?: ReconnectReason;
215
239
  readonly status?: number;
216
- constructor(code: string, message: string, status?: number);
240
+ readonly cause?: unknown;
241
+ constructor(code: string, message: string, options?: HttpFlvLoaderErrorOptions | number);
217
242
  }
218
- declare class HttpFlvLoader implements StreamLoader {
243
+ export declare class HttpFlvLoader implements StreamLoader {
219
244
  private readonly url;
220
245
  private readonly headers;
221
246
  private readonly credentials;
222
- private readonly retry;
247
+ private readonly readIdleTimeoutMs;
223
248
  private readonly fetchImpl;
224
249
  private readonly now;
225
- private readonly sleep;
250
+ private readonly setTimer;
251
+ private readonly clearTimer;
226
252
  private abortController?;
227
253
  private reader?;
228
254
  private state;
229
255
  private pausedState;
230
256
  private resumeWaiters;
257
+ private activeReadTimeout?;
231
258
  private readonly mutableStats;
232
259
  constructor(config: StreamLoaderConfig);
233
260
  get closed(): boolean;
@@ -238,13 +265,12 @@ declare class HttpFlvLoader implements StreamLoader {
238
265
  pause(): void;
239
266
  resume(): void;
240
267
  close(): Promise<void>;
241
- private openAttempt;
242
268
  private waitUntilResumed;
243
269
  private resolveResumeWaiters;
244
270
  }
245
271
  //#endregion
246
272
  //#region src/mse/mse-controller.d.ts
247
- declare class MseController {
273
+ export declare class MseController {
248
274
  private mediaSource?;
249
275
  private readonly sourceBuffers;
250
276
  private readonly queues;
@@ -273,7 +299,7 @@ type MseCleanupOptions = {
273
299
  };
274
300
  //#endregion
275
301
  //#region src/mse/source-buffer-queue.d.ts
276
- declare class SourceBufferQueue {
302
+ export declare class SourceBufferQueue {
277
303
  private readonly sourceBuffer;
278
304
  private readonly queue;
279
305
  private pendingDrain?;
@@ -297,10 +323,10 @@ declare class SourceBufferQueue {
297
323
  }
298
324
  //#endregion
299
325
  //#region src/mse/mime.d.ts
300
- declare function isMseSupported(mimeType: string): boolean;
326
+ export declare function isMseSupported(mimeType: string): boolean;
301
327
  //#endregion
302
328
  //#region src/wasm/wasm-loader.d.ts
303
- declare function createWasmTransmuxCoreHost(Core: TransmuxCoreWasmConstructor | undefined): TransmuxCoreHost;
329
+ export declare function createWasmTransmuxCoreHost(Core: TransmuxCoreWasmConstructor | undefined): TransmuxCoreHost;
304
330
  //#endregion
305
331
  //#region src/worker-entry.d.ts
306
332
  type DedicatedWorkerScopeLike = {
@@ -308,7 +334,7 @@ type DedicatedWorkerScopeLike = {
308
334
  postMessage(message: WorkerMessage, transfer?: Transferable[]): void;
309
335
  close(): void;
310
336
  };
311
- declare function startRuntimeWorker(scope: DedicatedWorkerScopeLike): RuntimeWorker;
337
+ export declare function startRuntimeWorker(scope: DedicatedWorkerScopeLike): RuntimeWorker;
312
338
  //#endregion
313
- export { type CoreEvent, HttpFlvLoader, HttpFlvLoaderError, MseController, RuntimeWorker, SourceBufferQueue, type StreamChunk, type StreamLoader, type StreamLoaderConfig, type StreamLoaderStats, type TransmuxCoreHost, type TransmuxCoreWasmConstructor, WasmTransmuxCoreHost, createWasmTransmuxCoreHost, isMseSupported, normalizeCoreEvents, startRuntimeWorker };
339
+ export type { CoreEvent, StreamChunk, StreamLoader, StreamLoaderConfig, StreamLoaderStats, TransmuxCoreHost, TransmuxCoreWasmConstructor };
314
340
  //# sourceMappingURL=rivmux-runtime-worker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rivmux-runtime-worker.d.ts","names":[],"sources":["../src/latency/buffer-ranges.ts","../src/loader/loader.ts","../src/wasm/rivmux-transmux-wasm.ts","../src/runtime/types.ts","../src/runtime/index.ts","../src/loader/http-flv-loader.ts","../src/mse/mse-controller.ts","../src/mse/source-buffer-queue.ts","../src/mse/mime.ts","../src/wasm/wasm-loader.ts","../src/worker-entry.ts"],"mappings":"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"}
1
+ {"version":3,"file":"rivmux-runtime-worker.d.ts","names":[],"sources":["../src/latency/buffer-ranges.ts","../src/loader/loader.ts","../src/wasm/rivmux-transmux-wasm.ts","../src/runtime/types.ts","../src/runtime/index.ts","../src/loader/http-flv-loader.ts","../src/mse/mse-controller.ts","../src/mse/source-buffer-queue.ts","../src/mse/mime.ts","../src/wasm/wasm-loader.ts","../src/worker-entry.ts"],"mappings":"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"}