@rivmux/runtime-worker 0.4.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,39 +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;
44
+ private rejectAttach;
45
+ private rejectStop;
46
+ private rejectStart;
40
47
  private rejectAll;
41
48
  private flushQueuedCommands;
42
49
  private startTimeout;
50
+ private failClient;
51
+ private notifyMessage;
43
52
  private clearAttachTimer;
44
53
  private clearStoppedTimer;
54
+ private clearStartedTimer;
45
55
  private clearDestroyedTimer;
46
56
  }
47
- declare function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike;
57
+ export declare function createRuntimeWorker(options: NormalizedRivmuxPlayerOptions): WorkerLike;
48
58
  //#endregion
49
- export { RuntimeWorkerFactory, WorkerClient, WorkerClientHooks, WorkerLike, createRuntimeWorker, getBundledWasmUrl };
50
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;UAKT;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;UA4BA;UAQA;UAMA;UAMA;UAMA;UAaA;UAaA;UAQA;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
@@ -18,15 +18,16 @@ var WorkerClient = class {
18
18
  };
19
19
  handleError = (event) => {
20
20
  const error = createRuntimeWorkerError("RIVMUX_WORKER_ERROR", event.message || "Worker runtime failed.", true, event.error);
21
- this.rejectAll(error);
22
- this.hooks.onError(error);
21
+ this.failClient(error);
23
22
  };
24
23
  pendingAttach;
24
+ pendingStart;
25
25
  pendingStop;
26
26
  pendingDestroy;
27
27
  workerReady = false;
28
28
  queuedCommands = [];
29
29
  attachTimer;
30
+ startedTimer;
30
31
  stoppedTimer;
31
32
  destroyedTimer;
32
33
  constructor(worker, hooks) {
@@ -64,6 +65,17 @@ var WorkerClient = class {
64
65
  this.post(command);
65
66
  });
66
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
+ }
67
79
  waitForDestroyed(command) {
68
80
  if (this.pendingDestroy !== void 0) return Promise.reject(createRuntimeWorkerError("RIVMUX_DESTROY_IN_PROGRESS", "A destroy request is already pending.", false));
69
81
  return new Promise((resolve, reject) => {
@@ -86,20 +98,37 @@ var WorkerClient = class {
86
98
  this.flushQueuedCommands();
87
99
  return;
88
100
  }
89
- this.hooks.onMessage(message);
90
101
  if (message.type === "media-source-handle") {
91
102
  this.resolveAttach();
103
+ this.notifyMessage(message);
104
+ return;
105
+ }
106
+ if (message.type === "started") {
107
+ this.resolveStart();
108
+ this.notifyMessage(message);
92
109
  return;
93
110
  }
94
111
  if (message.type === "stopped") {
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();
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));
122
+ this.rejectStop(createRuntimeWorkerError("RIVMUX_STOP_CANCELLED", "Stop was superseded by destroy.", false));
123
+ this.notifyMessage(message);
100
124
  return;
101
125
  }
102
- if (message.type === "error") this.rejectPendingForWorkerError(message.error);
126
+ if (message.type === "error") {
127
+ this.rejectPendingForWorkerError(message.error);
128
+ this.notifyMessage(message);
129
+ return;
130
+ }
131
+ this.notifyMessage(message);
103
132
  }
104
133
  rejectPendingForWorkerError(error) {
105
134
  if (!error.terminal) return;
@@ -115,20 +144,43 @@ var WorkerClient = class {
115
144
  this.pendingStop?.resolve();
116
145
  this.pendingStop = void 0;
117
146
  }
147
+ resolveStart() {
148
+ this.clearStartedTimer();
149
+ this.pendingStart?.resolve();
150
+ this.pendingStart = void 0;
151
+ }
118
152
  resolveDestroy() {
119
153
  this.clearDestroyedTimer();
120
154
  this.pendingDestroy?.resolve();
121
155
  this.pendingDestroy = void 0;
122
156
  }
157
+ rejectAttach(error) {
158
+ this.clearAttachTimer();
159
+ this.pendingAttach?.reject(error);
160
+ this.pendingAttach = void 0;
161
+ }
162
+ rejectStop(error) {
163
+ this.clearStoppedTimer();
164
+ this.pendingStop?.reject(error);
165
+ this.pendingStop = void 0;
166
+ }
167
+ rejectStart(error) {
168
+ this.clearStartedTimer();
169
+ this.pendingStart?.reject(error);
170
+ this.pendingStart = void 0;
171
+ }
123
172
  rejectAll(error) {
124
173
  this.queuedCommands = [];
125
174
  this.clearAttachTimer();
175
+ this.clearStartedTimer();
126
176
  this.clearStoppedTimer();
127
177
  this.clearDestroyedTimer();
128
178
  this.pendingAttach?.reject(error);
179
+ this.pendingStart?.reject(error);
129
180
  this.pendingStop?.reject(error);
130
181
  this.pendingDestroy?.reject(error);
131
182
  this.pendingAttach = void 0;
183
+ this.pendingStart = void 0;
132
184
  this.pendingStop = void 0;
133
185
  this.pendingDestroy = void 0;
134
186
  }
@@ -143,9 +195,24 @@ var WorkerClient = class {
143
195
  return setTimeout(() => {
144
196
  const error = createRuntimeWorkerError(code, message, true);
145
197
  reject(error);
146
- this.rejectAll(error);
198
+ this.failClient(error);
147
199
  }, REQUEST_TIMEOUT_MS);
148
200
  }
201
+ failClient(error) {
202
+ this.rejectAll(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
+ }
215
+ }
149
216
  clearAttachTimer() {
150
217
  if (this.attachTimer !== void 0) {
151
218
  clearTimeout(this.attachTimer);
@@ -158,6 +225,12 @@ var WorkerClient = class {
158
225
  this.stoppedTimer = void 0;
159
226
  }
160
227
  }
228
+ clearStartedTimer() {
229
+ if (this.startedTimer !== void 0) {
230
+ clearTimeout(this.startedTimer);
231
+ this.startedTimer = void 0;
232
+ }
233
+ }
161
234
  clearDestroyedTimer() {
162
235
  if (this.destroyedTimer !== void 0) {
163
236
  clearTimeout(this.destroyedTimer);
@@ -165,6 +238,18 @@ var WorkerClient = class {
165
238
  }
166
239
  }
167
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
+ }
168
253
  function createRuntimeWorker(options) {
169
254
  const url = options.runtime.workerUrl === void 0 ? new URL("./rivmux-runtime-worker.js", import.meta.url) : options.runtime.workerUrl;
170
255
  return new Worker(url, {
@@ -173,17 +258,35 @@ function createRuntimeWorker(options) {
173
258
  });
174
259
  }
175
260
  function createRuntimeWorkerError(code, message, terminal, cause) {
176
- return cause === void 0 ? {
261
+ if (cause === void 0) return {
177
262
  kind: "runtime",
178
263
  code,
179
264
  message,
180
265
  terminal
181
- } : {
266
+ };
267
+ return {
182
268
  kind: "runtime",
183
269
  code,
184
270
  message,
185
271
  terminal,
186
- 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)
187
290
  };
188
291
  }
189
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.rejectAll(error)\n this.hooks.onError(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.resolveStop()\n return\n }\n\n if (message.type === 'destroyed') {\n this.resolveDestroy()\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 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.rejectAll(error)\n }, REQUEST_TIMEOUT_MS)\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":"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"}
@@ -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;
@@ -88,16 +89,10 @@ type CoreEvent = {
88
89
  type: 'mediaSegment';
89
90
  data: CoreMediaSegment;
90
91
  } | {
91
- type: 'videoConfig';
92
+ type: 'trackConfig';
92
93
  data: unknown;
93
94
  } | {
94
- type: 'audioConfig';
95
- data: unknown;
96
- } | {
97
- type: 'videoSample';
98
- data: unknown;
99
- } | {
100
- type: 'audioSample';
95
+ type: 'sample';
101
96
  data: unknown;
102
97
  } | {
103
98
  type: 'metadata';
@@ -124,7 +119,7 @@ type TransmuxCoreWasmConstructor = new () => {
124
119
  reset(): void;
125
120
  destroy(): void;
126
121
  };
127
- declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
122
+ export declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
128
123
  private readonly core;
129
124
  constructor(Core: TransmuxCoreWasmConstructor);
130
125
  pushChunk(chunk: Uint8Array): CoreEvent[];
@@ -132,9 +127,9 @@ declare class WasmTransmuxCoreHost implements TransmuxCoreHost {
132
127
  reset(): void;
133
128
  destroy(): void;
134
129
  }
135
- declare function normalizeCoreEvents(value: unknown): CoreEvent[];
130
+ export declare function normalizeCoreEvents(value: unknown): CoreEvent[];
136
131
  //#endregion
137
- //#region src/runtime.d.ts
132
+ //#region src/runtime/types.d.ts
138
133
  type RuntimeMseCleanupOptions = {
139
134
  force?: boolean;
140
135
  };
@@ -168,75 +163,98 @@ type RuntimeWorkerDependencies = {
168
163
  createTransmuxCore?: (options: NormalizedRivmuxPlayerOptions) => TransmuxCoreHost | undefined | Promise<TransmuxCoreHost | undefined>;
169
164
  detectRuntime?: () => PlayerError | undefined;
170
165
  now?: () => number;
166
+ sleep?: (delayMs: number, signal: AbortSignal) => Promise<void>;
167
+ random?: () => number;
171
168
  };
172
- declare class RuntimeWorker {
169
+ //#endregion
170
+ //#region src/runtime/index.d.ts
171
+ export declare class RuntimeWorker {
173
172
  private readonly port;
174
- private readonly createMseController;
175
- private readonly createLoader;
176
- private readonly createTransmuxCore;
177
173
  private readonly detectRuntime;
178
174
  private readonly now;
175
+ private readonly sleep;
176
+ private readonly random;
179
177
  private state;
180
178
  private url?;
181
179
  private options?;
182
- private mse?;
183
- private loader?;
184
- private transmuxCore?;
180
+ private readonly session;
185
181
  private latencyController?;
186
182
  private videoState?;
187
183
  private lastLatencyMetrics;
188
184
  private statsTimer?;
189
185
  private statsTickInFlight;
190
- private loaderRunId;
191
- private outputBytes;
192
186
  private appendQueueMaxLength;
193
187
  private appendQueueMaxBytes;
188
+ private commandTail;
189
+ private lifecycleGeneration;
190
+ private lifecycleAbortController;
191
+ private fatalCleanupPromise;
192
+ private recoveryPromise?;
193
+ private connectionAttempt;
194
+ private recoveryStartedAt?;
195
+ private pendingRecovery?;
194
196
  constructor(port: RuntimeWorkerPort, dependencies?: RuntimeWorkerDependencies);
195
197
  handleCommand(command: WorkerCommand): Promise<void>;
198
+ private executeCommand;
196
199
  private attachMediaSource;
197
200
  private start;
198
201
  private stop;
199
202
  private destroy;
200
203
  private startLoader;
201
- private runLoader;
202
204
  private closeLoader;
203
- private closeCurrentLoader;
204
- private isCurrentLoader;
205
+ private scheduleRecovery;
206
+ private recover;
207
+ private markRecovered;
208
+ private waitForRecovery;
209
+ private resetRecoveryCycle;
205
210
  private postStats;
206
- private processTransmuxEvents;
207
211
  private collectMseStats;
208
- private appendToMse;
209
- private retryAppendAfterQuotaCleanup;
210
212
  private quotaCleanupCutoff;
211
213
  private applyLatencyPolicy;
212
214
  private startStatsTimer;
213
215
  private stopStatsTimer;
214
216
  private emitStatsTick;
217
+ private currentLifecycleContext;
218
+ private isLifecycleContextCurrent;
215
219
  private fail;
216
220
  private failWithError;
217
221
  private enterFatalErrorState;
218
222
  private post;
223
+ private invalidateLifecycle;
219
224
  }
220
225
  //#endregion
221
226
  //#region src/loader/http-flv-loader.d.ts
222
- 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 {
223
236
  readonly code: string;
237
+ readonly phase: HttpFlvLoaderErrorPhase;
238
+ readonly reason?: ReconnectReason;
224
239
  readonly status?: number;
225
- constructor(code: string, message: string, status?: number);
240
+ readonly cause?: unknown;
241
+ constructor(code: string, message: string, options?: HttpFlvLoaderErrorOptions | number);
226
242
  }
227
- declare class HttpFlvLoader implements StreamLoader {
243
+ export declare class HttpFlvLoader implements StreamLoader {
228
244
  private readonly url;
229
245
  private readonly headers;
230
246
  private readonly credentials;
231
- private readonly retry;
247
+ private readonly readIdleTimeoutMs;
232
248
  private readonly fetchImpl;
233
249
  private readonly now;
234
- private readonly sleep;
250
+ private readonly setTimer;
251
+ private readonly clearTimer;
235
252
  private abortController?;
236
253
  private reader?;
237
254
  private state;
238
255
  private pausedState;
239
256
  private resumeWaiters;
257
+ private activeReadTimeout?;
240
258
  private readonly mutableStats;
241
259
  constructor(config: StreamLoaderConfig);
242
260
  get closed(): boolean;
@@ -247,13 +265,12 @@ declare class HttpFlvLoader implements StreamLoader {
247
265
  pause(): void;
248
266
  resume(): void;
249
267
  close(): Promise<void>;
250
- private openAttempt;
251
268
  private waitUntilResumed;
252
269
  private resolveResumeWaiters;
253
270
  }
254
271
  //#endregion
255
272
  //#region src/mse/mse-controller.d.ts
256
- declare class MseController {
273
+ export declare class MseController {
257
274
  private mediaSource?;
258
275
  private readonly sourceBuffers;
259
276
  private readonly queues;
@@ -282,7 +299,7 @@ type MseCleanupOptions = {
282
299
  };
283
300
  //#endregion
284
301
  //#region src/mse/source-buffer-queue.d.ts
285
- declare class SourceBufferQueue {
302
+ export declare class SourceBufferQueue {
286
303
  private readonly sourceBuffer;
287
304
  private readonly queue;
288
305
  private pendingDrain?;
@@ -306,10 +323,10 @@ declare class SourceBufferQueue {
306
323
  }
307
324
  //#endregion
308
325
  //#region src/mse/mime.d.ts
309
- declare function isMseSupported(mimeType: string): boolean;
326
+ export declare function isMseSupported(mimeType: string): boolean;
310
327
  //#endregion
311
328
  //#region src/wasm/wasm-loader.d.ts
312
- declare function createWasmTransmuxCoreHost(Core: TransmuxCoreWasmConstructor | undefined): TransmuxCoreHost;
329
+ export declare function createWasmTransmuxCoreHost(Core: TransmuxCoreWasmConstructor | undefined): TransmuxCoreHost;
313
330
  //#endregion
314
331
  //#region src/worker-entry.d.ts
315
332
  type DedicatedWorkerScopeLike = {
@@ -317,7 +334,7 @@ type DedicatedWorkerScopeLike = {
317
334
  postMessage(message: WorkerMessage, transfer?: Transferable[]): void;
318
335
  close(): void;
319
336
  };
320
- declare function startRuntimeWorker(scope: DedicatedWorkerScopeLike): RuntimeWorker;
337
+ export declare function startRuntimeWorker(scope: DedicatedWorkerScopeLike): RuntimeWorker;
321
338
  //#endregion
322
- 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 };
323
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.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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"}