html-video-element-webworker-polyfill 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -9
- package/dist/auto.js +1 -1
- package/dist/{document-GIe-DKmi.js → document-BhePs2Wq.js} +120 -20
- package/dist/document-BhePs2Wq.js.map +1 -0
- package/dist/{host-D-rmvsLs.js → host-C01-_SSZ.js} +113 -19
- package/dist/host-C01-_SSZ.js.map +1 -0
- package/dist/host.d.ts +1 -1
- package/dist/host.js +1 -1
- package/dist/{index-B9gWpxKE.d.ts → index-DaAgPNC9.d.ts} +6 -2
- package/dist/{index-RizJW9Vb.d.ts → index-DfmcCbjK.d.ts} +4 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/{install-BDVttfHM.js → install-BV6rqIiK.js} +2 -2
- package/dist/{install-BDVttfHM.js.map → install-BV6rqIiK.js.map} +1 -1
- package/dist/{protocol-Be-N8xdd.js → protocol--LD8Qk5Y.js} +2 -1
- package/dist/protocol--LD8Qk5Y.js.map +1 -0
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +2 -2
- package/package.json +14 -12
- package/dist/document-GIe-DKmi.js.map +0 -1
- package/dist/host-D-rmvsLs.js.map +0 -1
- package/dist/protocol-Be-N8xdd.js.map +0 -1
package/README.md
CHANGED
|
@@ -78,17 +78,46 @@ video.requestVideoFrameCallback(function onFrame() {
|
|
|
78
78
|
video.dispose();
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
Set an `id` right after creating an element to find its real `<video>` on the main thread, for example to put it on
|
|
82
|
+
the page. Existing `document.createElement("video")` code works unchanged:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
createVideoHost(worker, {
|
|
86
|
+
onVideoCreated(video) {
|
|
87
|
+
if (video.id === "preview") document.querySelector("#slot")!.append(video);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const video = document.createElement("video");
|
|
94
|
+
video.id = "preview";
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or take control of a `<video>` that is already on the page:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { connectToHostVideo } from "html-video-element-webworker-polyfill/worker";
|
|
101
|
+
|
|
102
|
+
const video = await connectToHostVideo("#player");
|
|
103
|
+
video.currentTime = 10;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The element stays where it is. Changes made by the page, such as native controls or other scripts, reach the worker,
|
|
107
|
+
and `dispose()` only releases control. Pass `canConnect` to `createVideoHost` to restrict which elements a worker may
|
|
108
|
+
take over.
|
|
109
|
+
|
|
81
110
|
## API
|
|
82
111
|
|
|
83
|
-
| Import | Exports
|
|
84
|
-
| ---------------------------------------------------- |
|
|
85
|
-
| `html-video-element-webworker-polyfill/host` | `createVideoHost(worker, { container? })` — main thread
|
|
86
|
-
| `html-video-element-webworker-polyfill/worker` | `createVideoElement()`, `WorkerVideoElement`, `polyfillDocument()` — [`document.createElement`][createElement]
|
|
87
|
-
| `html-video-element-webworker-polyfill/canvas2d` | `polyfill2dCanvasApi()` — [`drawImage`][drawImage], [`createPattern`][createPattern]
|
|
88
|
-
| `html-video-element-webworker-polyfill/webgl` | `polyfillWebglAPI()` — [`texImage2D`][texImage2D] and friends, [WebGL][WebGL] 1 and 2
|
|
89
|
-
| `html-video-element-webworker-polyfill/webgpu` | `polyfillWebgpu()` — [`copyExternalImageToTexture`][copyExternalImageToTexture], [`importExternalTexture`][importExternalTexture]
|
|
90
|
-
| `html-video-element-webworker-polyfill/image-bitmap` | `polyfillCreateImageBitmap()` — [`createImageBitmap`][createImageBitmap], `polyfillVideoFrame()` — [`new VideoFrame`][VideoFrame constructor]
|
|
91
|
-
| `html-video-element-webworker-polyfill/auto` | installs every worker polyfill
|
|
112
|
+
| Import | Exports |
|
|
113
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
114
|
+
| `html-video-element-webworker-polyfill/host` | `createVideoHost(worker, { container?, onVideoCreated?, canConnect? })` — main thread |
|
|
115
|
+
| `html-video-element-webworker-polyfill/worker` | `createVideoElement()`, `connectToHostVideo(selector)`, `WorkerVideoElement`, `polyfillDocument()` — [`document.createElement`][createElement] |
|
|
116
|
+
| `html-video-element-webworker-polyfill/canvas2d` | `polyfill2dCanvasApi()` — [`drawImage`][drawImage], [`createPattern`][createPattern] |
|
|
117
|
+
| `html-video-element-webworker-polyfill/webgl` | `polyfillWebglAPI()` — [`texImage2D`][texImage2D] and friends, [WebGL][WebGL] 1 and 2 |
|
|
118
|
+
| `html-video-element-webworker-polyfill/webgpu` | `polyfillWebgpu()` — [`copyExternalImageToTexture`][copyExternalImageToTexture], [`importExternalTexture`][importExternalTexture] |
|
|
119
|
+
| `html-video-element-webworker-polyfill/image-bitmap` | `polyfillCreateImageBitmap()` — [`createImageBitmap`][createImageBitmap], `polyfillVideoFrame()` — [`new VideoFrame`][VideoFrame constructor] |
|
|
120
|
+
| `html-video-element-webworker-polyfill/auto` | installs every worker polyfill |
|
|
92
121
|
|
|
93
122
|
Each entry point is tree-shakeable, so you only ship what you import.
|
|
94
123
|
|
package/dist/auto.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as isProtocolMessage, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol
|
|
1
|
+
import { a as isProtocolMessage, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol--LD8Qk5Y.js";
|
|
2
2
|
import { a as isMessageEndpoint, r as assertWorker } from "./environment-De2r8LaA.js";
|
|
3
3
|
import { t as FRAME_SOURCE } from "./frame-source-BG--PzqD.js";
|
|
4
4
|
//#region src/worker/bridge.ts
|
|
@@ -7,12 +7,16 @@ var Bridge = class {
|
|
|
7
7
|
endpoint;
|
|
8
8
|
timeOffset = 0;
|
|
9
9
|
#seq = 0;
|
|
10
|
+
#outbox = [];
|
|
11
|
+
#outboxTransfer = [];
|
|
12
|
+
#flushScheduled = false;
|
|
10
13
|
#nextId = 1;
|
|
11
14
|
#nextCallId = 1;
|
|
12
15
|
#receivers = /* @__PURE__ */ new Map();
|
|
13
16
|
#pinned = /* @__PURE__ */ new Set();
|
|
14
17
|
#calls = /* @__PURE__ */ new Map();
|
|
15
18
|
#canPlayType = /* @__PURE__ */ new Map();
|
|
19
|
+
#ids = /* @__PURE__ */ new Map();
|
|
16
20
|
#registry;
|
|
17
21
|
#welcomed = false;
|
|
18
22
|
#missingHostTimer;
|
|
@@ -42,13 +46,31 @@ var Bridge = class {
|
|
|
42
46
|
}
|
|
43
47
|
post(message, transfer = []) {
|
|
44
48
|
const seq = ++this.#seq;
|
|
45
|
-
this.
|
|
49
|
+
this.#outbox.push({
|
|
46
50
|
...message,
|
|
47
51
|
[CHANNEL]: 1,
|
|
48
52
|
seq
|
|
49
|
-
}
|
|
53
|
+
});
|
|
54
|
+
this.#outboxTransfer.push(...transfer);
|
|
55
|
+
if (!this.#flushScheduled) {
|
|
56
|
+
this.#flushScheduled = true;
|
|
57
|
+
queueMicrotask(this.#flush);
|
|
58
|
+
}
|
|
50
59
|
return seq;
|
|
51
60
|
}
|
|
61
|
+
#flush = () => {
|
|
62
|
+
this.#flushScheduled = false;
|
|
63
|
+
const messages = this.#outbox;
|
|
64
|
+
const transfer = this.#outboxTransfer;
|
|
65
|
+
this.#outbox = [];
|
|
66
|
+
this.#outboxTransfer = [];
|
|
67
|
+
if (messages.length === 1) this.endpoint.postMessage(messages[0], transfer);
|
|
68
|
+
else if (messages.length > 1) this.endpoint.postMessage({
|
|
69
|
+
[CHANNEL]: 1,
|
|
70
|
+
kind: "batch",
|
|
71
|
+
messages
|
|
72
|
+
}, transfer);
|
|
73
|
+
};
|
|
52
74
|
call(message, transfer) {
|
|
53
75
|
const callId = this.#nextCallId++;
|
|
54
76
|
const promise = new Promise((resolve, reject) => this.#calls.set(callId, {
|
|
@@ -72,6 +94,15 @@ var Bridge = class {
|
|
|
72
94
|
this.#registry?.unregister(receiver);
|
|
73
95
|
this.#pinned.delete(element);
|
|
74
96
|
}
|
|
97
|
+
claimId(id, element) {
|
|
98
|
+
if (id === "") return;
|
|
99
|
+
const owner = this.#ids.get(id)?.deref();
|
|
100
|
+
if (owner && owner !== element && !owner.disposed) throw new DOMException(`html-video-element-webworker-polyfill: a video element with id "${id}" already exists in this worker.`, "InvalidStateError");
|
|
101
|
+
this.#ids.set(id, new WeakRef(element));
|
|
102
|
+
}
|
|
103
|
+
releaseId(id, element) {
|
|
104
|
+
if (this.#ids.get(id)?.deref() === element) this.#ids.delete(id);
|
|
105
|
+
}
|
|
75
106
|
pin(element, pinned) {
|
|
76
107
|
if (pinned) this.#pinned.add(element);
|
|
77
108
|
else this.#pinned.delete(element);
|
|
@@ -205,6 +236,7 @@ var WorkerMediaError = class {
|
|
|
205
236
|
};
|
|
206
237
|
//#endregion
|
|
207
238
|
//#region src/worker/video-element.ts
|
|
239
|
+
const CONNECT = Symbol("connect");
|
|
208
240
|
const EMPTY_STATE = {
|
|
209
241
|
currentSrc: "",
|
|
210
242
|
currentTime: 0,
|
|
@@ -223,7 +255,8 @@ const EMPTY_STATE = {
|
|
|
223
255
|
buffered: [],
|
|
224
256
|
played: [],
|
|
225
257
|
seekable: [],
|
|
226
|
-
quality: null
|
|
258
|
+
quality: null,
|
|
259
|
+
props: {}
|
|
227
260
|
};
|
|
228
261
|
const LOAD_RESET = {
|
|
229
262
|
currentTime: 0,
|
|
@@ -291,8 +324,18 @@ const ATTRIBUTES = {
|
|
|
291
324
|
width: {
|
|
292
325
|
prop: "width",
|
|
293
326
|
type: "number"
|
|
327
|
+
},
|
|
328
|
+
id: {
|
|
329
|
+
prop: "id",
|
|
330
|
+
type: "string"
|
|
294
331
|
}
|
|
295
332
|
};
|
|
333
|
+
function frameReleaser(holder) {
|
|
334
|
+
return () => {
|
|
335
|
+
holder.current?.close();
|
|
336
|
+
holder.current = null;
|
|
337
|
+
};
|
|
338
|
+
}
|
|
296
339
|
var Internals = class {
|
|
297
340
|
element;
|
|
298
341
|
bridge;
|
|
@@ -307,6 +350,7 @@ var Internals = class {
|
|
|
307
350
|
disablePictureInPicture: false,
|
|
308
351
|
disableRemotePlayback: false,
|
|
309
352
|
height: 0,
|
|
353
|
+
id: "",
|
|
310
354
|
loop: false,
|
|
311
355
|
playsInline: false,
|
|
312
356
|
poster: "",
|
|
@@ -324,20 +368,47 @@ var Internals = class {
|
|
|
324
368
|
handlers = /* @__PURE__ */ new Map();
|
|
325
369
|
loadSeq = 0;
|
|
326
370
|
disposed = false;
|
|
327
|
-
|
|
371
|
+
ready;
|
|
372
|
+
constructor(element, bridge, selector) {
|
|
328
373
|
this.element = element;
|
|
329
374
|
this.bridge = bridge;
|
|
330
375
|
this.id = bridge.nextId();
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
376
|
+
bridge.register(this.id, element, this, frameReleaser(this.frame));
|
|
377
|
+
if (selector === void 0) {
|
|
378
|
+
bridge.post({
|
|
379
|
+
kind: "create",
|
|
380
|
+
id: this.id,
|
|
381
|
+
props: {}
|
|
382
|
+
});
|
|
383
|
+
this.ready = Promise.resolve();
|
|
384
|
+
} else this.ready = this.connect(selector);
|
|
385
|
+
}
|
|
386
|
+
async connect(selector) {
|
|
387
|
+
const [seq, result] = this.bridge.call({
|
|
388
|
+
kind: "connect",
|
|
338
389
|
id: this.id,
|
|
339
|
-
|
|
390
|
+
selector
|
|
340
391
|
});
|
|
392
|
+
const connected = await result;
|
|
393
|
+
this.applyState(seq, connected.state);
|
|
394
|
+
if (connected.frame) this.setFrame(connected.frame);
|
|
395
|
+
}
|
|
396
|
+
markProps(seq, ...props) {
|
|
397
|
+
if (!seq) return;
|
|
398
|
+
for (const prop of props) this.localWrites.set(`props.${prop}`, seq);
|
|
399
|
+
}
|
|
400
|
+
applyProps(ack, props) {
|
|
401
|
+
for (const [prop, value] of Object.entries(props)) {
|
|
402
|
+
const key = `props.${prop}`;
|
|
403
|
+
const pending = this.localWrites.get(key);
|
|
404
|
+
if (pending !== void 0) {
|
|
405
|
+
if (pending > ack) continue;
|
|
406
|
+
this.localWrites.delete(key);
|
|
407
|
+
}
|
|
408
|
+
if (prop === "src") this.src = value;
|
|
409
|
+
else if (prop === "hasSrcAttribute") this.hasSrcAttribute = value;
|
|
410
|
+
else if (prop in this.props) this.props[prop] = value;
|
|
411
|
+
}
|
|
341
412
|
}
|
|
342
413
|
write(prop, value, local = {}, transfer) {
|
|
343
414
|
if (this.disposed) return 0;
|
|
@@ -379,6 +450,10 @@ var Internals = class {
|
|
|
379
450
|
applyState(ack, state) {
|
|
380
451
|
const target = this.state;
|
|
381
452
|
for (const [key, value] of Object.entries(state)) {
|
|
453
|
+
if (key === "props") {
|
|
454
|
+
this.applyProps(ack, value);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
382
457
|
const pending = this.localWrites.get(key);
|
|
383
458
|
if (pending !== void 0) {
|
|
384
459
|
if (pending > ack) continue;
|
|
@@ -480,7 +555,7 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
480
555
|
super();
|
|
481
556
|
const bridge = bridgeFor(options.transport);
|
|
482
557
|
bridge.watchForHost();
|
|
483
|
-
internals.set(this, new Internals(this, bridge));
|
|
558
|
+
internals.set(this, new Internals(this, bridge, options[CONNECT]));
|
|
484
559
|
}
|
|
485
560
|
get currentFrame() {
|
|
486
561
|
const frame = $(this).frame.current;
|
|
@@ -500,6 +575,7 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
500
575
|
core.setFrame(null);
|
|
501
576
|
core.frameCallbacks.clear();
|
|
502
577
|
core.bridge.unregister(core.id, core, this);
|
|
578
|
+
core.bridge.releaseId(core.props.id, this);
|
|
503
579
|
core.state = { ...EMPTY_STATE };
|
|
504
580
|
core.localWrites.clear();
|
|
505
581
|
}
|
|
@@ -513,11 +589,13 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
513
589
|
const core = $(this);
|
|
514
590
|
core.src = core.resolveUrl(String(value));
|
|
515
591
|
core.hasSrcAttribute = true;
|
|
516
|
-
core.
|
|
592
|
+
const seq = core.write("src", core.src, {
|
|
517
593
|
...LOAD_RESET,
|
|
518
594
|
currentSrc: "",
|
|
519
595
|
networkState: 0
|
|
520
|
-
})
|
|
596
|
+
});
|
|
597
|
+
core.markLoad(seq);
|
|
598
|
+
core.markProps(seq, "src", "hasSrcAttribute");
|
|
521
599
|
}
|
|
522
600
|
get srcObject() {
|
|
523
601
|
return $(this).srcObject;
|
|
@@ -657,6 +735,16 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
657
735
|
set disableRemotePlayback(value) {
|
|
658
736
|
this.#mirror("disableRemotePlayback", Boolean(value));
|
|
659
737
|
}
|
|
738
|
+
get id() {
|
|
739
|
+
return $(this).props.id;
|
|
740
|
+
}
|
|
741
|
+
set id(value) {
|
|
742
|
+
const core = $(this);
|
|
743
|
+
const id = String(value);
|
|
744
|
+
core.bridge.claimId(id, this);
|
|
745
|
+
if (core.props.id !== id) core.bridge.releaseId(core.props.id, this);
|
|
746
|
+
this.#mirror("id", id);
|
|
747
|
+
}
|
|
660
748
|
get height() {
|
|
661
749
|
return $(this).props.height;
|
|
662
750
|
}
|
|
@@ -707,7 +795,7 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
707
795
|
#mirror(prop, value) {
|
|
708
796
|
const core = $(this);
|
|
709
797
|
core.props[prop] = value;
|
|
710
|
-
core.write(prop, value);
|
|
798
|
+
core.markProps(core.write(prop, value), prop);
|
|
711
799
|
}
|
|
712
800
|
getAttribute(name) {
|
|
713
801
|
const core = $(this);
|
|
@@ -745,7 +833,7 @@ var WorkerVideoElement = class extends EventTarget {
|
|
|
745
833
|
if (attribute.prop === "src") {
|
|
746
834
|
core.src = "";
|
|
747
835
|
core.hasSrcAttribute = false;
|
|
748
|
-
core.invoke("removeAttribute", ["src"]);
|
|
836
|
+
core.markProps(core.invoke("removeAttribute", ["src"]), "src", "hasSrcAttribute");
|
|
749
837
|
return;
|
|
750
838
|
}
|
|
751
839
|
const target = this;
|
|
@@ -844,6 +932,18 @@ for (const type of MEDIA_EVENTS) Object.defineProperty(WorkerVideoElement.protot
|
|
|
844
932
|
function createVideoElement(options) {
|
|
845
933
|
return new WorkerVideoElement(options);
|
|
846
934
|
}
|
|
935
|
+
function connectToHostVideo(selector, options = {}) {
|
|
936
|
+
assertWorker("connectToHostVideo()");
|
|
937
|
+
if (typeof selector !== "string" || selector.trim() === "") throw new TypeError("html-video-element-webworker-polyfill: connectToHostVideo() expects a CSS selector string.");
|
|
938
|
+
const video = new WorkerVideoElement({
|
|
939
|
+
...options,
|
|
940
|
+
[CONNECT]: selector
|
|
941
|
+
});
|
|
942
|
+
return $(video).ready.then(() => video, (error) => {
|
|
943
|
+
video.dispose();
|
|
944
|
+
throw error;
|
|
945
|
+
});
|
|
946
|
+
}
|
|
847
947
|
//#endregion
|
|
848
948
|
//#region src/worker/document.ts
|
|
849
949
|
const PATCHED = Symbol.for("html-video-element-webworker-polyfill.patched");
|
|
@@ -874,6 +974,6 @@ function isVideo(tagName) {
|
|
|
874
974
|
return String(tagName).toLowerCase() === "video";
|
|
875
975
|
}
|
|
876
976
|
//#endregion
|
|
877
|
-
export {
|
|
977
|
+
export { WorkerMediaError as a, createVideoElement as i, WorkerVideoElement as n, WorkerTimeRanges as o, connectToHostVideo as r, configureVideoTransport as s, polyfillDocument as t };
|
|
878
978
|
|
|
879
|
-
//# sourceMappingURL=document-
|
|
979
|
+
//# sourceMappingURL=document-BhePs2Wq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-BhePs2Wq.js","names":[],"sources":["../src/worker/bridge.ts","../src/worker/media-types.ts","../src/worker/video-element.ts","../src/worker/document.ts"],"sourcesContent":["import {\n CHANNEL,\n type CanPlayTypeResult,\n type ClientMessage,\n type HostMessage,\n type MessageEndpoint,\n isProtocolMessage,\n} from \"../shared/protocol.ts\";\nimport { assertWorker, isMessageEndpoint } from \"../shared/environment.ts\";\n\nexport const MISSING_HOST_WARNING_DELAY = 3000;\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\nexport type OutgoingMessage = DistributiveOmit<ClientMessage, typeof CHANNEL | \"seq\">;\n\nexport interface ElementReceiver {\n receive(message: Extract<HostMessage, { id: number }>): void;\n}\n\ninterface Finalizable {\n id: number;\n release: () => void;\n}\n\nexport class Bridge {\n readonly endpoint: MessageEndpoint;\n timeOffset = 0;\n\n #seq = 0;\n #outbox: Array<Record<string, unknown>> = [];\n #outboxTransfer: Transferable[] = [];\n #flushScheduled = false;\n #nextId = 1;\n #nextCallId = 1;\n readonly #receivers = new Map<number, WeakRef<ElementReceiver>>();\n readonly #pinned = new Set<object>();\n readonly #calls = new Map<number, { resolve: (value: unknown) => void; reject: (error: unknown) => void }>();\n readonly #canPlayType = new Map<string, CanPlayTypeResult>();\n readonly #ids = new Map<string, WeakRef<{ disposed: boolean }>>();\n readonly #registry: FinalizationRegistry<Finalizable> | null;\n #welcomed = false;\n #missingHostTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(endpoint: MessageEndpoint) {\n this.endpoint = endpoint;\n this.#registry =\n typeof FinalizationRegistry === \"function\"\n ? new FinalizationRegistry<Finalizable>(({ id, release }) => {\n release();\n this.#receivers.delete(id);\n this.post({ kind: \"dispose\", id });\n })\n : null;\n endpoint.addEventListener(\"message\", this.#onMessage);\n endpoint.start?.();\n this.post({ kind: \"hello\" });\n }\n\n watchForHost(): void {\n if (this.#welcomed || this.#missingHostTimer !== undefined) return;\n this.#missingHostTimer = setTimeout(() => {\n if (this.#welcomed) return;\n console.warn(\n \"html-video-element-webworker-polyfill: no VideoHost answered this worker. \" +\n \"Call createVideoHost(worker) on the main thread right after creating the worker, otherwise videos never load.\",\n );\n }, MISSING_HOST_WARNING_DELAY);\n }\n\n nextId(): number {\n return this.#nextId++;\n }\n\n post(message: OutgoingMessage, transfer: Transferable[] = []): number {\n const seq = ++this.#seq;\n this.#outbox.push({ ...message, [CHANNEL]: 1, seq });\n this.#outboxTransfer.push(...transfer);\n if (!this.#flushScheduled) {\n this.#flushScheduled = true;\n queueMicrotask(this.#flush);\n }\n return seq;\n }\n\n #flush = (): void => {\n this.#flushScheduled = false;\n const messages = this.#outbox;\n const transfer = this.#outboxTransfer;\n this.#outbox = [];\n this.#outboxTransfer = [];\n if (messages.length === 1) this.endpoint.postMessage(messages[0], transfer);\n else if (messages.length > 1) this.endpoint.postMessage({ [CHANNEL]: 1, kind: \"batch\", messages }, transfer);\n };\n\n call(message: OutgoingMessage & { kind: \"call\" | \"connect\" }, transfer?: Transferable[]): [number, Promise<unknown>] {\n const callId = this.#nextCallId++;\n const promise = new Promise((resolve, reject) => this.#calls.set(callId, { resolve, reject }));\n return [this.post({ ...message, callId }, transfer), promise];\n }\n\n register(id: number, element: object, receiver: ElementReceiver, release: () => void): void {\n this.#receivers.set(id, new WeakRef(receiver));\n this.#registry?.register(element, { id, release }, receiver);\n }\n\n unregister(id: number, receiver: ElementReceiver, element: object): void {\n this.#receivers.delete(id);\n this.#registry?.unregister(receiver);\n this.#pinned.delete(element);\n }\n\n claimId(id: string, element: { disposed: boolean }): void {\n if (id === \"\") return;\n const owner = this.#ids.get(id)?.deref();\n if (owner && owner !== element && !owner.disposed) {\n throw new DOMException(\n `html-video-element-webworker-polyfill: a video element with id \"${id}\" already exists in this worker.`,\n \"InvalidStateError\",\n );\n }\n this.#ids.set(id, new WeakRef(element));\n }\n\n releaseId(id: string, element: object): void {\n if (this.#ids.get(id)?.deref() === element) this.#ids.delete(id);\n }\n\n pin(element: object, pinned: boolean): void {\n if (pinned) this.#pinned.add(element);\n else this.#pinned.delete(element);\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n const cached = this.#canPlayType.get(type);\n if (cached !== undefined) return cached;\n const callId = this.#nextCallId++;\n this.#calls.set(callId, {\n resolve: (value) => this.#canPlayType.set(type, value as CanPlayTypeResult),\n reject: () => {},\n });\n this.post({ kind: \"canPlayType\", type, callId });\n return guessCanPlayType(type);\n }\n\n #onMessage = (event: MessageEvent): void => {\n if (!isProtocolMessage(event.data)) return;\n const message = event.data as HostMessage;\n switch (message.kind) {\n case \"welcome\": {\n this.#welcomed = true;\n clearTimeout(this.#missingHostTimer);\n this.timeOffset = message.timeOrigin - performance.timeOrigin;\n for (const [type, result] of Object.entries(message.canPlayType)) this.#canPlayType.set(type, result);\n return;\n }\n case \"result\": {\n const call = this.#calls.get(message.callId);\n if (!call) return;\n this.#calls.delete(message.callId);\n if (message.error) call.reject(new DOMException(message.error.message, message.error.name));\n else call.resolve(message.value);\n return;\n }\n default: {\n const receiver = this.#receivers.get(message.id)?.deref();\n if (receiver) receiver.receive(message);\n else if (\"frame\" in message) message.frame?.close();\n if (message.kind === \"frame\") this.post({ kind: \"frameAck\", id: message.id });\n }\n }\n };\n}\n\nconst CONTAINER_CODECS: Record<string, string[]> = {\n \"video/webm\": [\"vp8\", \"vp9\", \"av01.0.05M.08\"],\n \"video/mp4\": [\"avc1.42E01E\", \"av01.0.05M.08\", \"hvc1.1.6.L93.B0\", \"vp09.00.10.08\"],\n \"audio/webm\": [\"opus\", \"vorbis\"],\n \"audio/mp4\": [\"mp4a.40.2\", \"opus\", \"flac\"],\n};\n\nfunction guessCanPlayType(type: string): CanPlayTypeResult {\n const MediaSourceCtor = (globalThis as { MediaSource?: { isTypeSupported(type: string): boolean } }).MediaSource;\n if (!MediaSourceCtor) return \"\";\n if (/codecs\\s*=/i.test(type)) return MediaSourceCtor.isTypeSupported(type) ? \"probably\" : \"\";\n if (MediaSourceCtor.isTypeSupported(type)) return \"maybe\";\n const container = type.split(\";\")[0]!.trim().toLowerCase();\n const codecs = CONTAINER_CODECS[container] ?? [];\n return codecs.some((codec) => MediaSourceCtor.isTypeSupported(`${container}; codecs=\"${codec}\"`)) ? \"maybe\" : \"\";\n}\n\nconst bridges = new WeakMap<object, Bridge>();\nlet defaultEndpoint: MessageEndpoint | undefined;\n\nexport function bridgeFor(endpoint: MessageEndpoint | undefined): Bridge {\n const target = endpoint ?? defaultEndpoint ?? (globalThis as unknown as MessageEndpoint);\n if (!isMessageEndpoint(target)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: `transport` must be a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n let bridge = bridges.get(target);\n if (!bridge) {\n bridge = new Bridge(target);\n bridges.set(target, bridge);\n }\n return bridge;\n}\n\nexport function configureVideoTransport(endpoint: MessageEndpoint): void {\n assertWorker(\"configureVideoTransport()\");\n if (!isMessageEndpoint(endpoint)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: configureVideoTransport() expects a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n defaultEndpoint = endpoint;\n}\n","import type { Ranges, SerializedMediaError } from \"../shared/protocol.ts\";\n\nexport class WorkerTimeRanges implements TimeRanges {\n readonly #ranges: Ranges;\n\n constructor(ranges: Ranges = []) {\n this.#ranges = ranges;\n }\n\n get length(): number {\n return this.#ranges.length;\n }\n\n start(index: number): number {\n return this.#at(index)[0];\n }\n\n end(index: number): number {\n return this.#at(index)[1];\n }\n\n #at(index: number): [number, number] {\n const range = this.#ranges[index];\n if (!range) {\n throw new DOMException(\n `The index provided (${index}) is greater than or equal to the maximum bound (${this.#ranges.length}).`,\n \"IndexSizeError\",\n );\n }\n return range;\n }\n}\n\nexport class WorkerMediaError implements MediaError {\n static readonly MEDIA_ERR_ABORTED = 1 as const;\n static readonly MEDIA_ERR_NETWORK = 2 as const;\n static readonly MEDIA_ERR_DECODE = 3 as const;\n static readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n readonly MEDIA_ERR_ABORTED = 1 as const;\n readonly MEDIA_ERR_NETWORK = 2 as const;\n readonly MEDIA_ERR_DECODE = 3 as const;\n readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n\n readonly code: number;\n readonly message: string;\n\n constructor({ code, message }: SerializedMediaError) {\n this.code = code;\n this.message = message;\n }\n}\n","import { assertWorker } from \"../shared/environment.ts\";\nimport { FRAME_SOURCE } from \"../shared/frame-source.ts\";\nimport {\n type CanPlayTypeResult,\n type ConnectResult,\n type FrameMetadata,\n type HostMessage,\n MEDIA_EVENTS,\n type MediaState,\n type MessageEndpoint,\n} from \"../shared/protocol.ts\";\nimport { type Bridge, type ElementReceiver, bridgeFor } from \"./bridge.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\n\nconst CONNECT: unique symbol = Symbol(\"connect\") as never;\n\ninterface InternalOptions extends CreateVideoElementOptions {\n [CONNECT]?: string;\n}\n\nexport interface CreateVideoElementOptions {\n transport?: MessageEndpoint;\n}\n\nexport type VideoFrameRequestCallback = (now: number, metadata: FrameMetadata) => void;\n\ntype EventHandler = ((this: WorkerVideoElement, event: Event) => unknown) | null;\n\ninterface MirroredProps {\n autoplay: boolean;\n controls: boolean;\n crossOrigin: string | null;\n defaultMuted: boolean;\n defaultPlaybackRate: number;\n disablePictureInPicture: boolean;\n disableRemotePlayback: boolean;\n height: number;\n id: string;\n loop: boolean;\n playsInline: boolean;\n poster: string;\n preload: \"\" | \"none\" | \"metadata\" | \"auto\";\n preservesPitch: boolean;\n width: number;\n}\n\nconst EMPTY_STATE: MediaState = {\n currentSrc: \"\",\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n muted: false,\n networkState: 0,\n paused: true,\n playbackRate: 1,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n volume: 1,\n buffered: [],\n played: [],\n seekable: [],\n quality: null,\n props: {},\n};\n\nconst LOAD_RESET: Partial<MediaState> = {\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n paused: true,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n buffered: [],\n played: [],\n seekable: [],\n};\n\nconst ATTRIBUTES: Record<string, { prop: string; type: \"bool\" | \"string\" | \"number\" | \"nullable\" }> = {\n autoplay: { prop: \"autoplay\", type: \"bool\" },\n controls: { prop: \"controls\", type: \"bool\" },\n crossorigin: { prop: \"crossOrigin\", type: \"nullable\" },\n disablepictureinpicture: { prop: \"disablePictureInPicture\", type: \"bool\" },\n disableremoteplayback: { prop: \"disableRemotePlayback\", type: \"bool\" },\n height: { prop: \"height\", type: \"number\" },\n loop: { prop: \"loop\", type: \"bool\" },\n muted: { prop: \"defaultMuted\", type: \"bool\" },\n playsinline: { prop: \"playsInline\", type: \"bool\" },\n poster: { prop: \"poster\", type: \"string\" },\n preload: { prop: \"preload\", type: \"string\" },\n src: { prop: \"src\", type: \"string\" },\n width: { prop: \"width\", type: \"number\" },\n id: { prop: \"id\", type: \"string\" },\n};\n\nfunction frameReleaser(holder: { current: VideoFrame | null }): () => void {\n return () => {\n holder.current?.close();\n holder.current = null;\n };\n}\n\nclass Internals implements ElementReceiver {\n readonly element: WorkerVideoElement;\n readonly bridge: Bridge;\n readonly id: number;\n state: MediaState = { ...EMPTY_STATE };\n props: MirroredProps = {\n autoplay: false,\n controls: false,\n crossOrigin: null,\n defaultMuted: false,\n defaultPlaybackRate: 1,\n disablePictureInPicture: false,\n disableRemotePlayback: false,\n height: 0,\n id: \"\",\n loop: false,\n playsInline: false,\n poster: \"\",\n preload: \"metadata\",\n preservesPitch: true,\n width: 0,\n };\n src = \"\";\n srcObject: unknown = null;\n hasSrcAttribute = false;\n readonly frame: { current: VideoFrame | null } = { current: null };\n readonly localWrites = new Map<string, number>();\n readonly frameCallbacks = new Map<number, VideoFrameRequestCallback>();\n nextFrameCallbackId = 1;\n readonly handlers = new Map<string, { handler: EventHandler; listener: (event: Event) => void }>();\n loadSeq = 0;\n disposed = false;\n readonly ready: Promise<void>;\n\n constructor(element: WorkerVideoElement, bridge: Bridge, selector?: string) {\n this.element = element;\n this.bridge = bridge;\n this.id = bridge.nextId();\n bridge.register(this.id, element, this, frameReleaser(this.frame));\n if (selector === undefined) {\n bridge.post({ kind: \"create\", id: this.id, props: {} });\n this.ready = Promise.resolve();\n } else {\n this.ready = this.connect(selector);\n }\n }\n\n async connect(selector: string): Promise<void> {\n const [seq, result] = this.bridge.call({ kind: \"connect\", id: this.id, selector });\n const connected = (await result) as ConnectResult;\n this.applyState(seq, connected.state);\n if (connected.frame) this.setFrame(connected.frame);\n }\n\n markProps(seq: number, ...props: string[]): void {\n if (!seq) return;\n for (const prop of props) this.localWrites.set(`props.${prop}`, seq);\n }\n\n applyProps(ack: number, props: Record<string, unknown>): void {\n for (const [prop, value] of Object.entries(props)) {\n const key = `props.${prop}`;\n const pending = this.localWrites.get(key);\n if (pending !== undefined) {\n if (pending > ack) continue;\n this.localWrites.delete(key);\n }\n if (prop === \"src\") this.src = value as string;\n else if (prop === \"hasSrcAttribute\") this.hasSrcAttribute = value as boolean;\n else if (prop in this.props) (this.props as unknown as Record<string, unknown>)[prop] = value;\n }\n }\n\n write(prop: string, value: unknown, local: Partial<MediaState> = {}, transfer?: Transferable[]): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"set\", id: this.id, prop, value }, transfer);\n this.applyLocal(seq, local);\n return seq;\n }\n\n invoke(\n method: \"pause\" | \"load\" | \"fastSeek\" | \"removeAttribute\",\n args: unknown[],\n local: Partial<MediaState> = {},\n ): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"call\", id: this.id, method, args });\n this.applyLocal(seq, local);\n return seq;\n }\n\n markLoad(seq: number): void {\n if (seq) this.loadSeq = seq;\n }\n\n applyLocal(seq: number, local: Partial<MediaState>): void {\n for (const [key, value] of Object.entries(local)) {\n (this.state as unknown as Record<string, unknown>)[key] = value;\n this.localWrites.set(key, seq);\n }\n if (\"readyState\" in local && (local.readyState ?? 0) < 2) this.setFrame(null);\n this.updatePin();\n }\n\n updatePin(): void {\n const { paused, seeking, networkState } = this.state;\n this.bridge.pin(this.element, !paused || seeking || networkState === 2);\n }\n\n applyState(ack: number, state: MediaState): void {\n const target = this.state as unknown as Record<string, unknown>;\n for (const [key, value] of Object.entries(state)) {\n if (key === \"props\") {\n this.applyProps(ack, value as Record<string, unknown>);\n continue;\n }\n const pending = this.localWrites.get(key);\n if (pending !== undefined) {\n if (pending > ack) continue;\n this.localWrites.delete(key);\n }\n target[key] = value;\n }\n this.updatePin();\n }\n\n setFrame(frame: VideoFrame | null): void {\n if (this.frame.current === frame) return;\n this.frame.current?.close();\n this.frame.current = frame;\n }\n\n receive(message: Extract<HostMessage, { id: number }>): void {\n if (this.disposed || (message.kind !== \"state\" && message.ack < this.loadSeq)) {\n if (\"frame\" in message) message.frame?.close();\n if (this.disposed) return;\n }\n this.applyState(message.ack, message.state);\n if (message.kind !== \"state\" && message.ack < this.loadSeq) return;\n switch (message.kind) {\n case \"state\":\n return;\n case \"frame\":\n this.setFrame(message.frame);\n this.runFrameCallbacks(message.metadata);\n return;\n case \"event\": {\n if (message.frame) this.setFrame(message.frame);\n else if (message.type === \"emptied\") this.setFrame(null);\n this.element.dispatchEvent(new Event(message.type));\n if (message.frame && message.metadata) this.runFrameCallbacks(message.metadata);\n }\n }\n }\n\n runFrameCallbacks(metadata: FrameMetadata): void {\n if (this.frameCallbacks.size === 0) return;\n const callbacks = [...this.frameCallbacks.values()];\n this.frameCallbacks.clear();\n const offset = this.bridge.timeOffset;\n const local: FrameMetadata = {\n ...metadata,\n presentationTime: metadata.presentationTime + offset,\n expectedDisplayTime: metadata.expectedDisplayTime + offset,\n };\n const now = performance.now();\n for (const callback of callbacks) {\n try {\n callback.call(this.element, now, local);\n } catch (error) {\n reportError(error);\n }\n }\n }\n\n resolveUrl(value: string): string {\n if (value === \"\") return value;\n const base = (globalThis as { location?: { href: string } }).location?.href;\n try {\n return new URL(value, base).href;\n } catch {\n return value;\n }\n }\n}\n\nfunction reportError(error: unknown): void {\n const report = (globalThis as { reportError?: (error: unknown) => void }).reportError;\n if (report) report(error);\n else\n setTimeout(() => {\n throw error;\n });\n}\n\nconst internals = new WeakMap<WorkerVideoElement, Internals>();\n\nfunction $(element: WorkerVideoElement): Internals {\n const value = internals.get(element);\n if (!value) throw new TypeError(\"Illegal invocation\");\n return value;\n}\n\nexport class WorkerVideoElement extends EventTarget {\n static readonly NETWORK_EMPTY = 0 as const;\n static readonly NETWORK_IDLE = 1 as const;\n static readonly NETWORK_LOADING = 2 as const;\n static readonly NETWORK_NO_SOURCE = 3 as const;\n static readonly HAVE_NOTHING = 0 as const;\n static readonly HAVE_METADATA = 1 as const;\n static readonly HAVE_CURRENT_DATA = 2 as const;\n static readonly HAVE_FUTURE_DATA = 3 as const;\n static readonly HAVE_ENOUGH_DATA = 4 as const;\n readonly NETWORK_EMPTY = 0 as const;\n readonly NETWORK_IDLE = 1 as const;\n readonly NETWORK_LOADING = 2 as const;\n readonly NETWORK_NO_SOURCE = 3 as const;\n readonly HAVE_NOTHING = 0 as const;\n readonly HAVE_METADATA = 1 as const;\n readonly HAVE_CURRENT_DATA = 2 as const;\n readonly HAVE_FUTURE_DATA = 3 as const;\n readonly HAVE_ENOUGH_DATA = 4 as const;\n\n readonly tagName = \"VIDEO\" as const;\n readonly nodeName = \"VIDEO\" as const;\n readonly localName = \"video\" as const;\n\n constructor(options: CreateVideoElementOptions = {}) {\n assertWorker(\"createVideoElement()\");\n super();\n const bridge = bridgeFor(options.transport);\n bridge.watchForHost();\n internals.set(this, new Internals(this, bridge, (options as InternalOptions)[CONNECT]));\n }\n\n get currentFrame(): VideoFrame | null {\n const frame = $(this).frame.current;\n return frame && frame.format !== null ? frame : null;\n }\n\n get disposed(): boolean {\n return $(this).disposed;\n }\n\n dispose(): void {\n const core = $(this);\n if (core.disposed) return;\n core.bridge.post({ kind: \"dispose\", id: core.id });\n core.disposed = true;\n core.setFrame(null);\n core.frameCallbacks.clear();\n core.bridge.unregister(core.id, core, this);\n core.bridge.releaseId(core.props.id, this);\n core.state = { ...EMPTY_STATE };\n core.localWrites.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n get src(): string {\n return $(this).src;\n }\n set src(value: string) {\n const core = $(this);\n core.src = core.resolveUrl(String(value));\n core.hasSrcAttribute = true;\n const seq = core.write(\"src\", core.src, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 });\n core.markLoad(seq);\n core.markProps(seq, \"src\", \"hasSrcAttribute\");\n }\n\n get srcObject(): unknown {\n return $(this).srcObject;\n }\n set srcObject(value: unknown) {\n const core = $(this);\n core.srcObject = value ?? null;\n const transfer = value ? [value as Transferable] : [];\n core.markLoad(core.write(\"srcObject\", value ?? null, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 }, transfer));\n }\n\n get currentSrc(): string {\n return $(this).state.currentSrc;\n }\n\n get duration(): number {\n return $(this).state.duration;\n }\n get paused(): boolean {\n return $(this).state.paused;\n }\n get ended(): boolean {\n return $(this).state.ended;\n }\n get seeking(): boolean {\n return $(this).state.seeking;\n }\n get readyState(): number {\n return $(this).state.readyState;\n }\n get networkState(): number {\n return $(this).state.networkState;\n }\n get videoWidth(): number {\n return $(this).state.videoWidth;\n }\n get videoHeight(): number {\n return $(this).state.videoHeight;\n }\n get error(): MediaError | null {\n const error = $(this).state.error;\n return error ? new WorkerMediaError(error) : null;\n }\n get buffered(): TimeRanges {\n return new WorkerTimeRanges($(this).state.buffered);\n }\n get played(): TimeRanges {\n return new WorkerTimeRanges($(this).state.played);\n }\n get seekable(): TimeRanges {\n return new WorkerTimeRanges($(this).state.seekable);\n }\n\n get currentTime(): number {\n return $(this).state.currentTime;\n }\n set currentTime(value: number) {\n const time = Number(value);\n if (!Number.isFinite(time)) {\n throw new TypeError(\"Failed to set the 'currentTime' property: The provided double value is non-finite.\");\n }\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.write(\"currentTime\", time, local);\n }\n\n fastSeek(time: number): void {\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.invoke(\"fastSeek\", [time], local);\n }\n\n get volume(): number {\n return $(this).state.volume;\n }\n set volume(value: number) {\n const volume = Number(value);\n if (!(volume >= 0 && volume <= 1)) {\n throw new DOMException(\n `Failed to set the 'volume' property: The volume provided (${value}) is outside the range [0, 1].`,\n \"IndexSizeError\",\n );\n }\n $(this).write(\"volume\", volume, { volume });\n }\n\n get muted(): boolean {\n return $(this).state.muted;\n }\n set muted(value: boolean) {\n $(this).write(\"muted\", Boolean(value), { muted: Boolean(value) });\n }\n\n get playbackRate(): number {\n return $(this).state.playbackRate;\n }\n set playbackRate(value: number) {\n $(this).write(\"playbackRate\", Number(value), { playbackRate: Number(value) });\n }\n\n get autoplay(): boolean {\n return $(this).props.autoplay;\n }\n set autoplay(value: boolean) {\n this.#mirror(\"autoplay\", Boolean(value));\n }\n get controls(): boolean {\n return $(this).props.controls;\n }\n set controls(value: boolean) {\n this.#mirror(\"controls\", Boolean(value));\n }\n get crossOrigin(): string | null {\n return $(this).props.crossOrigin;\n }\n set crossOrigin(value: string | null) {\n this.#mirror(\"crossOrigin\", value === null ? null : String(value));\n }\n get defaultMuted(): boolean {\n return $(this).props.defaultMuted;\n }\n set defaultMuted(value: boolean) {\n this.#mirror(\"defaultMuted\", Boolean(value));\n }\n get defaultPlaybackRate(): number {\n return $(this).props.defaultPlaybackRate;\n }\n set defaultPlaybackRate(value: number) {\n this.#mirror(\"defaultPlaybackRate\", Number(value));\n }\n get disablePictureInPicture(): boolean {\n return $(this).props.disablePictureInPicture;\n }\n set disablePictureInPicture(value: boolean) {\n this.#mirror(\"disablePictureInPicture\", Boolean(value));\n }\n get disableRemotePlayback(): boolean {\n return $(this).props.disableRemotePlayback;\n }\n set disableRemotePlayback(value: boolean) {\n this.#mirror(\"disableRemotePlayback\", Boolean(value));\n }\n get id(): string {\n return $(this).props.id;\n }\n set id(value: string) {\n const core = $(this);\n const id = String(value);\n core.bridge.claimId(id, this);\n if (core.props.id !== id) core.bridge.releaseId(core.props.id, this);\n this.#mirror(\"id\", id);\n }\n\n get height(): number {\n return $(this).props.height;\n }\n set height(value: number) {\n this.#mirror(\"height\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get width(): number {\n return $(this).props.width;\n }\n set width(value: number) {\n this.#mirror(\"width\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get loop(): boolean {\n return $(this).props.loop;\n }\n set loop(value: boolean) {\n this.#mirror(\"loop\", Boolean(value));\n }\n get playsInline(): boolean {\n return $(this).props.playsInline;\n }\n set playsInline(value: boolean) {\n this.#mirror(\"playsInline\", Boolean(value));\n }\n get poster(): string {\n return $(this).props.poster;\n }\n set poster(value: string) {\n this.#mirror(\"poster\", $(this).resolveUrl(String(value)));\n }\n get preload(): MirroredProps[\"preload\"] {\n return $(this).props.preload;\n }\n set preload(value: MirroredProps[\"preload\"]) {\n const normalized = String(value).toLowerCase();\n this.#mirror(\"preload\", ([\"none\", \"metadata\", \"auto\"].includes(normalized) ? normalized : \"auto\") as never);\n }\n get preservesPitch(): boolean {\n return $(this).props.preservesPitch;\n }\n set preservesPitch(value: boolean) {\n this.#mirror(\"preservesPitch\", Boolean(value));\n }\n\n #mirror<K extends keyof MirroredProps>(prop: K, value: MirroredProps[K]): void {\n const core = $(this);\n core.props[prop] = value;\n core.markProps(core.write(prop, value), prop);\n }\n\n getAttribute(name: string): string | null {\n const core = $(this);\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return null;\n if (attribute.prop === \"src\") return core.hasSrcAttribute ? core.src : null;\n const value = (this as unknown as Record<string, unknown>)[attribute.prop];\n switch (attribute.type) {\n case \"bool\":\n return value ? \"\" : null;\n case \"nullable\":\n return value === null ? null : String(value);\n default:\n return String(value);\n }\n }\n\n hasAttribute(name: string): boolean {\n return this.getAttribute(name) !== null;\n }\n\n setAttribute(name: string, value: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = true;\n break;\n case \"number\":\n target[attribute.prop] = Number.parseInt(value, 10) || 0;\n break;\n default:\n target[attribute.prop] = String(value);\n }\n }\n\n removeAttribute(name: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const core = $(this);\n if (attribute.prop === \"src\") {\n core.src = \"\";\n core.hasSrcAttribute = false;\n core.markProps(core.invoke(\"removeAttribute\", [\"src\"]), \"src\", \"hasSrcAttribute\");\n return;\n }\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = false;\n break;\n case \"nullable\":\n target[attribute.prop] = null;\n break;\n case \"number\":\n target[attribute.prop] = 0;\n break;\n default:\n target[attribute.prop] = attribute.prop === \"preload\" ? \"metadata\" : \"\";\n }\n }\n\n play(): Promise<void> {\n const core = $(this);\n if (core.disposed) {\n return Promise.reject(new DOMException(\"The element has been disposed.\", \"InvalidStateError\"));\n }\n const [seq, promise] = core.bridge.call({ kind: \"call\", id: core.id, method: \"play\", args: [] });\n core.applyLocal(seq, { paused: false });\n return promise as Promise<void>;\n }\n\n pause(): void {\n $(this).invoke(\"pause\", [], { paused: true });\n }\n\n load(): void {\n const core = $(this);\n core.markLoad(core.invoke(\"load\", [], { ...LOAD_RESET, networkState: 0 }));\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n return $(this).bridge.canPlayType(String(type));\n }\n\n getVideoPlaybackQuality(): VideoPlaybackQuality {\n const quality = $(this).state.quality;\n return (quality ?? {\n creationTime: performance.now(),\n droppedVideoFrames: 0,\n totalVideoFrames: 0,\n }) as VideoPlaybackQuality;\n }\n\n requestVideoFrameCallback(callback: VideoFrameRequestCallback): number {\n const core = $(this);\n const handle = core.nextFrameCallbackId++;\n core.frameCallbacks.set(handle, callback);\n return handle;\n }\n\n cancelVideoFrameCallback(handle: number): void {\n $(this).frameCallbacks.delete(handle);\n }\n\n requestPictureInPicture(): Promise<never> {\n return Promise.reject(new DOMException(\"Picture-in-Picture is not available in workers.\", \"NotSupportedError\"));\n }\n}\n\nexport interface WorkerVideoElement {\n [FRAME_SOURCE](): VideoFrame | null;\n onabort: EventHandler;\n oncanplay: EventHandler;\n oncanplaythrough: EventHandler;\n ondurationchange: EventHandler;\n onemptied: EventHandler;\n onencrypted: EventHandler;\n onended: EventHandler;\n onerror: EventHandler;\n onloadeddata: EventHandler;\n onloadedmetadata: EventHandler;\n onloadstart: EventHandler;\n onpause: EventHandler;\n onplay: EventHandler;\n onplaying: EventHandler;\n onprogress: EventHandler;\n onratechange: EventHandler;\n onresize: EventHandler;\n onseeked: EventHandler;\n onseeking: EventHandler;\n onstalled: EventHandler;\n onsuspend: EventHandler;\n ontimeupdate: EventHandler;\n onvolumechange: EventHandler;\n onwaiting: EventHandler;\n onwaitingforkey: EventHandler;\n}\n\nObject.defineProperty(WorkerVideoElement.prototype, FRAME_SOURCE, {\n configurable: true,\n value(this: WorkerVideoElement): VideoFrame | null {\n return this.currentFrame;\n },\n});\n\nfor (const type of MEDIA_EVENTS) {\n Object.defineProperty(WorkerVideoElement.prototype, `on${type}`, {\n configurable: true,\n enumerable: true,\n get(this: WorkerVideoElement): EventHandler {\n return $(this).handlers.get(type)?.handler ?? null;\n },\n set(this: WorkerVideoElement, handler: EventHandler) {\n const core = $(this);\n const existing = core.handlers.get(type);\n if (typeof handler !== \"function\") {\n if (existing) this.removeEventListener(type, existing.listener);\n core.handlers.delete(type);\n return;\n }\n if (existing) {\n existing.handler = handler;\n return;\n }\n const entry = {\n handler,\n listener: (event: Event) => {\n const result = entry.handler?.call(this, event);\n if (result === false) event.preventDefault();\n },\n };\n core.handlers.set(type, entry);\n this.addEventListener(type, entry.listener);\n },\n });\n}\n\nexport function createVideoElement(options?: CreateVideoElementOptions): WorkerVideoElement {\n return new WorkerVideoElement(options);\n}\n\nexport function connectToHostVideo(\n selector: string,\n options: CreateVideoElementOptions = {},\n): Promise<WorkerVideoElement> {\n assertWorker(\"connectToHostVideo()\");\n if (typeof selector !== \"string\" || selector.trim() === \"\") {\n throw new TypeError(\"html-video-element-webworker-polyfill: connectToHostVideo() expects a CSS selector string.\");\n }\n const video = new WorkerVideoElement({ ...options, [CONNECT]: selector } as InternalOptions);\n return $(video).ready.then(\n () => video,\n (error: unknown) => {\n video.dispose();\n throw error;\n },\n );\n}\n","import type { CreateVideoElementOptions } from \"./video-element.ts\";\nimport { WorkerVideoElement } from \"./video-element.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\nimport { assertWorker } from \"../shared/environment.ts\";\n\nconst PATCHED: unique symbol = Symbol.for(\"html-video-element-webworker-polyfill.patched\") as never;\n\ninterface DocumentLike {\n createElement(tagName: string, options?: unknown): unknown;\n [PATCHED]?: true;\n}\n\nexport function polyfillDocument(options?: CreateVideoElementOptions): void {\n assertWorker(\"polyfillDocument()\");\n const scope = globalThis as Record<string, unknown>;\n scope.HTMLVideoElement ??= WorkerVideoElement;\n scope.HTMLMediaElement ??= WorkerVideoElement;\n scope.MediaError ??= WorkerMediaError;\n scope.TimeRanges ??= WorkerTimeRanges;\n\n const existing = scope.document as DocumentLike | undefined;\n if (existing && typeof existing.createElement === \"function\") {\n if (existing[PATCHED]) return;\n const original = existing.createElement.bind(existing);\n existing.createElement = (tagName: string, elementOptions?: unknown) =>\n isVideo(tagName) ? new WorkerVideoElement(options) : original(tagName, elementOptions);\n existing[PATCHED] = true;\n return;\n }\n\n const document: DocumentLike = {\n createElement(tagName: string): unknown {\n if (isVideo(tagName)) return new WorkerVideoElement(options);\n throw new DOMException(\n `document.createElement(\"${tagName}\") is not supported in a worker; only \"video\" is polyfilled.`,\n \"NotSupportedError\",\n );\n },\n [PATCHED]: true,\n };\n scope.document = document;\n}\n\nfunction isVideo(tagName: string): boolean {\n return String(tagName).toLowerCase() === \"video\";\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as isProtocolMessage, i as MIRRORED_PROPERTIES, n as COMMON_MIME_TYPES, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol
|
|
1
|
+
import { a as isProtocolMessage, i as MIRRORED_PROPERTIES, n as COMMON_MIME_TYPES, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol--LD8Qk5Y.js";
|
|
2
2
|
import { a as isMessageEndpoint, i as isMainThread, n as assertMainThread } from "./environment-De2r8LaA.js";
|
|
3
3
|
//#region src/host/video-host.ts
|
|
4
4
|
const FRAME_EVENTS = /* @__PURE__ */ new Set(["loadeddata", "seeked"]);
|
|
5
5
|
const SILENT_STATE_POLL_INTERVAL = 16;
|
|
6
6
|
const SILENT_STATE_POLLS = 32;
|
|
7
7
|
const FRAME_WAIT_TIMEOUT = 500;
|
|
8
|
+
const CONNECT_FRAME_ATTEMPTS = 30;
|
|
8
9
|
const TIMESTAMP_EPSILON = 1e3;
|
|
9
10
|
const hosted = /* @__PURE__ */ new WeakSet();
|
|
10
11
|
function createVideoHost(endpoint, options = {}) {
|
|
@@ -68,20 +69,11 @@ function createVideoHost(endpoint, options = {}) {
|
|
|
68
69
|
canPlayType
|
|
69
70
|
});
|
|
70
71
|
};
|
|
71
|
-
const captureFrame = (entry) =>
|
|
72
|
-
|
|
73
|
-
if (video.readyState < 2 || typeof VideoFrame !== "function") return null;
|
|
74
|
-
try {
|
|
75
|
-
return new VideoFrame(video);
|
|
76
|
-
} catch {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const create = (id) => {
|
|
81
|
-
const video = document.createElement("video");
|
|
82
|
-
video.playsInline = true;
|
|
72
|
+
const captureFrame = (entry) => captureVideoFrame(entry.video);
|
|
73
|
+
const attach = (id, video, adopted) => {
|
|
83
74
|
const entry = {
|
|
84
75
|
video,
|
|
76
|
+
adopted,
|
|
85
77
|
frameCallback: null,
|
|
86
78
|
lastFrameTimestamp: null,
|
|
87
79
|
frameInFlight: false,
|
|
@@ -224,8 +216,70 @@ function createVideoHost(endpoint, options = {}) {
|
|
|
224
216
|
};
|
|
225
217
|
entries.set(id, entry);
|
|
226
218
|
videos.set(id, video);
|
|
219
|
+
return entry;
|
|
220
|
+
};
|
|
221
|
+
const create = (id, props) => {
|
|
222
|
+
const video = document.createElement("video");
|
|
223
|
+
video.playsInline = true;
|
|
224
|
+
if (typeof props.id === "string") video.id = props.id;
|
|
225
|
+
attach(id, video, false);
|
|
227
226
|
options.container?.append(video);
|
|
228
|
-
|
|
227
|
+
if (batch) batch.created.push(video);
|
|
228
|
+
else options.onVideoCreated?.(video);
|
|
229
|
+
};
|
|
230
|
+
const connect = (id, selector, callId) => {
|
|
231
|
+
const reply = (value, transfer = []) => {
|
|
232
|
+
if (callId !== void 0) post({
|
|
233
|
+
kind: "result",
|
|
234
|
+
callId,
|
|
235
|
+
value
|
|
236
|
+
}, transfer);
|
|
237
|
+
};
|
|
238
|
+
const fail = (name, message) => {
|
|
239
|
+
if (callId !== void 0) post({
|
|
240
|
+
kind: "result",
|
|
241
|
+
callId,
|
|
242
|
+
error: {
|
|
243
|
+
name,
|
|
244
|
+
message
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
let found;
|
|
249
|
+
try {
|
|
250
|
+
found = document.querySelector(selector);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
fail("SyntaxError", error.message);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (!found) {
|
|
256
|
+
fail("NotFoundError", `connectToHostVideo(): no element matches "${selector}" on the main thread.`);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (!(found instanceof HTMLVideoElement)) {
|
|
260
|
+
fail("InvalidNodeTypeError", `connectToHostVideo(): "${selector}" matches a <${found.localName}>, not a <video>.`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (options.canConnect && !options.canConnect(found, selector)) {
|
|
264
|
+
fail("NotAllowedError", `connectToHostVideo(): the host does not allow connecting to "${selector}".`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const video = found;
|
|
268
|
+
const finish = (attempt) => {
|
|
269
|
+
if (disposed) return;
|
|
270
|
+
const frame = captureVideoFrame(video);
|
|
271
|
+
if (!frame && video.readyState >= 2 && attempt < CONNECT_FRAME_ATTEMPTS) {
|
|
272
|
+
setTimeout(() => finish(attempt + 1), SILENT_STATE_POLL_INTERVAL);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const entry = attach(id, video, true);
|
|
276
|
+
if (frame) entry.lastFrameTimestamp = frame.timestamp;
|
|
277
|
+
reply({
|
|
278
|
+
state: snapshot(video),
|
|
279
|
+
frame
|
|
280
|
+
}, frame ? [frame] : []);
|
|
281
|
+
};
|
|
282
|
+
finish(0);
|
|
229
283
|
};
|
|
230
284
|
const release = (id) => {
|
|
231
285
|
const entry = entries.get(id);
|
|
@@ -234,17 +288,36 @@ function createVideoHost(endpoint, options = {}) {
|
|
|
234
288
|
videos.delete(id);
|
|
235
289
|
sentNetworkState.delete(id);
|
|
236
290
|
const { video } = entry;
|
|
237
|
-
options.onVideoDisposed?.(video, id);
|
|
238
291
|
entry.detach();
|
|
292
|
+
if (entry.adopted) return;
|
|
293
|
+
options.onVideoDisposed?.(video);
|
|
239
294
|
video.pause();
|
|
240
295
|
video.removeAttribute("src");
|
|
241
296
|
video.srcObject = null;
|
|
242
297
|
video.load();
|
|
243
298
|
video.remove();
|
|
244
299
|
};
|
|
300
|
+
let batch = null;
|
|
301
|
+
const handleBatch = (messages) => {
|
|
302
|
+
const current = {
|
|
303
|
+
created: [],
|
|
304
|
+
touched: /* @__PURE__ */ new Map()
|
|
305
|
+
};
|
|
306
|
+
batch = current;
|
|
307
|
+
try {
|
|
308
|
+
for (const message of messages) handle(message);
|
|
309
|
+
} finally {
|
|
310
|
+
batch = null;
|
|
311
|
+
}
|
|
312
|
+
for (const [id, video] of current.touched) if (entries.get(id)?.video === video) sendState(id, video);
|
|
313
|
+
for (const video of current.created) if ([...videos.values()].includes(video)) options.onVideoCreated?.(video);
|
|
314
|
+
};
|
|
245
315
|
const handle = (message) => {
|
|
246
316
|
if ("seq" in message) ack = Math.max(ack, message.seq);
|
|
247
317
|
switch (message.kind) {
|
|
318
|
+
case "batch":
|
|
319
|
+
handleBatch(message.messages);
|
|
320
|
+
return;
|
|
248
321
|
case "hello":
|
|
249
322
|
welcome();
|
|
250
323
|
return;
|
|
@@ -259,8 +332,11 @@ function createVideoHost(endpoint, options = {}) {
|
|
|
259
332
|
});
|
|
260
333
|
return;
|
|
261
334
|
case "create":
|
|
262
|
-
create(message.id);
|
|
335
|
+
create(message.id, message.props);
|
|
263
336
|
break;
|
|
337
|
+
case "connect":
|
|
338
|
+
connect(message.id, message.selector, message.callId);
|
|
339
|
+
return;
|
|
264
340
|
case "dispose":
|
|
265
341
|
release(message.id);
|
|
266
342
|
return;
|
|
@@ -296,7 +372,9 @@ function createVideoHost(endpoint, options = {}) {
|
|
|
296
372
|
}
|
|
297
373
|
}
|
|
298
374
|
const video = entries.get(message.id)?.video;
|
|
299
|
-
if (video)
|
|
375
|
+
if (!video) return;
|
|
376
|
+
if (batch) batch.touched.set(message.id, video);
|
|
377
|
+
else sendState(message.id, video);
|
|
300
378
|
};
|
|
301
379
|
const onMessage = (event) => {
|
|
302
380
|
if (isProtocolMessage(event.data)) handle(event.data);
|
|
@@ -377,9 +455,25 @@ function snapshot(video) {
|
|
|
377
455
|
creationTime: quality.creationTime,
|
|
378
456
|
droppedVideoFrames: quality.droppedVideoFrames,
|
|
379
457
|
totalVideoFrames: quality.totalVideoFrames
|
|
380
|
-
} : null
|
|
458
|
+
} : null,
|
|
459
|
+
props: snapshotProps(video)
|
|
381
460
|
};
|
|
382
461
|
}
|
|
462
|
+
function captureVideoFrame(video) {
|
|
463
|
+
if (video.readyState < 2 || typeof VideoFrame !== "function") return null;
|
|
464
|
+
try {
|
|
465
|
+
return new VideoFrame(video);
|
|
466
|
+
} catch {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function snapshotProps(video) {
|
|
471
|
+
const props = {};
|
|
472
|
+
for (const prop of MIRRORED_PROPERTIES) props[prop] = video[prop];
|
|
473
|
+
props.hasSrcAttribute = video.hasAttribute("src");
|
|
474
|
+
props.src = props.hasSrcAttribute ? video.src : "";
|
|
475
|
+
return props;
|
|
476
|
+
}
|
|
383
477
|
function toMetadata(metadata) {
|
|
384
478
|
const result = {
|
|
385
479
|
presentationTime: metadata.presentationTime,
|
|
@@ -420,4 +514,4 @@ function serializeError(error) {
|
|
|
420
514
|
//#endregion
|
|
421
515
|
export { createVideoHost as t };
|
|
422
516
|
|
|
423
|
-
//# sourceMappingURL=host-
|
|
517
|
+
//# sourceMappingURL=host-C01-_SSZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-C01-_SSZ.js","names":[],"sources":["../src/host/video-host.ts"],"sourcesContent":["import {\n CHANNEL,\n COMMON_MIME_TYPES,\n type CanPlayTypeResult,\n type ClientMessage,\n type FrameMetadata,\n type HostMessage,\n MEDIA_EVENTS,\n MIRRORED_PROPERTIES,\n type MediaState,\n type MessageEndpoint,\n type Ranges,\n type SerializedError,\n isProtocolMessage,\n} from \"../shared/protocol.ts\";\nimport { assertMainThread, isMainThread, isMessageEndpoint } from \"../shared/environment.ts\";\n\nexport interface VideoHostOptions {\n container?: HTMLElement | null;\n onVideoCreated?: (video: HTMLVideoElement) => void;\n onVideoDisposed?: (video: HTMLVideoElement) => void;\n canConnect?: (video: HTMLVideoElement, selector: string) => boolean;\n}\n\nexport interface VideoHost {\n readonly videos: ReadonlyMap<number, HTMLVideoElement>;\n dispose(): void;\n}\n\ntype Distribute<T> = T extends unknown ? Omit<T, typeof CHANNEL> : never;\ntype OutgoingHostMessage = Distribute<HostMessage>;\n\nconst FRAME_EVENTS = new Set([\"loadeddata\", \"seeked\"]);\n\nconst SILENT_STATE_POLL_INTERVAL = 16;\nconst SILENT_STATE_POLLS = 32;\n\ninterface Entry {\n video: HTMLVideoElement;\n adopted: boolean;\n frameCallback: number | null;\n frameInFlight: boolean;\n pendingFrame: { frame: VideoFrame; metadata: FrameMetadata } | null;\n sendPendingFrame: () => void;\n lastFrameTimestamp: number | null;\n frameDuration: number | null;\n detach: () => void;\n}\n\nconst FRAME_WAIT_TIMEOUT = 500;\nconst CONNECT_FRAME_ATTEMPTS = 30;\nconst TIMESTAMP_EPSILON = 1000;\n\nconst hosted = new WeakSet<object>();\n\nexport function createVideoHost(endpoint: MessageEndpoint, options: VideoHostOptions = {}): VideoHost {\n assertMainThread(\"createVideoHost()\");\n if (!isMessageEndpoint(endpoint) || (isMainThread() && endpoint === (globalThis as object))) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: createVideoHost() expects the Worker (or a MessagePort connected to it) that uses the polyfill.\",\n );\n }\n if (hosted.has(endpoint)) {\n throw new DOMException(\n \"html-video-element-webworker-polyfill: createVideoHost() was already called for this endpoint; call dispose() on the existing host first.\",\n \"InvalidStateError\",\n );\n }\n hosted.add(endpoint);\n const entries = new Map<number, Entry>();\n const videos = new Map<number, HTMLVideoElement>();\n let ack = 0;\n let disposed = false;\n\n const sentNetworkState = new Map<number, number>();\n const post = (message: OutgoingHostMessage, transfer: Transferable[] = []): void => {\n if (disposed) {\n for (const item of transfer) (item as Partial<VideoFrame>).close?.();\n return;\n }\n if (\"state\" in message) sentNetworkState.set(message.id, message.state.networkState);\n endpoint.postMessage({ ...message, [CHANNEL]: 1 }, transfer);\n };\n\n const watching = new Map<number, { polls: number }>();\n const sendState = (id: number, video: HTMLVideoElement): void => {\n post({ kind: \"state\", id, ack, state: snapshot(video) });\n const existing = watching.get(id);\n if (existing) {\n existing.polls = 0;\n return;\n }\n const watch = { polls: 0 };\n watching.set(id, watch);\n const poll = (): void => {\n if (entries.get(id)?.video !== video || ++watch.polls > SILENT_STATE_POLLS) {\n watching.delete(id);\n return;\n }\n if (video.networkState !== sentNetworkState.get(id)) {\n post({ kind: \"state\", id, ack, state: snapshot(video) });\n }\n setTimeout(poll, SILENT_STATE_POLL_INTERVAL);\n };\n setTimeout(poll, SILENT_STATE_POLL_INTERVAL);\n };\n\n const welcome = (): void => {\n const probe = document.createElement(\"video\");\n const canPlayType: Record<string, CanPlayTypeResult> = {};\n for (const type of COMMON_MIME_TYPES) canPlayType[type] = probe.canPlayType(type);\n post({ kind: \"welcome\", timeOrigin: performance.timeOrigin, canPlayType });\n };\n\n const captureFrame = (entry: Entry): VideoFrame | null => captureVideoFrame(entry.video);\n\n const attach = (id: number, video: HTMLVideoElement, adopted: boolean): Entry => {\n const entry: Entry = {\n video,\n adopted,\n frameCallback: null,\n lastFrameTimestamp: null,\n frameInFlight: false,\n pendingFrame: null,\n sendPendingFrame: () => {},\n frameDuration: null,\n detach: () => {},\n };\n\n const noteFrame = (frame: VideoFrame): void => {\n entry.lastFrameTimestamp = frame.timestamp;\n };\n\n let previousPresented: { frames: number; timestamp: number } | null = null;\n const learnFrameDuration = (frame: VideoFrame, presentedFrames: number): void => {\n const previous = previousPresented;\n previousPresented = { frames: presentedFrames, timestamp: frame.timestamp };\n if (!previous || presentedFrames !== previous.frames + 1 || frame.timestamp <= previous.timestamp) return;\n const delta = frame.timestamp - previous.timestamp;\n entry.frameDuration = entry.frameDuration === null ? delta : Math.min(entry.frameDuration, delta);\n };\n\n const shows = (frame: VideoFrame, target: number): boolean => {\n if (!video.paused && frame.timestamp >= target - TIMESTAMP_EPSILON) return true;\n if (frame.timestamp > target + TIMESTAMP_EPSILON) return false;\n const duration = frame.duration || entry.frameDuration;\n if (duration) return target < frame.timestamp + duration + TIMESTAMP_EPSILON;\n return frame.timestamp !== entry.lastFrameTimestamp;\n };\n\n const dropPendingFrame = (): void => {\n entry.pendingFrame?.frame.close();\n entry.pendingFrame = null;\n };\n\n const sendFrame = (frame: VideoFrame, metadata: FrameMetadata): void => {\n entry.frameInFlight = true;\n post({ kind: \"frame\", id, ack, state: snapshot(video), frame, metadata }, [frame]);\n };\n\n entry.sendPendingFrame = () => {\n entry.frameInFlight = false;\n const pending = entry.pendingFrame;\n if (!pending) return;\n entry.pendingFrame = null;\n sendFrame(pending.frame, pending.metadata);\n };\n\n const sendEvent = (type: string, frame: VideoFrame | null): void => {\n if (frame || type === \"emptied\") dropPendingFrame();\n if (!frame) {\n if (type === \"emptied\") entry.lastFrameTimestamp = null;\n post({ kind: \"event\", id, ack, type, state: snapshot(video) });\n return;\n }\n noteFrame(frame);\n post({ kind: \"event\", id, ack, type, state: snapshot(video), frame, metadata: syntheticMetadata(video, frame) }, [\n frame,\n ]);\n };\n\n let held: { type: string; target: number; queue: string[]; timer: ReturnType<typeof setTimeout> } | null = null;\n\n const releaseHeld = (frame: VideoFrame | null): void => {\n if (!held) return;\n const { type, queue, timer } = held;\n held = null;\n clearTimeout(timer);\n sendEvent(type, frame);\n for (const queued of queue) dispatch(queued);\n };\n\n const dispatch = (type: string): void => {\n if (held) {\n held.queue.push(type);\n return;\n }\n if (!FRAME_EVENTS.has(type)) {\n sendEvent(type, null);\n return;\n }\n const frame = captureFrame(entry);\n const target = video.currentTime * 1e6;\n if (!frame || shows(frame, target)) {\n sendEvent(type, frame);\n return;\n }\n frame.close();\n held = { type, target, queue: [], timer: setTimeout(() => releaseHeld(captureFrame(entry)), FRAME_WAIT_TIMEOUT) };\n };\n\n const onEvent = (event: Event): void => dispatch(event.type);\n for (const type of MEDIA_EVENTS) video.addEventListener(type, onEvent);\n\n const onFrame = (_now: number, metadata: VideoFrameCallbackMetadata): void => {\n entry.frameCallback = video.requestVideoFrameCallback(onFrame);\n const frame = captureFrame(entry);\n if (!frame) return;\n learnFrameDuration(frame, metadata.presentedFrames);\n if (held) {\n if (shows(frame, held.target)) releaseHeld(frame);\n else frame.close();\n return;\n }\n if (frame.timestamp === entry.lastFrameTimestamp) {\n frame.close();\n return;\n }\n noteFrame(frame);\n if (entry.frameInFlight) {\n dropPendingFrame();\n entry.pendingFrame = { frame, metadata: toMetadata(metadata) };\n } else {\n sendFrame(frame, toMetadata(metadata));\n }\n };\n if (typeof video.requestVideoFrameCallback === \"function\") {\n entry.frameCallback = video.requestVideoFrameCallback(onFrame);\n }\n\n entry.detach = () => {\n dropPendingFrame();\n for (const type of MEDIA_EVENTS) video.removeEventListener(type, onEvent);\n if (entry.frameCallback !== null) video.cancelVideoFrameCallback(entry.frameCallback);\n if (held) clearTimeout(held.timer);\n held = null;\n };\n\n entries.set(id, entry);\n videos.set(id, video);\n return entry;\n };\n\n const create = (id: number, props: Record<string, unknown>): void => {\n const video = document.createElement(\"video\");\n video.playsInline = true;\n if (typeof props.id === \"string\") video.id = props.id;\n attach(id, video, false);\n options.container?.append(video);\n if (batch) batch.created.push(video);\n else options.onVideoCreated?.(video);\n };\n\n const connect = (id: number, selector: string, callId: number | undefined): void => {\n const reply = (value: unknown, transfer: Transferable[] = []): void => {\n if (callId !== undefined) post({ kind: \"result\", callId, value }, transfer);\n };\n const fail = (name: string, message: string): void => {\n if (callId !== undefined) post({ kind: \"result\", callId, error: { name, message } });\n };\n let found: Element | null;\n try {\n found = document.querySelector(selector);\n } catch (error) {\n fail(\"SyntaxError\", (error as Error).message);\n return;\n }\n if (!found) {\n fail(\"NotFoundError\", `connectToHostVideo(): no element matches \"${selector}\" on the main thread.`);\n return;\n }\n if (!(found instanceof HTMLVideoElement)) {\n fail(\n \"InvalidNodeTypeError\",\n `connectToHostVideo(): \"${selector}\" matches a <${found.localName}>, not a <video>.`,\n );\n return;\n }\n if (options.canConnect && !options.canConnect(found, selector)) {\n fail(\"NotAllowedError\", `connectToHostVideo(): the host does not allow connecting to \"${selector}\".`);\n return;\n }\n const video = found;\n const finish = (attempt: number): void => {\n if (disposed) return;\n const frame = captureVideoFrame(video);\n if (!frame && video.readyState >= 2 && attempt < CONNECT_FRAME_ATTEMPTS) {\n setTimeout(() => finish(attempt + 1), SILENT_STATE_POLL_INTERVAL);\n return;\n }\n const entry = attach(id, video, true);\n if (frame) entry.lastFrameTimestamp = frame.timestamp;\n reply({ state: snapshot(video), frame }, frame ? [frame] : []);\n };\n finish(0);\n };\n\n const release = (id: number): void => {\n const entry = entries.get(id);\n if (!entry) return;\n entries.delete(id);\n videos.delete(id);\n sentNetworkState.delete(id);\n const { video } = entry;\n entry.detach();\n if (entry.adopted) return;\n options.onVideoDisposed?.(video);\n video.pause();\n video.removeAttribute(\"src\");\n video.srcObject = null;\n video.load();\n video.remove();\n };\n\n let batch: { created: HTMLVideoElement[]; touched: Map<number, HTMLVideoElement> } | null = null;\n\n const handleBatch = (messages: ClientMessage[]): void => {\n const current = { created: [] as HTMLVideoElement[], touched: new Map<number, HTMLVideoElement>() };\n batch = current;\n try {\n for (const message of messages) handle(message);\n } finally {\n batch = null;\n }\n for (const [id, video] of current.touched) {\n if (entries.get(id)?.video === video) sendState(id, video);\n }\n for (const video of current.created) {\n if ([...videos.values()].includes(video)) options.onVideoCreated?.(video);\n }\n };\n\n const handle = (message: ClientMessage): void => {\n if (\"seq\" in message) ack = Math.max(ack, message.seq);\n switch (message.kind) {\n case \"batch\":\n handleBatch(message.messages);\n return;\n case \"hello\":\n welcome();\n return;\n case \"frameAck\":\n entries.get(message.id)?.sendPendingFrame();\n return;\n case \"canPlayType\":\n post({ kind: \"result\", callId: message.callId, value: probeCanPlayType(message.type) });\n return;\n case \"create\":\n create(message.id, message.props);\n break;\n case \"connect\":\n connect(message.id, message.selector, message.callId);\n return;\n case \"dispose\":\n release(message.id);\n return;\n case \"set\": {\n const video = entries.get(message.id)?.video;\n if (!video) return;\n applyProperty(video, message.prop, message.value);\n break;\n }\n case \"call\": {\n const video = entries.get(message.id)?.video;\n if (!video) {\n if (message.callId !== undefined) {\n post({\n kind: \"result\",\n callId: message.callId,\n error: { name: \"InvalidStateError\", message: \"The element has been disposed.\" },\n });\n }\n return;\n }\n invoke(video, message.method, message.args).then(\n (value) => message.callId !== undefined && post({ kind: \"result\", callId: message.callId, value }),\n (error: unknown) =>\n message.callId !== undefined &&\n post({ kind: \"result\", callId: message.callId, error: serializeError(error) }),\n );\n break;\n }\n }\n const video = entries.get(message.id)?.video;\n if (!video) return;\n if (batch) batch.touched.set(message.id, video);\n else sendState(message.id, video);\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (isProtocolMessage(event.data)) handle(event.data as ClientMessage);\n };\n endpoint.addEventListener(\"message\", onMessage);\n endpoint.start?.();\n welcome();\n\n return {\n videos,\n dispose() {\n if (disposed) return;\n for (const id of entries.keys()) release(id);\n endpoint.removeEventListener(\"message\", onMessage);\n hosted.delete(endpoint);\n disposed = true;\n },\n };\n}\n\nfunction applyProperty(video: HTMLVideoElement, prop: string, value: unknown): void {\n try {\n if (prop === \"src\") video.src = value as string;\n else if (prop === \"srcObject\") video.srcObject = value as MediaProvider | null;\n else if (prop === \"currentTime\") video.currentTime = value as number;\n else if (MIRRORED_PROPERTIES.includes(prop)) (video as unknown as Record<string, unknown>)[prop] = value;\n } catch (error) {\n console.warn(`[html-video-element-webworker-polyfill] failed to set \"${prop}\":`, error);\n }\n}\n\nasync function invoke(video: HTMLVideoElement, method: string, args: unknown[]): Promise<unknown> {\n switch (method) {\n case \"play\":\n await video.play();\n return undefined;\n case \"pause\":\n return video.pause();\n case \"load\":\n return video.load();\n case \"fastSeek\":\n if (typeof video.fastSeek === \"function\") video.fastSeek(args[0] as number);\n else video.currentTime = args[0] as number;\n return undefined;\n case \"removeAttribute\":\n return video.removeAttribute(args[0] as string);\n default:\n throw new DOMException(`Unknown method ${method}`, \"NotSupportedError\");\n }\n}\n\nlet canPlayTypeProbe: HTMLVideoElement | undefined;\nfunction probeCanPlayType(type: string): CanPlayTypeResult {\n canPlayTypeProbe ??= document.createElement(\"video\");\n return canPlayTypeProbe.canPlayType(type);\n}\n\nfunction ranges(timeRanges: TimeRanges): Ranges {\n const result: Ranges = [];\n for (let i = 0; i < timeRanges.length; i++) result.push([timeRanges.start(i), timeRanges.end(i)]);\n return result;\n}\n\nfunction snapshot(video: HTMLVideoElement): MediaState {\n const quality = typeof video.getVideoPlaybackQuality === \"function\" ? video.getVideoPlaybackQuality() : null;\n return {\n currentSrc: video.currentSrc,\n currentTime: video.currentTime,\n duration: video.duration,\n ended: video.ended,\n error: video.error ? { code: video.error.code, message: video.error.message } : null,\n muted: video.muted,\n networkState: video.networkState,\n paused: video.paused,\n playbackRate: video.playbackRate,\n readyState: video.readyState,\n seeking: video.seeking,\n videoHeight: video.videoHeight,\n videoWidth: video.videoWidth,\n volume: video.volume,\n buffered: ranges(video.buffered),\n played: ranges(video.played),\n seekable: ranges(video.seekable),\n quality: quality\n ? {\n creationTime: quality.creationTime,\n droppedVideoFrames: quality.droppedVideoFrames,\n totalVideoFrames: quality.totalVideoFrames,\n }\n : null,\n props: snapshotProps(video),\n };\n}\n\nfunction captureVideoFrame(video: HTMLVideoElement): VideoFrame | null {\n if (video.readyState < 2 || typeof VideoFrame !== \"function\") return null;\n try {\n return new VideoFrame(video);\n } catch {\n return null;\n }\n}\n\nfunction snapshotProps(video: HTMLVideoElement): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n for (const prop of MIRRORED_PROPERTIES) props[prop] = (video as unknown as Record<string, unknown>)[prop];\n props.hasSrcAttribute = video.hasAttribute(\"src\");\n props.src = props.hasSrcAttribute ? video.src : \"\";\n return props;\n}\n\nfunction toMetadata(metadata: VideoFrameCallbackMetadata): FrameMetadata {\n const result: FrameMetadata = {\n presentationTime: metadata.presentationTime,\n expectedDisplayTime: metadata.expectedDisplayTime,\n width: metadata.width,\n height: metadata.height,\n mediaTime: metadata.mediaTime,\n presentedFrames: metadata.presentedFrames,\n };\n if (metadata.processingDuration !== undefined) result.processingDuration = metadata.processingDuration;\n if (metadata.captureTime !== undefined) result.captureTime = metadata.captureTime;\n if (metadata.receiveTime !== undefined) result.receiveTime = metadata.receiveTime;\n if (metadata.rtpTimestamp !== undefined) result.rtpTimestamp = metadata.rtpTimestamp;\n return result;\n}\n\nfunction syntheticMetadata(video: HTMLVideoElement, frame: VideoFrame): FrameMetadata {\n const now = performance.now();\n const quality = typeof video.getVideoPlaybackQuality === \"function\" ? video.getVideoPlaybackQuality() : null;\n return {\n presentationTime: now,\n expectedDisplayTime: now,\n width: frame.displayWidth,\n height: frame.displayHeight,\n mediaTime: frame.timestamp / 1e6,\n presentedFrames: quality?.totalVideoFrames ?? 0,\n };\n}\n\nfunction serializeError(error: unknown): SerializedError {\n if (error instanceof Error || error instanceof DOMException) return { name: error.name, message: error.message };\n return { name: \"Error\", message: String(error) };\n}\n"],"mappings":"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"}
|
package/dist/host.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as isMainThread, o as MessageEndpoint, r as isWorker, t as InvalidEnvironmentError } from "./environment-W_2WcDor.js";
|
|
2
|
-
import { n as VideoHostOptions, r as createVideoHost, t as VideoHost } from "./index-
|
|
2
|
+
import { n as VideoHostOptions, r as createVideoHost, t as VideoHost } from "./index-DfmcCbjK.js";
|
|
3
3
|
export { InvalidEnvironmentError, type MessageEndpoint, type VideoHost, type VideoHostOptions, createVideoHost, isMainThread, isWorker };
|
package/dist/host.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { i as isMainThread, o as isWorker, t as InvalidEnvironmentError } from "./environment-De2r8LaA.js";
|
|
2
|
-
import { t as createVideoHost } from "./host-
|
|
2
|
+
import { t as createVideoHost } from "./host-C01-_SSZ.js";
|
|
3
3
|
export { InvalidEnvironmentError, createVideoHost, isMainThread, isWorker };
|
|
@@ -25,6 +25,7 @@ interface MirroredProps {
|
|
|
25
25
|
disablePictureInPicture: boolean;
|
|
26
26
|
disableRemotePlayback: boolean;
|
|
27
27
|
height: number;
|
|
28
|
+
id: string;
|
|
28
29
|
loop: boolean;
|
|
29
30
|
playsInline: boolean;
|
|
30
31
|
poster: string;
|
|
@@ -100,6 +101,8 @@ declare class WorkerVideoElement extends EventTarget {
|
|
|
100
101
|
set disablePictureInPicture(value: boolean);
|
|
101
102
|
get disableRemotePlayback(): boolean;
|
|
102
103
|
set disableRemotePlayback(value: boolean);
|
|
104
|
+
get id(): string;
|
|
105
|
+
set id(value: string);
|
|
103
106
|
get height(): number;
|
|
104
107
|
set height(value: number);
|
|
105
108
|
get width(): number;
|
|
@@ -156,6 +159,7 @@ interface WorkerVideoElement {
|
|
|
156
159
|
onwaitingforkey: EventHandler;
|
|
157
160
|
}
|
|
158
161
|
declare function createVideoElement(options?: CreateVideoElementOptions): WorkerVideoElement;
|
|
162
|
+
declare function connectToHostVideo(selector: string, options?: CreateVideoElementOptions): Promise<WorkerVideoElement>;
|
|
159
163
|
//#endregion
|
|
160
164
|
//#region src/worker/document.d.ts
|
|
161
165
|
declare function polyfillDocument(options?: CreateVideoElementOptions): void;
|
|
@@ -182,5 +186,5 @@ declare class WorkerMediaError implements MediaError {
|
|
|
182
186
|
constructor({ code, message }: SerializedMediaError);
|
|
183
187
|
}
|
|
184
188
|
//#endregion
|
|
185
|
-
export { VideoFrameRequestCallback as a,
|
|
186
|
-
//# sourceMappingURL=index-
|
|
189
|
+
export { VideoFrameRequestCallback as a, createVideoElement as c, frameOf as d, isFrameSource as f, CreateVideoElementOptions as i, FRAME_SOURCE as l, WorkerTimeRanges as n, WorkerVideoElement as o, configureVideoTransport as p, polyfillDocument as r, connectToHostVideo as s, WorkerMediaError as t, FrameSource as u };
|
|
190
|
+
//# sourceMappingURL=index-DaAgPNC9.d.ts.map
|
|
@@ -2,8 +2,9 @@ import { o as MessageEndpoint } from "./environment-W_2WcDor.js";
|
|
|
2
2
|
//#region src/host/video-host.d.ts
|
|
3
3
|
interface VideoHostOptions {
|
|
4
4
|
container?: HTMLElement | null;
|
|
5
|
-
onVideoCreated?: (video: HTMLVideoElement
|
|
6
|
-
onVideoDisposed?: (video: HTMLVideoElement
|
|
5
|
+
onVideoCreated?: (video: HTMLVideoElement) => void;
|
|
6
|
+
onVideoDisposed?: (video: HTMLVideoElement) => void;
|
|
7
|
+
canConnect?: (video: HTMLVideoElement, selector: string) => boolean;
|
|
7
8
|
}
|
|
8
9
|
interface VideoHost {
|
|
9
10
|
readonly videos: ReadonlyMap<number, HTMLVideoElement>;
|
|
@@ -12,4 +13,4 @@ interface VideoHost {
|
|
|
12
13
|
declare function createVideoHost(endpoint: MessageEndpoint, options?: VideoHostOptions): VideoHost;
|
|
13
14
|
//#endregion
|
|
14
15
|
export { VideoHostOptions as n, createVideoHost as r, VideoHost as t };
|
|
15
|
-
//# sourceMappingURL=index-
|
|
16
|
+
//# sourceMappingURL=index-DfmcCbjK.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as FrameMetadata, n as isMainThread, o as MessageEndpoint, r as isWorker, t as InvalidEnvironmentError } from "./environment-W_2WcDor.js";
|
|
2
|
-
import { n as VideoHostOptions, r as createVideoHost, t as VideoHost } from "./index-
|
|
3
|
-
import { a as VideoFrameRequestCallback, c as
|
|
2
|
+
import { n as VideoHostOptions, r as createVideoHost, t as VideoHost } from "./index-DfmcCbjK.js";
|
|
3
|
+
import { a as VideoFrameRequestCallback, c as createVideoElement, d as frameOf, f as isFrameSource, i as CreateVideoElementOptions, l as FRAME_SOURCE, n as WorkerTimeRanges, o as WorkerVideoElement, p as configureVideoTransport, r as polyfillDocument, s as connectToHostVideo, t as WorkerMediaError, u as FrameSource } from "./index-DaAgPNC9.js";
|
|
4
4
|
import { polyfill2dCanvasApi } from "./canvas2d.js";
|
|
5
5
|
import { polyfillWebglAPI } from "./webgl.js";
|
|
6
6
|
import { polyfillWebgpu } from "./webgpu.js";
|
|
@@ -8,5 +8,5 @@ import { polyfillCreateImageBitmap, polyfillVideoFrame } from "./image-bitmap.js
|
|
|
8
8
|
//#region src/install.d.ts
|
|
9
9
|
export declare function installWorkerPolyfills(): void;
|
|
10
10
|
//#endregion
|
|
11
|
-
export { type CreateVideoElementOptions, FRAME_SOURCE, type FrameMetadata, type FrameSource, InvalidEnvironmentError, type MessageEndpoint, type VideoFrameRequestCallback, type VideoHost, type VideoHostOptions, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, createVideoElement, createVideoHost, frameOf, isFrameSource, isMainThread, isWorker, polyfill2dCanvasApi, polyfillCreateImageBitmap, polyfillDocument, polyfillVideoFrame, polyfillWebglAPI, polyfillWebgpu };
|
|
11
|
+
export { type CreateVideoElementOptions, FRAME_SOURCE, type FrameMetadata, type FrameSource, InvalidEnvironmentError, type MessageEndpoint, type VideoFrameRequestCallback, type VideoHost, type VideoHostOptions, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, connectToHostVideo, createVideoElement, createVideoHost, frameOf, isFrameSource, isMainThread, isWorker, polyfill2dCanvasApi, polyfillCreateImageBitmap, polyfillDocument, polyfillVideoFrame, polyfillWebglAPI, polyfillWebgpu };
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { i as isMainThread, o as isWorker, t as InvalidEnvironmentError } from "./environment-De2r8LaA.js";
|
|
2
|
-
import { t as createVideoHost } from "./host-
|
|
3
|
-
import { a as
|
|
2
|
+
import { t as createVideoHost } from "./host-C01-_SSZ.js";
|
|
3
|
+
import { a as WorkerMediaError, i as createVideoElement, n as WorkerVideoElement, o as WorkerTimeRanges, r as connectToHostVideo, s as configureVideoTransport, t as polyfillDocument } from "./document-BhePs2Wq.js";
|
|
4
4
|
import { n as frameOf, r as isFrameSource, t as FRAME_SOURCE } from "./frame-source-BG--PzqD.js";
|
|
5
5
|
import "./worker.js";
|
|
6
6
|
import { polyfill2dCanvasApi } from "./canvas2d.js";
|
|
7
7
|
import { polyfillWebglAPI } from "./webgl.js";
|
|
8
8
|
import { polyfillWebgpu } from "./webgpu.js";
|
|
9
9
|
import { polyfillCreateImageBitmap, polyfillVideoFrame } from "./image-bitmap.js";
|
|
10
|
-
import { t as installWorkerPolyfills } from "./install-
|
|
11
|
-
export { FRAME_SOURCE, InvalidEnvironmentError, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, createVideoElement, createVideoHost, frameOf, installWorkerPolyfills, isFrameSource, isMainThread, isWorker, polyfill2dCanvasApi, polyfillCreateImageBitmap, polyfillDocument, polyfillVideoFrame, polyfillWebglAPI, polyfillWebgpu };
|
|
10
|
+
import { t as installWorkerPolyfills } from "./install-BV6rqIiK.js";
|
|
11
|
+
export { FRAME_SOURCE, InvalidEnvironmentError, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, connectToHostVideo, createVideoElement, createVideoHost, frameOf, installWorkerPolyfills, isFrameSource, isMainThread, isWorker, polyfill2dCanvasApi, polyfillCreateImageBitmap, polyfillDocument, polyfillVideoFrame, polyfillWebglAPI, polyfillWebgpu };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as assertWorker } from "./environment-De2r8LaA.js";
|
|
2
|
-
import { t as polyfillDocument } from "./document-
|
|
2
|
+
import { t as polyfillDocument } from "./document-BhePs2Wq.js";
|
|
3
3
|
import { polyfill2dCanvasApi } from "./canvas2d.js";
|
|
4
4
|
import { polyfillWebglAPI } from "./webgl.js";
|
|
5
5
|
import { polyfillWebgpu } from "./webgpu.js";
|
|
@@ -17,4 +17,4 @@ function installWorkerPolyfills() {
|
|
|
17
17
|
//#endregion
|
|
18
18
|
export { installWorkerPolyfills as t };
|
|
19
19
|
|
|
20
|
-
//# sourceMappingURL=install-
|
|
20
|
+
//# sourceMappingURL=install-BV6rqIiK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-
|
|
1
|
+
{"version":3,"file":"install-BV6rqIiK.js","names":[],"sources":["../src/install.ts"],"sourcesContent":["import { polyfill2dCanvasApi } from \"./polyfills/canvas2d.ts\";\nimport { polyfillCreateImageBitmap, polyfillVideoFrame } from \"./polyfills/image-bitmap.ts\";\nimport { polyfillWebglAPI } from \"./polyfills/webgl.ts\";\nimport { polyfillWebgpu } from \"./polyfills/webgpu.ts\";\nimport { polyfillDocument } from \"./worker/document.ts\";\nimport { assertWorker } from \"./shared/environment.ts\";\n\nexport function installWorkerPolyfills(): void {\n assertWorker(\"installWorkerPolyfills()\");\n polyfillDocument();\n polyfill2dCanvasApi();\n polyfillWebglAPI();\n polyfillWebgpu();\n polyfillCreateImageBitmap();\n polyfillVideoFrame();\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,yBAA+B;CAC7C,aAAa,0BAA0B;CACvC,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,eAAe;CACf,0BAA0B;CAC1B,mBAAmB;AACrB"}
|
|
@@ -36,6 +36,7 @@ const MIRRORED_PROPERTIES = [
|
|
|
36
36
|
"disablePictureInPicture",
|
|
37
37
|
"disableRemotePlayback",
|
|
38
38
|
"height",
|
|
39
|
+
"id",
|
|
39
40
|
"loop",
|
|
40
41
|
"muted",
|
|
41
42
|
"playbackRate",
|
|
@@ -76,4 +77,4 @@ const COMMON_MIME_TYPES = [
|
|
|
76
77
|
//#endregion
|
|
77
78
|
export { isProtocolMessage as a, MIRRORED_PROPERTIES as i, COMMON_MIME_TYPES as n, MEDIA_EVENTS as r, CHANNEL as t };
|
|
78
79
|
|
|
79
|
-
//# sourceMappingURL=protocol
|
|
80
|
+
//# sourceMappingURL=protocol--LD8Qk5Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol--LD8Qk5Y.js","names":[],"sources":["../src/shared/protocol.ts"],"sourcesContent":["export const CHANNEL = \"__htmlVideoElementWorkerPolyfill\" as const;\n\nexport const MEDIA_EVENTS: readonly string[] = [\n \"abort\",\n \"canplay\",\n \"canplaythrough\",\n \"durationchange\",\n \"emptied\",\n \"encrypted\",\n \"ended\",\n \"error\",\n \"loadeddata\",\n \"loadedmetadata\",\n \"loadstart\",\n \"pause\",\n \"play\",\n \"playing\",\n \"progress\",\n \"ratechange\",\n \"resize\",\n \"seeked\",\n \"seeking\",\n \"stalled\",\n \"suspend\",\n \"timeupdate\",\n \"volumechange\",\n \"waiting\",\n \"waitingforkey\",\n];\n\nexport const MIRRORED_PROPERTIES: readonly string[] = [\n \"autoplay\",\n \"controls\",\n \"crossOrigin\",\n \"defaultMuted\",\n \"defaultPlaybackRate\",\n \"disablePictureInPicture\",\n \"disableRemotePlayback\",\n \"height\",\n \"id\",\n \"loop\",\n \"muted\",\n \"playbackRate\",\n \"playsInline\",\n \"poster\",\n \"preload\",\n \"preservesPitch\",\n \"volume\",\n \"width\",\n];\n\nexport type Ranges = Array<[start: number, end: number]>;\n\nexport interface SerializedMediaError {\n code: number;\n message: string;\n}\n\nexport interface SerializedPlaybackQuality {\n creationTime: number;\n droppedVideoFrames: number;\n totalVideoFrames: number;\n}\n\nexport interface MediaState {\n currentSrc: string;\n currentTime: number;\n duration: number;\n ended: boolean;\n error: SerializedMediaError | null;\n muted: boolean;\n networkState: number;\n paused: boolean;\n playbackRate: number;\n readyState: number;\n seeking: boolean;\n videoHeight: number;\n videoWidth: number;\n volume: number;\n buffered: Ranges;\n played: Ranges;\n seekable: Ranges;\n quality: SerializedPlaybackQuality | null;\n props: Record<string, unknown>;\n}\n\nexport interface ConnectResult {\n state: MediaState;\n frame: VideoFrame | null;\n}\n\nexport interface FrameMetadata {\n presentationTime: number;\n expectedDisplayTime: number;\n width: number;\n height: number;\n mediaTime: number;\n presentedFrames: number;\n processingDuration?: number;\n captureTime?: number;\n receiveTime?: number;\n rtpTimestamp?: number;\n}\n\nexport interface SerializedError {\n name: string;\n message: string;\n}\n\nexport type ClientMessage =\n | { [CHANNEL]: 1; kind: \"create\"; id: number; seq: number; props: Record<string, unknown> }\n | { [CHANNEL]: 1; kind: \"set\"; id: number; seq: number; prop: string; value: unknown }\n | {\n [CHANNEL]: 1;\n kind: \"call\";\n id: number;\n seq: number;\n method: \"play\" | \"pause\" | \"load\" | \"fastSeek\" | \"removeAttribute\";\n args: unknown[];\n callId?: number;\n }\n | { [CHANNEL]: 1; kind: \"connect\"; id: number; seq: number; selector: string; callId?: number }\n | { [CHANNEL]: 1; kind: \"dispose\"; id: number; seq: number }\n | { [CHANNEL]: 1; kind: \"canPlayType\"; type: string; callId: number }\n | { [CHANNEL]: 1; kind: \"frameAck\"; id: number; seq: number }\n | { [CHANNEL]: 1; kind: \"hello\" }\n | { [CHANNEL]: 1; kind: \"batch\"; messages: ClientMessage[] };\n\nexport type HostMessage =\n | {\n [CHANNEL]: 1;\n kind: \"event\";\n id: number;\n ack: number;\n type: string;\n state: MediaState;\n frame?: VideoFrame;\n metadata?: FrameMetadata;\n }\n | {\n [CHANNEL]: 1;\n kind: \"frame\";\n id: number;\n ack: number;\n state: MediaState;\n frame: VideoFrame;\n metadata: FrameMetadata;\n }\n | { [CHANNEL]: 1; kind: \"state\"; id: number; ack: number; state: MediaState }\n | { [CHANNEL]: 1; kind: \"result\"; callId: number; value?: unknown; error?: SerializedError }\n | {\n [CHANNEL]: 1;\n kind: \"welcome\";\n timeOrigin: number;\n canPlayType: Record<string, CanPlayTypeResult>;\n };\n\nexport type CanPlayTypeResult = \"\" | \"maybe\" | \"probably\";\n\nexport interface MessageEndpoint {\n postMessage(message: unknown, transfer: Transferable[]): void;\n addEventListener(type: \"message\", listener: (event: MessageEvent) => void): void;\n removeEventListener(type: \"message\", listener: (event: MessageEvent) => void): void;\n start?: () => void;\n}\n\nexport function isProtocolMessage(data: unknown): boolean {\n return typeof data === \"object\" && data !== null && (data as Record<string, unknown>)[CHANNEL] === 1;\n}\n\nexport const COMMON_MIME_TYPES: readonly string[] = [\n \"video/mp4\",\n \"video/webm\",\n \"video/ogg\",\n \"video/quicktime\",\n \"video/x-matroska\",\n \"application/vnd.apple.mpegurl\",\n 'video/mp4; codecs=\"avc1.42E01E\"',\n 'video/mp4; codecs=\"avc1.4D401E\"',\n 'video/mp4; codecs=\"avc1.64001E\"',\n 'video/mp4; codecs=\"hvc1.1.6.L93.B0\"',\n 'video/mp4; codecs=\"av01.0.05M.08\"',\n 'video/mp4; codecs=\"vp09.00.10.08\"',\n 'video/webm; codecs=\"vp8\"',\n 'video/webm; codecs=\"vp9\"',\n 'video/webm; codecs=\"av01.0.05M.08\"',\n 'video/ogg; codecs=\"theora\"',\n \"audio/mpeg\",\n \"audio/mp4\",\n \"audio/ogg\",\n \"audio/webm\",\n \"audio/wav\",\n \"audio/flac\",\n];\n"],"mappings":";AAAA,MAAa,UAAU;AAEvB,MAAa,eAAkC;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,sBAAyC;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAqHA,SAAgB,kBAAkB,MAAwB;CACxD,OAAO,OAAO,SAAS,YAAY,SAAS,QAAS,KAAA,wCAA8C;AACrG;AAEA,MAAa,oBAAuC;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
package/dist/worker.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as FrameMetadata, n as isMainThread, o as MessageEndpoint, r as isWorker, t as InvalidEnvironmentError } from "./environment-W_2WcDor.js";
|
|
2
|
-
import { a as VideoFrameRequestCallback,
|
|
3
|
-
export { type CreateVideoElementOptions, type FrameMetadata, InvalidEnvironmentError, type MessageEndpoint, type VideoFrameRequestCallback, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, createVideoElement, isMainThread, isWorker, polyfillDocument };
|
|
2
|
+
import { a as VideoFrameRequestCallback, c as createVideoElement, i as CreateVideoElementOptions, n as WorkerTimeRanges, o as WorkerVideoElement, p as configureVideoTransport, r as polyfillDocument, s as connectToHostVideo, t as WorkerMediaError } from "./index-DaAgPNC9.js";
|
|
3
|
+
export { type CreateVideoElementOptions, type FrameMetadata, InvalidEnvironmentError, type MessageEndpoint, type VideoFrameRequestCallback, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, connectToHostVideo, createVideoElement, isMainThread, isWorker, polyfillDocument };
|
package/dist/worker.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { i as isMainThread, o as isWorker, t as InvalidEnvironmentError } from "./environment-De2r8LaA.js";
|
|
2
|
-
import { a as
|
|
3
|
-
export { InvalidEnvironmentError, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, createVideoElement, isMainThread, isWorker, polyfillDocument };
|
|
2
|
+
import { a as WorkerMediaError, i as createVideoElement, n as WorkerVideoElement, o as WorkerTimeRanges, r as connectToHostVideo, s as configureVideoTransport, t as polyfillDocument } from "./document-BhePs2Wq.js";
|
|
3
|
+
export { InvalidEnvironmentError, WorkerMediaError, WorkerTimeRanges, WorkerVideoElement, configureVideoTransport, connectToHostVideo, createVideoElement, isMainThread, isWorker, polyfillDocument };
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-video-element-webworker-polyfill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "HTMLVideoElement inside Web Workers: a main-thread <video> mirrored into the worker with synchronous state, events and VideoFrames, plus Canvas 2D / WebGL / WebGPU polyfills.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
6
|
+
"canvas",
|
|
7
|
+
"frame-extraction",
|
|
7
8
|
"html5-video",
|
|
8
9
|
"htmlvideoelement",
|
|
9
|
-
"video-processing",
|
|
10
|
-
"frame-extraction",
|
|
11
|
-
"videoframe",
|
|
12
|
-
"webcodecs",
|
|
13
|
-
"worker",
|
|
14
|
-
"web-worker",
|
|
15
|
-
"webworker",
|
|
16
10
|
"multithreading",
|
|
17
11
|
"off-main-thread",
|
|
18
|
-
"canvas",
|
|
19
12
|
"offscreencanvas",
|
|
13
|
+
"polyfill",
|
|
14
|
+
"video",
|
|
15
|
+
"video-processing",
|
|
16
|
+
"videoframe",
|
|
17
|
+
"web-worker",
|
|
18
|
+
"webcodecs",
|
|
20
19
|
"webgl",
|
|
21
20
|
"webgpu",
|
|
22
|
-
"
|
|
21
|
+
"webworker",
|
|
22
|
+
"worker"
|
|
23
23
|
],
|
|
24
24
|
"homepage": "https://stepancar.github.io/html-video-element-webworker-polyfill/",
|
|
25
25
|
"bugs": {
|
|
@@ -95,7 +95,8 @@
|
|
|
95
95
|
"demo:build": "vite build demo",
|
|
96
96
|
"prepublishOnly": "npm run build",
|
|
97
97
|
"check:treeshake": "node scripts/check-treeshake.mjs",
|
|
98
|
-
"test:update-linux": "scripts/update-linux-screenshots.sh"
|
|
98
|
+
"test:update-linux": "scripts/update-linux-screenshots.sh",
|
|
99
|
+
"prepare": "node scripts/install-hooks.mjs"
|
|
99
100
|
},
|
|
100
101
|
"devDependencies": {
|
|
101
102
|
"@types/node": "^26.6.5",
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
"@vitest/browser-playwright": "^5.0.4",
|
|
104
105
|
"@webgpu/types": "^0.1.74",
|
|
105
106
|
"highlight.js": "^11.12.0",
|
|
107
|
+
"lefthook": "^2.2.2",
|
|
106
108
|
"oxfmt": "^0.73.0",
|
|
107
109
|
"oxlint": "^1.88.0",
|
|
108
110
|
"playwright": "^1.64.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"document-GIe-DKmi.js","names":[],"sources":["../src/worker/bridge.ts","../src/worker/media-types.ts","../src/worker/video-element.ts","../src/worker/document.ts"],"sourcesContent":["import {\n CHANNEL,\n type CanPlayTypeResult,\n type ClientMessage,\n type HostMessage,\n type MessageEndpoint,\n isProtocolMessage,\n} from \"../shared/protocol.ts\";\nimport { assertWorker, isMessageEndpoint } from \"../shared/environment.ts\";\n\nexport const MISSING_HOST_WARNING_DELAY = 3000;\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\nexport type OutgoingMessage = DistributiveOmit<ClientMessage, typeof CHANNEL | \"seq\">;\n\nexport interface ElementReceiver {\n receive(message: Extract<HostMessage, { id: number }>): void;\n}\n\ninterface Finalizable {\n id: number;\n release: () => void;\n}\n\nexport class Bridge {\n readonly endpoint: MessageEndpoint;\n timeOffset = 0;\n\n #seq = 0;\n #nextId = 1;\n #nextCallId = 1;\n readonly #receivers = new Map<number, WeakRef<ElementReceiver>>();\n readonly #pinned = new Set<object>();\n readonly #calls = new Map<number, { resolve: (value: unknown) => void; reject: (error: unknown) => void }>();\n readonly #canPlayType = new Map<string, CanPlayTypeResult>();\n readonly #registry: FinalizationRegistry<Finalizable> | null;\n #welcomed = false;\n #missingHostTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(endpoint: MessageEndpoint) {\n this.endpoint = endpoint;\n this.#registry =\n typeof FinalizationRegistry === \"function\"\n ? new FinalizationRegistry<Finalizable>(({ id, release }) => {\n release();\n this.#receivers.delete(id);\n this.post({ kind: \"dispose\", id });\n })\n : null;\n endpoint.addEventListener(\"message\", this.#onMessage);\n endpoint.start?.();\n this.post({ kind: \"hello\" });\n }\n\n watchForHost(): void {\n if (this.#welcomed || this.#missingHostTimer !== undefined) return;\n this.#missingHostTimer = setTimeout(() => {\n if (this.#welcomed) return;\n console.warn(\n \"html-video-element-webworker-polyfill: no VideoHost answered this worker. \" +\n \"Call createVideoHost(worker) on the main thread right after creating the worker, otherwise videos never load.\",\n );\n }, MISSING_HOST_WARNING_DELAY);\n }\n\n nextId(): number {\n return this.#nextId++;\n }\n\n post(message: OutgoingMessage, transfer: Transferable[] = []): number {\n const seq = ++this.#seq;\n this.endpoint.postMessage({ ...message, [CHANNEL]: 1, seq }, transfer);\n return seq;\n }\n\n call(message: OutgoingMessage & { kind: \"call\" }, transfer?: Transferable[]): [number, Promise<unknown>] {\n const callId = this.#nextCallId++;\n const promise = new Promise((resolve, reject) => this.#calls.set(callId, { resolve, reject }));\n return [this.post({ ...message, callId }, transfer), promise];\n }\n\n register(id: number, element: object, receiver: ElementReceiver, release: () => void): void {\n this.#receivers.set(id, new WeakRef(receiver));\n this.#registry?.register(element, { id, release }, receiver);\n }\n\n unregister(id: number, receiver: ElementReceiver, element: object): void {\n this.#receivers.delete(id);\n this.#registry?.unregister(receiver);\n this.#pinned.delete(element);\n }\n\n pin(element: object, pinned: boolean): void {\n if (pinned) this.#pinned.add(element);\n else this.#pinned.delete(element);\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n const cached = this.#canPlayType.get(type);\n if (cached !== undefined) return cached;\n const callId = this.#nextCallId++;\n this.#calls.set(callId, {\n resolve: (value) => this.#canPlayType.set(type, value as CanPlayTypeResult),\n reject: () => {},\n });\n this.post({ kind: \"canPlayType\", type, callId });\n return guessCanPlayType(type);\n }\n\n #onMessage = (event: MessageEvent): void => {\n if (!isProtocolMessage(event.data)) return;\n const message = event.data as HostMessage;\n switch (message.kind) {\n case \"welcome\": {\n this.#welcomed = true;\n clearTimeout(this.#missingHostTimer);\n this.timeOffset = message.timeOrigin - performance.timeOrigin;\n for (const [type, result] of Object.entries(message.canPlayType)) this.#canPlayType.set(type, result);\n return;\n }\n case \"result\": {\n const call = this.#calls.get(message.callId);\n if (!call) return;\n this.#calls.delete(message.callId);\n if (message.error) call.reject(new DOMException(message.error.message, message.error.name));\n else call.resolve(message.value);\n return;\n }\n default: {\n const receiver = this.#receivers.get(message.id)?.deref();\n if (receiver) receiver.receive(message);\n else if (\"frame\" in message) message.frame?.close();\n if (message.kind === \"frame\") this.post({ kind: \"frameAck\", id: message.id });\n }\n }\n };\n}\n\nconst CONTAINER_CODECS: Record<string, string[]> = {\n \"video/webm\": [\"vp8\", \"vp9\", \"av01.0.05M.08\"],\n \"video/mp4\": [\"avc1.42E01E\", \"av01.0.05M.08\", \"hvc1.1.6.L93.B0\", \"vp09.00.10.08\"],\n \"audio/webm\": [\"opus\", \"vorbis\"],\n \"audio/mp4\": [\"mp4a.40.2\", \"opus\", \"flac\"],\n};\n\nfunction guessCanPlayType(type: string): CanPlayTypeResult {\n const MediaSourceCtor = (globalThis as { MediaSource?: { isTypeSupported(type: string): boolean } }).MediaSource;\n if (!MediaSourceCtor) return \"\";\n if (/codecs\\s*=/i.test(type)) return MediaSourceCtor.isTypeSupported(type) ? \"probably\" : \"\";\n if (MediaSourceCtor.isTypeSupported(type)) return \"maybe\";\n const container = type.split(\";\")[0]!.trim().toLowerCase();\n const codecs = CONTAINER_CODECS[container] ?? [];\n return codecs.some((codec) => MediaSourceCtor.isTypeSupported(`${container}; codecs=\"${codec}\"`)) ? \"maybe\" : \"\";\n}\n\nconst bridges = new WeakMap<object, Bridge>();\nlet defaultEndpoint: MessageEndpoint | undefined;\n\nexport function bridgeFor(endpoint: MessageEndpoint | undefined): Bridge {\n const target = endpoint ?? defaultEndpoint ?? (globalThis as unknown as MessageEndpoint);\n if (!isMessageEndpoint(target)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: `transport` must be a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n let bridge = bridges.get(target);\n if (!bridge) {\n bridge = new Bridge(target);\n bridges.set(target, bridge);\n }\n return bridge;\n}\n\nexport function configureVideoTransport(endpoint: MessageEndpoint): void {\n assertWorker(\"configureVideoTransport()\");\n if (!isMessageEndpoint(endpoint)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: configureVideoTransport() expects a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n defaultEndpoint = endpoint;\n}\n","import type { Ranges, SerializedMediaError } from \"../shared/protocol.ts\";\n\nexport class WorkerTimeRanges implements TimeRanges {\n readonly #ranges: Ranges;\n\n constructor(ranges: Ranges = []) {\n this.#ranges = ranges;\n }\n\n get length(): number {\n return this.#ranges.length;\n }\n\n start(index: number): number {\n return this.#at(index)[0];\n }\n\n end(index: number): number {\n return this.#at(index)[1];\n }\n\n #at(index: number): [number, number] {\n const range = this.#ranges[index];\n if (!range) {\n throw new DOMException(\n `The index provided (${index}) is greater than or equal to the maximum bound (${this.#ranges.length}).`,\n \"IndexSizeError\",\n );\n }\n return range;\n }\n}\n\nexport class WorkerMediaError implements MediaError {\n static readonly MEDIA_ERR_ABORTED = 1 as const;\n static readonly MEDIA_ERR_NETWORK = 2 as const;\n static readonly MEDIA_ERR_DECODE = 3 as const;\n static readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n readonly MEDIA_ERR_ABORTED = 1 as const;\n readonly MEDIA_ERR_NETWORK = 2 as const;\n readonly MEDIA_ERR_DECODE = 3 as const;\n readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n\n readonly code: number;\n readonly message: string;\n\n constructor({ code, message }: SerializedMediaError) {\n this.code = code;\n this.message = message;\n }\n}\n","import { assertWorker } from \"../shared/environment.ts\";\nimport { FRAME_SOURCE } from \"../shared/frame-source.ts\";\nimport {\n type CanPlayTypeResult,\n type FrameMetadata,\n type HostMessage,\n MEDIA_EVENTS,\n type MediaState,\n type MessageEndpoint,\n} from \"../shared/protocol.ts\";\nimport { type Bridge, type ElementReceiver, bridgeFor } from \"./bridge.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\n\nexport interface CreateVideoElementOptions {\n transport?: MessageEndpoint;\n}\n\nexport type VideoFrameRequestCallback = (now: number, metadata: FrameMetadata) => void;\n\ntype EventHandler = ((this: WorkerVideoElement, event: Event) => unknown) | null;\n\ninterface MirroredProps {\n autoplay: boolean;\n controls: boolean;\n crossOrigin: string | null;\n defaultMuted: boolean;\n defaultPlaybackRate: number;\n disablePictureInPicture: boolean;\n disableRemotePlayback: boolean;\n height: number;\n loop: boolean;\n playsInline: boolean;\n poster: string;\n preload: \"\" | \"none\" | \"metadata\" | \"auto\";\n preservesPitch: boolean;\n width: number;\n}\n\nconst EMPTY_STATE: MediaState = {\n currentSrc: \"\",\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n muted: false,\n networkState: 0,\n paused: true,\n playbackRate: 1,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n volume: 1,\n buffered: [],\n played: [],\n seekable: [],\n quality: null,\n};\n\nconst LOAD_RESET: Partial<MediaState> = {\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n paused: true,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n buffered: [],\n played: [],\n seekable: [],\n};\n\nconst ATTRIBUTES: Record<string, { prop: string; type: \"bool\" | \"string\" | \"number\" | \"nullable\" }> = {\n autoplay: { prop: \"autoplay\", type: \"bool\" },\n controls: { prop: \"controls\", type: \"bool\" },\n crossorigin: { prop: \"crossOrigin\", type: \"nullable\" },\n disablepictureinpicture: { prop: \"disablePictureInPicture\", type: \"bool\" },\n disableremoteplayback: { prop: \"disableRemotePlayback\", type: \"bool\" },\n height: { prop: \"height\", type: \"number\" },\n loop: { prop: \"loop\", type: \"bool\" },\n muted: { prop: \"defaultMuted\", type: \"bool\" },\n playsinline: { prop: \"playsInline\", type: \"bool\" },\n poster: { prop: \"poster\", type: \"string\" },\n preload: { prop: \"preload\", type: \"string\" },\n src: { prop: \"src\", type: \"string\" },\n width: { prop: \"width\", type: \"number\" },\n};\n\nclass Internals implements ElementReceiver {\n readonly element: WorkerVideoElement;\n readonly bridge: Bridge;\n readonly id: number;\n state: MediaState = { ...EMPTY_STATE };\n props: MirroredProps = {\n autoplay: false,\n controls: false,\n crossOrigin: null,\n defaultMuted: false,\n defaultPlaybackRate: 1,\n disablePictureInPicture: false,\n disableRemotePlayback: false,\n height: 0,\n loop: false,\n playsInline: false,\n poster: \"\",\n preload: \"metadata\",\n preservesPitch: true,\n width: 0,\n };\n src = \"\";\n srcObject: unknown = null;\n hasSrcAttribute = false;\n readonly frame: { current: VideoFrame | null } = { current: null };\n readonly localWrites = new Map<string, number>();\n readonly frameCallbacks = new Map<number, VideoFrameRequestCallback>();\n nextFrameCallbackId = 1;\n readonly handlers = new Map<string, { handler: EventHandler; listener: (event: Event) => void }>();\n loadSeq = 0;\n disposed = false;\n\n constructor(element: WorkerVideoElement, bridge: Bridge) {\n this.element = element;\n this.bridge = bridge;\n this.id = bridge.nextId();\n const frame = this.frame;\n bridge.register(this.id, element, this, () => {\n frame.current?.close();\n frame.current = null;\n });\n bridge.post({ kind: \"create\", id: this.id, props: {} });\n }\n\n write(prop: string, value: unknown, local: Partial<MediaState> = {}, transfer?: Transferable[]): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"set\", id: this.id, prop, value }, transfer);\n this.applyLocal(seq, local);\n return seq;\n }\n\n invoke(\n method: \"pause\" | \"load\" | \"fastSeek\" | \"removeAttribute\",\n args: unknown[],\n local: Partial<MediaState> = {},\n ): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"call\", id: this.id, method, args });\n this.applyLocal(seq, local);\n return seq;\n }\n\n markLoad(seq: number): void {\n if (seq) this.loadSeq = seq;\n }\n\n applyLocal(seq: number, local: Partial<MediaState>): void {\n for (const [key, value] of Object.entries(local)) {\n (this.state as unknown as Record<string, unknown>)[key] = value;\n this.localWrites.set(key, seq);\n }\n if (\"readyState\" in local && (local.readyState ?? 0) < 2) this.setFrame(null);\n this.updatePin();\n }\n\n updatePin(): void {\n const { paused, seeking, networkState } = this.state;\n this.bridge.pin(this.element, !paused || seeking || networkState === 2);\n }\n\n applyState(ack: number, state: MediaState): void {\n const target = this.state as unknown as Record<string, unknown>;\n for (const [key, value] of Object.entries(state)) {\n const pending = this.localWrites.get(key);\n if (pending !== undefined) {\n if (pending > ack) continue;\n this.localWrites.delete(key);\n }\n target[key] = value;\n }\n this.updatePin();\n }\n\n setFrame(frame: VideoFrame | null): void {\n if (this.frame.current === frame) return;\n this.frame.current?.close();\n this.frame.current = frame;\n }\n\n receive(message: Extract<HostMessage, { id: number }>): void {\n if (this.disposed || (message.kind !== \"state\" && message.ack < this.loadSeq)) {\n if (\"frame\" in message) message.frame?.close();\n if (this.disposed) return;\n }\n this.applyState(message.ack, message.state);\n if (message.kind !== \"state\" && message.ack < this.loadSeq) return;\n switch (message.kind) {\n case \"state\":\n return;\n case \"frame\":\n this.setFrame(message.frame);\n this.runFrameCallbacks(message.metadata);\n return;\n case \"event\": {\n if (message.frame) this.setFrame(message.frame);\n else if (message.type === \"emptied\") this.setFrame(null);\n this.element.dispatchEvent(new Event(message.type));\n if (message.frame && message.metadata) this.runFrameCallbacks(message.metadata);\n }\n }\n }\n\n runFrameCallbacks(metadata: FrameMetadata): void {\n if (this.frameCallbacks.size === 0) return;\n const callbacks = [...this.frameCallbacks.values()];\n this.frameCallbacks.clear();\n const offset = this.bridge.timeOffset;\n const local: FrameMetadata = {\n ...metadata,\n presentationTime: metadata.presentationTime + offset,\n expectedDisplayTime: metadata.expectedDisplayTime + offset,\n };\n const now = performance.now();\n for (const callback of callbacks) {\n try {\n callback.call(this.element, now, local);\n } catch (error) {\n reportError(error);\n }\n }\n }\n\n resolveUrl(value: string): string {\n if (value === \"\") return value;\n const base = (globalThis as { location?: { href: string } }).location?.href;\n try {\n return new URL(value, base).href;\n } catch {\n return value;\n }\n }\n}\n\nfunction reportError(error: unknown): void {\n const report = (globalThis as { reportError?: (error: unknown) => void }).reportError;\n if (report) report(error);\n else\n setTimeout(() => {\n throw error;\n });\n}\n\nconst internals = new WeakMap<WorkerVideoElement, Internals>();\n\nfunction $(element: WorkerVideoElement): Internals {\n const value = internals.get(element);\n if (!value) throw new TypeError(\"Illegal invocation\");\n return value;\n}\n\nexport class WorkerVideoElement extends EventTarget {\n static readonly NETWORK_EMPTY = 0 as const;\n static readonly NETWORK_IDLE = 1 as const;\n static readonly NETWORK_LOADING = 2 as const;\n static readonly NETWORK_NO_SOURCE = 3 as const;\n static readonly HAVE_NOTHING = 0 as const;\n static readonly HAVE_METADATA = 1 as const;\n static readonly HAVE_CURRENT_DATA = 2 as const;\n static readonly HAVE_FUTURE_DATA = 3 as const;\n static readonly HAVE_ENOUGH_DATA = 4 as const;\n readonly NETWORK_EMPTY = 0 as const;\n readonly NETWORK_IDLE = 1 as const;\n readonly NETWORK_LOADING = 2 as const;\n readonly NETWORK_NO_SOURCE = 3 as const;\n readonly HAVE_NOTHING = 0 as const;\n readonly HAVE_METADATA = 1 as const;\n readonly HAVE_CURRENT_DATA = 2 as const;\n readonly HAVE_FUTURE_DATA = 3 as const;\n readonly HAVE_ENOUGH_DATA = 4 as const;\n\n readonly tagName = \"VIDEO\" as const;\n readonly nodeName = \"VIDEO\" as const;\n readonly localName = \"video\" as const;\n\n constructor(options: CreateVideoElementOptions = {}) {\n assertWorker(\"createVideoElement()\");\n super();\n const bridge = bridgeFor(options.transport);\n bridge.watchForHost();\n internals.set(this, new Internals(this, bridge));\n }\n\n get currentFrame(): VideoFrame | null {\n const frame = $(this).frame.current;\n return frame && frame.format !== null ? frame : null;\n }\n\n get disposed(): boolean {\n return $(this).disposed;\n }\n\n dispose(): void {\n const core = $(this);\n if (core.disposed) return;\n core.bridge.post({ kind: \"dispose\", id: core.id });\n core.disposed = true;\n core.setFrame(null);\n core.frameCallbacks.clear();\n core.bridge.unregister(core.id, core, this);\n core.state = { ...EMPTY_STATE };\n core.localWrites.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n get src(): string {\n return $(this).src;\n }\n set src(value: string) {\n const core = $(this);\n core.src = core.resolveUrl(String(value));\n core.hasSrcAttribute = true;\n core.markLoad(core.write(\"src\", core.src, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 }));\n }\n\n get srcObject(): unknown {\n return $(this).srcObject;\n }\n set srcObject(value: unknown) {\n const core = $(this);\n core.srcObject = value ?? null;\n const transfer = value ? [value as Transferable] : [];\n core.markLoad(core.write(\"srcObject\", value ?? null, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 }, transfer));\n }\n\n get currentSrc(): string {\n return $(this).state.currentSrc;\n }\n\n get duration(): number {\n return $(this).state.duration;\n }\n get paused(): boolean {\n return $(this).state.paused;\n }\n get ended(): boolean {\n return $(this).state.ended;\n }\n get seeking(): boolean {\n return $(this).state.seeking;\n }\n get readyState(): number {\n return $(this).state.readyState;\n }\n get networkState(): number {\n return $(this).state.networkState;\n }\n get videoWidth(): number {\n return $(this).state.videoWidth;\n }\n get videoHeight(): number {\n return $(this).state.videoHeight;\n }\n get error(): MediaError | null {\n const error = $(this).state.error;\n return error ? new WorkerMediaError(error) : null;\n }\n get buffered(): TimeRanges {\n return new WorkerTimeRanges($(this).state.buffered);\n }\n get played(): TimeRanges {\n return new WorkerTimeRanges($(this).state.played);\n }\n get seekable(): TimeRanges {\n return new WorkerTimeRanges($(this).state.seekable);\n }\n\n get currentTime(): number {\n return $(this).state.currentTime;\n }\n set currentTime(value: number) {\n const time = Number(value);\n if (!Number.isFinite(time)) {\n throw new TypeError(\"Failed to set the 'currentTime' property: The provided double value is non-finite.\");\n }\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.write(\"currentTime\", time, local);\n }\n\n fastSeek(time: number): void {\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.invoke(\"fastSeek\", [time], local);\n }\n\n get volume(): number {\n return $(this).state.volume;\n }\n set volume(value: number) {\n const volume = Number(value);\n if (!(volume >= 0 && volume <= 1)) {\n throw new DOMException(\n `Failed to set the 'volume' property: The volume provided (${value}) is outside the range [0, 1].`,\n \"IndexSizeError\",\n );\n }\n $(this).write(\"volume\", volume, { volume });\n }\n\n get muted(): boolean {\n return $(this).state.muted;\n }\n set muted(value: boolean) {\n $(this).write(\"muted\", Boolean(value), { muted: Boolean(value) });\n }\n\n get playbackRate(): number {\n return $(this).state.playbackRate;\n }\n set playbackRate(value: number) {\n $(this).write(\"playbackRate\", Number(value), { playbackRate: Number(value) });\n }\n\n get autoplay(): boolean {\n return $(this).props.autoplay;\n }\n set autoplay(value: boolean) {\n this.#mirror(\"autoplay\", Boolean(value));\n }\n get controls(): boolean {\n return $(this).props.controls;\n }\n set controls(value: boolean) {\n this.#mirror(\"controls\", Boolean(value));\n }\n get crossOrigin(): string | null {\n return $(this).props.crossOrigin;\n }\n set crossOrigin(value: string | null) {\n this.#mirror(\"crossOrigin\", value === null ? null : String(value));\n }\n get defaultMuted(): boolean {\n return $(this).props.defaultMuted;\n }\n set defaultMuted(value: boolean) {\n this.#mirror(\"defaultMuted\", Boolean(value));\n }\n get defaultPlaybackRate(): number {\n return $(this).props.defaultPlaybackRate;\n }\n set defaultPlaybackRate(value: number) {\n this.#mirror(\"defaultPlaybackRate\", Number(value));\n }\n get disablePictureInPicture(): boolean {\n return $(this).props.disablePictureInPicture;\n }\n set disablePictureInPicture(value: boolean) {\n this.#mirror(\"disablePictureInPicture\", Boolean(value));\n }\n get disableRemotePlayback(): boolean {\n return $(this).props.disableRemotePlayback;\n }\n set disableRemotePlayback(value: boolean) {\n this.#mirror(\"disableRemotePlayback\", Boolean(value));\n }\n get height(): number {\n return $(this).props.height;\n }\n set height(value: number) {\n this.#mirror(\"height\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get width(): number {\n return $(this).props.width;\n }\n set width(value: number) {\n this.#mirror(\"width\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get loop(): boolean {\n return $(this).props.loop;\n }\n set loop(value: boolean) {\n this.#mirror(\"loop\", Boolean(value));\n }\n get playsInline(): boolean {\n return $(this).props.playsInline;\n }\n set playsInline(value: boolean) {\n this.#mirror(\"playsInline\", Boolean(value));\n }\n get poster(): string {\n return $(this).props.poster;\n }\n set poster(value: string) {\n this.#mirror(\"poster\", $(this).resolveUrl(String(value)));\n }\n get preload(): MirroredProps[\"preload\"] {\n return $(this).props.preload;\n }\n set preload(value: MirroredProps[\"preload\"]) {\n const normalized = String(value).toLowerCase();\n this.#mirror(\"preload\", ([\"none\", \"metadata\", \"auto\"].includes(normalized) ? normalized : \"auto\") as never);\n }\n get preservesPitch(): boolean {\n return $(this).props.preservesPitch;\n }\n set preservesPitch(value: boolean) {\n this.#mirror(\"preservesPitch\", Boolean(value));\n }\n\n #mirror<K extends keyof MirroredProps>(prop: K, value: MirroredProps[K]): void {\n const core = $(this);\n core.props[prop] = value;\n core.write(prop, value);\n }\n\n getAttribute(name: string): string | null {\n const core = $(this);\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return null;\n if (attribute.prop === \"src\") return core.hasSrcAttribute ? core.src : null;\n const value = (this as unknown as Record<string, unknown>)[attribute.prop];\n switch (attribute.type) {\n case \"bool\":\n return value ? \"\" : null;\n case \"nullable\":\n return value === null ? null : String(value);\n default:\n return String(value);\n }\n }\n\n hasAttribute(name: string): boolean {\n return this.getAttribute(name) !== null;\n }\n\n setAttribute(name: string, value: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = true;\n break;\n case \"number\":\n target[attribute.prop] = Number.parseInt(value, 10) || 0;\n break;\n default:\n target[attribute.prop] = String(value);\n }\n }\n\n removeAttribute(name: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const core = $(this);\n if (attribute.prop === \"src\") {\n core.src = \"\";\n core.hasSrcAttribute = false;\n core.invoke(\"removeAttribute\", [\"src\"]);\n return;\n }\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = false;\n break;\n case \"nullable\":\n target[attribute.prop] = null;\n break;\n case \"number\":\n target[attribute.prop] = 0;\n break;\n default:\n target[attribute.prop] = attribute.prop === \"preload\" ? \"metadata\" : \"\";\n }\n }\n\n play(): Promise<void> {\n const core = $(this);\n if (core.disposed) {\n return Promise.reject(new DOMException(\"The element has been disposed.\", \"InvalidStateError\"));\n }\n const [seq, promise] = core.bridge.call({ kind: \"call\", id: core.id, method: \"play\", args: [] });\n core.applyLocal(seq, { paused: false });\n return promise as Promise<void>;\n }\n\n pause(): void {\n $(this).invoke(\"pause\", [], { paused: true });\n }\n\n load(): void {\n const core = $(this);\n core.markLoad(core.invoke(\"load\", [], { ...LOAD_RESET, networkState: 0 }));\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n return $(this).bridge.canPlayType(String(type));\n }\n\n getVideoPlaybackQuality(): VideoPlaybackQuality {\n const quality = $(this).state.quality;\n return (quality ?? {\n creationTime: performance.now(),\n droppedVideoFrames: 0,\n totalVideoFrames: 0,\n }) as VideoPlaybackQuality;\n }\n\n requestVideoFrameCallback(callback: VideoFrameRequestCallback): number {\n const core = $(this);\n const handle = core.nextFrameCallbackId++;\n core.frameCallbacks.set(handle, callback);\n return handle;\n }\n\n cancelVideoFrameCallback(handle: number): void {\n $(this).frameCallbacks.delete(handle);\n }\n\n requestPictureInPicture(): Promise<never> {\n return Promise.reject(new DOMException(\"Picture-in-Picture is not available in workers.\", \"NotSupportedError\"));\n }\n}\n\nexport interface WorkerVideoElement {\n [FRAME_SOURCE](): VideoFrame | null;\n onabort: EventHandler;\n oncanplay: EventHandler;\n oncanplaythrough: EventHandler;\n ondurationchange: EventHandler;\n onemptied: EventHandler;\n onencrypted: EventHandler;\n onended: EventHandler;\n onerror: EventHandler;\n onloadeddata: EventHandler;\n onloadedmetadata: EventHandler;\n onloadstart: EventHandler;\n onpause: EventHandler;\n onplay: EventHandler;\n onplaying: EventHandler;\n onprogress: EventHandler;\n onratechange: EventHandler;\n onresize: EventHandler;\n onseeked: EventHandler;\n onseeking: EventHandler;\n onstalled: EventHandler;\n onsuspend: EventHandler;\n ontimeupdate: EventHandler;\n onvolumechange: EventHandler;\n onwaiting: EventHandler;\n onwaitingforkey: EventHandler;\n}\n\nObject.defineProperty(WorkerVideoElement.prototype, FRAME_SOURCE, {\n configurable: true,\n value(this: WorkerVideoElement): VideoFrame | null {\n return this.currentFrame;\n },\n});\n\nfor (const type of MEDIA_EVENTS) {\n Object.defineProperty(WorkerVideoElement.prototype, `on${type}`, {\n configurable: true,\n enumerable: true,\n get(this: WorkerVideoElement): EventHandler {\n return $(this).handlers.get(type)?.handler ?? null;\n },\n set(this: WorkerVideoElement, handler: EventHandler) {\n const core = $(this);\n const existing = core.handlers.get(type);\n if (typeof handler !== \"function\") {\n if (existing) this.removeEventListener(type, existing.listener);\n core.handlers.delete(type);\n return;\n }\n if (existing) {\n existing.handler = handler;\n return;\n }\n const entry = {\n handler,\n listener: (event: Event) => {\n const result = entry.handler?.call(this, event);\n if (result === false) event.preventDefault();\n },\n };\n core.handlers.set(type, entry);\n this.addEventListener(type, entry.listener);\n },\n });\n}\n\nexport function createVideoElement(options?: CreateVideoElementOptions): WorkerVideoElement {\n return new WorkerVideoElement(options);\n}\n","import type { CreateVideoElementOptions } from \"./video-element.ts\";\nimport { WorkerVideoElement } from \"./video-element.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\nimport { assertWorker } from \"../shared/environment.ts\";\n\nconst PATCHED: unique symbol = Symbol.for(\"html-video-element-webworker-polyfill.patched\") as never;\n\ninterface DocumentLike {\n createElement(tagName: string, options?: unknown): unknown;\n [PATCHED]?: true;\n}\n\nexport function polyfillDocument(options?: CreateVideoElementOptions): void {\n assertWorker(\"polyfillDocument()\");\n const scope = globalThis as Record<string, unknown>;\n scope.HTMLVideoElement ??= WorkerVideoElement;\n scope.HTMLMediaElement ??= WorkerVideoElement;\n scope.MediaError ??= WorkerMediaError;\n scope.TimeRanges ??= WorkerTimeRanges;\n\n const existing = scope.document as DocumentLike | undefined;\n if (existing && typeof existing.createElement === \"function\") {\n if (existing[PATCHED]) return;\n const original = existing.createElement.bind(existing);\n existing.createElement = (tagName: string, elementOptions?: unknown) =>\n isVideo(tagName) ? new WorkerVideoElement(options) : original(tagName, elementOptions);\n existing[PATCHED] = true;\n return;\n }\n\n const document: DocumentLike = {\n createElement(tagName: string): unknown {\n if (isVideo(tagName)) return new WorkerVideoElement(options);\n throw new DOMException(\n `document.createElement(\"${tagName}\") is not supported in a worker; only \"video\" is polyfilled.`,\n \"NotSupportedError\",\n );\n },\n [PATCHED]: true,\n };\n scope.document = document;\n}\n\nfunction isVideo(tagName: string): boolean {\n return String(tagName).toLowerCase() === \"video\";\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"host-D-rmvsLs.js","names":[],"sources":["../src/host/video-host.ts"],"sourcesContent":["import {\n CHANNEL,\n COMMON_MIME_TYPES,\n type CanPlayTypeResult,\n type ClientMessage,\n type FrameMetadata,\n type HostMessage,\n MEDIA_EVENTS,\n MIRRORED_PROPERTIES,\n type MediaState,\n type MessageEndpoint,\n type Ranges,\n type SerializedError,\n isProtocolMessage,\n} from \"../shared/protocol.ts\";\nimport { assertMainThread, isMainThread, isMessageEndpoint } from \"../shared/environment.ts\";\n\nexport interface VideoHostOptions {\n container?: HTMLElement | null;\n onVideoCreated?: (video: HTMLVideoElement, id: number) => void;\n onVideoDisposed?: (video: HTMLVideoElement, id: number) => void;\n}\n\nexport interface VideoHost {\n readonly videos: ReadonlyMap<number, HTMLVideoElement>;\n dispose(): void;\n}\n\ntype Distribute<T> = T extends unknown ? Omit<T, typeof CHANNEL> : never;\ntype OutgoingHostMessage = Distribute<HostMessage>;\n\nconst FRAME_EVENTS = new Set([\"loadeddata\", \"seeked\"]);\n\nconst SILENT_STATE_POLL_INTERVAL = 16;\nconst SILENT_STATE_POLLS = 32;\n\ninterface Entry {\n video: HTMLVideoElement;\n frameCallback: number | null;\n frameInFlight: boolean;\n pendingFrame: { frame: VideoFrame; metadata: FrameMetadata } | null;\n sendPendingFrame: () => void;\n lastFrameTimestamp: number | null;\n frameDuration: number | null;\n detach: () => void;\n}\n\nconst FRAME_WAIT_TIMEOUT = 500;\nconst TIMESTAMP_EPSILON = 1000;\n\nconst hosted = new WeakSet<object>();\n\nexport function createVideoHost(endpoint: MessageEndpoint, options: VideoHostOptions = {}): VideoHost {\n assertMainThread(\"createVideoHost()\");\n if (!isMessageEndpoint(endpoint) || (isMainThread() && endpoint === (globalThis as object))) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: createVideoHost() expects the Worker (or a MessagePort connected to it) that uses the polyfill.\",\n );\n }\n if (hosted.has(endpoint)) {\n throw new DOMException(\n \"html-video-element-webworker-polyfill: createVideoHost() was already called for this endpoint; call dispose() on the existing host first.\",\n \"InvalidStateError\",\n );\n }\n hosted.add(endpoint);\n const entries = new Map<number, Entry>();\n const videos = new Map<number, HTMLVideoElement>();\n let ack = 0;\n let disposed = false;\n\n const sentNetworkState = new Map<number, number>();\n const post = (message: OutgoingHostMessage, transfer: Transferable[] = []): void => {\n if (disposed) {\n for (const item of transfer) (item as Partial<VideoFrame>).close?.();\n return;\n }\n if (\"state\" in message) sentNetworkState.set(message.id, message.state.networkState);\n endpoint.postMessage({ ...message, [CHANNEL]: 1 }, transfer);\n };\n\n const watching = new Map<number, { polls: number }>();\n const sendState = (id: number, video: HTMLVideoElement): void => {\n post({ kind: \"state\", id, ack, state: snapshot(video) });\n const existing = watching.get(id);\n if (existing) {\n existing.polls = 0;\n return;\n }\n const watch = { polls: 0 };\n watching.set(id, watch);\n const poll = (): void => {\n if (entries.get(id)?.video !== video || ++watch.polls > SILENT_STATE_POLLS) {\n watching.delete(id);\n return;\n }\n if (video.networkState !== sentNetworkState.get(id)) {\n post({ kind: \"state\", id, ack, state: snapshot(video) });\n }\n setTimeout(poll, SILENT_STATE_POLL_INTERVAL);\n };\n setTimeout(poll, SILENT_STATE_POLL_INTERVAL);\n };\n\n const welcome = (): void => {\n const probe = document.createElement(\"video\");\n const canPlayType: Record<string, CanPlayTypeResult> = {};\n for (const type of COMMON_MIME_TYPES) canPlayType[type] = probe.canPlayType(type);\n post({ kind: \"welcome\", timeOrigin: performance.timeOrigin, canPlayType });\n };\n\n const captureFrame = (entry: Entry): VideoFrame | null => {\n const { video } = entry;\n if (video.readyState < 2 || typeof VideoFrame !== \"function\") return null;\n try {\n return new VideoFrame(video);\n } catch {\n return null;\n }\n };\n\n const create = (id: number): void => {\n const video = document.createElement(\"video\");\n video.playsInline = true;\n const entry: Entry = {\n video,\n frameCallback: null,\n lastFrameTimestamp: null,\n frameInFlight: false,\n pendingFrame: null,\n sendPendingFrame: () => {},\n frameDuration: null,\n detach: () => {},\n };\n\n const noteFrame = (frame: VideoFrame): void => {\n entry.lastFrameTimestamp = frame.timestamp;\n };\n\n let previousPresented: { frames: number; timestamp: number } | null = null;\n const learnFrameDuration = (frame: VideoFrame, presentedFrames: number): void => {\n const previous = previousPresented;\n previousPresented = { frames: presentedFrames, timestamp: frame.timestamp };\n if (!previous || presentedFrames !== previous.frames + 1 || frame.timestamp <= previous.timestamp) return;\n const delta = frame.timestamp - previous.timestamp;\n entry.frameDuration = entry.frameDuration === null ? delta : Math.min(entry.frameDuration, delta);\n };\n\n const shows = (frame: VideoFrame, target: number): boolean => {\n if (!video.paused && frame.timestamp >= target - TIMESTAMP_EPSILON) return true;\n if (frame.timestamp > target + TIMESTAMP_EPSILON) return false;\n const duration = frame.duration || entry.frameDuration;\n if (duration) return target < frame.timestamp + duration + TIMESTAMP_EPSILON;\n return frame.timestamp !== entry.lastFrameTimestamp;\n };\n\n const dropPendingFrame = (): void => {\n entry.pendingFrame?.frame.close();\n entry.pendingFrame = null;\n };\n\n const sendFrame = (frame: VideoFrame, metadata: FrameMetadata): void => {\n entry.frameInFlight = true;\n post({ kind: \"frame\", id, ack, state: snapshot(video), frame, metadata }, [frame]);\n };\n\n entry.sendPendingFrame = () => {\n entry.frameInFlight = false;\n const pending = entry.pendingFrame;\n if (!pending) return;\n entry.pendingFrame = null;\n sendFrame(pending.frame, pending.metadata);\n };\n\n const sendEvent = (type: string, frame: VideoFrame | null): void => {\n if (frame || type === \"emptied\") dropPendingFrame();\n if (!frame) {\n if (type === \"emptied\") entry.lastFrameTimestamp = null;\n post({ kind: \"event\", id, ack, type, state: snapshot(video) });\n return;\n }\n noteFrame(frame);\n post({ kind: \"event\", id, ack, type, state: snapshot(video), frame, metadata: syntheticMetadata(video, frame) }, [\n frame,\n ]);\n };\n\n let held: { type: string; target: number; queue: string[]; timer: ReturnType<typeof setTimeout> } | null = null;\n\n const releaseHeld = (frame: VideoFrame | null): void => {\n if (!held) return;\n const { type, queue, timer } = held;\n held = null;\n clearTimeout(timer);\n sendEvent(type, frame);\n for (const queued of queue) dispatch(queued);\n };\n\n const dispatch = (type: string): void => {\n if (held) {\n held.queue.push(type);\n return;\n }\n if (!FRAME_EVENTS.has(type)) {\n sendEvent(type, null);\n return;\n }\n const frame = captureFrame(entry);\n const target = video.currentTime * 1e6;\n if (!frame || shows(frame, target)) {\n sendEvent(type, frame);\n return;\n }\n frame.close();\n held = { type, target, queue: [], timer: setTimeout(() => releaseHeld(captureFrame(entry)), FRAME_WAIT_TIMEOUT) };\n };\n\n const onEvent = (event: Event): void => dispatch(event.type);\n for (const type of MEDIA_EVENTS) video.addEventListener(type, onEvent);\n\n const onFrame = (_now: number, metadata: VideoFrameCallbackMetadata): void => {\n entry.frameCallback = video.requestVideoFrameCallback(onFrame);\n const frame = captureFrame(entry);\n if (!frame) return;\n learnFrameDuration(frame, metadata.presentedFrames);\n if (held) {\n if (shows(frame, held.target)) releaseHeld(frame);\n else frame.close();\n return;\n }\n if (frame.timestamp === entry.lastFrameTimestamp) {\n frame.close();\n return;\n }\n noteFrame(frame);\n if (entry.frameInFlight) {\n dropPendingFrame();\n entry.pendingFrame = { frame, metadata: toMetadata(metadata) };\n } else {\n sendFrame(frame, toMetadata(metadata));\n }\n };\n if (typeof video.requestVideoFrameCallback === \"function\") {\n entry.frameCallback = video.requestVideoFrameCallback(onFrame);\n }\n\n entry.detach = () => {\n dropPendingFrame();\n for (const type of MEDIA_EVENTS) video.removeEventListener(type, onEvent);\n if (entry.frameCallback !== null) video.cancelVideoFrameCallback(entry.frameCallback);\n if (held) clearTimeout(held.timer);\n held = null;\n };\n\n entries.set(id, entry);\n videos.set(id, video);\n options.container?.append(video);\n options.onVideoCreated?.(video, id);\n };\n\n const release = (id: number): void => {\n const entry = entries.get(id);\n if (!entry) return;\n entries.delete(id);\n videos.delete(id);\n sentNetworkState.delete(id);\n const { video } = entry;\n options.onVideoDisposed?.(video, id);\n entry.detach();\n video.pause();\n video.removeAttribute(\"src\");\n video.srcObject = null;\n video.load();\n video.remove();\n };\n\n const handle = (message: ClientMessage): void => {\n if (\"seq\" in message) ack = Math.max(ack, message.seq);\n switch (message.kind) {\n case \"hello\":\n welcome();\n return;\n case \"frameAck\":\n entries.get(message.id)?.sendPendingFrame();\n return;\n case \"canPlayType\":\n post({ kind: \"result\", callId: message.callId, value: probeCanPlayType(message.type) });\n return;\n case \"create\":\n create(message.id);\n break;\n case \"dispose\":\n release(message.id);\n return;\n case \"set\": {\n const video = entries.get(message.id)?.video;\n if (!video) return;\n applyProperty(video, message.prop, message.value);\n break;\n }\n case \"call\": {\n const video = entries.get(message.id)?.video;\n if (!video) {\n if (message.callId !== undefined) {\n post({\n kind: \"result\",\n callId: message.callId,\n error: { name: \"InvalidStateError\", message: \"The element has been disposed.\" },\n });\n }\n return;\n }\n invoke(video, message.method, message.args).then(\n (value) => message.callId !== undefined && post({ kind: \"result\", callId: message.callId, value }),\n (error: unknown) =>\n message.callId !== undefined &&\n post({ kind: \"result\", callId: message.callId, error: serializeError(error) }),\n );\n break;\n }\n }\n const video = entries.get(message.id)?.video;\n if (video) sendState(message.id, video);\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (isProtocolMessage(event.data)) handle(event.data as ClientMessage);\n };\n endpoint.addEventListener(\"message\", onMessage);\n endpoint.start?.();\n welcome();\n\n return {\n videos,\n dispose() {\n if (disposed) return;\n for (const id of entries.keys()) release(id);\n endpoint.removeEventListener(\"message\", onMessage);\n hosted.delete(endpoint);\n disposed = true;\n },\n };\n}\n\nfunction applyProperty(video: HTMLVideoElement, prop: string, value: unknown): void {\n try {\n if (prop === \"src\") video.src = value as string;\n else if (prop === \"srcObject\") video.srcObject = value as MediaProvider | null;\n else if (prop === \"currentTime\") video.currentTime = value as number;\n else if (MIRRORED_PROPERTIES.includes(prop)) (video as unknown as Record<string, unknown>)[prop] = value;\n } catch (error) {\n console.warn(`[html-video-element-webworker-polyfill] failed to set \"${prop}\":`, error);\n }\n}\n\nasync function invoke(video: HTMLVideoElement, method: string, args: unknown[]): Promise<unknown> {\n switch (method) {\n case \"play\":\n await video.play();\n return undefined;\n case \"pause\":\n return video.pause();\n case \"load\":\n return video.load();\n case \"fastSeek\":\n if (typeof video.fastSeek === \"function\") video.fastSeek(args[0] as number);\n else video.currentTime = args[0] as number;\n return undefined;\n case \"removeAttribute\":\n return video.removeAttribute(args[0] as string);\n default:\n throw new DOMException(`Unknown method ${method}`, \"NotSupportedError\");\n }\n}\n\nlet canPlayTypeProbe: HTMLVideoElement | undefined;\nfunction probeCanPlayType(type: string): CanPlayTypeResult {\n canPlayTypeProbe ??= document.createElement(\"video\");\n return canPlayTypeProbe.canPlayType(type);\n}\n\nfunction ranges(timeRanges: TimeRanges): Ranges {\n const result: Ranges = [];\n for (let i = 0; i < timeRanges.length; i++) result.push([timeRanges.start(i), timeRanges.end(i)]);\n return result;\n}\n\nfunction snapshot(video: HTMLVideoElement): MediaState {\n const quality = typeof video.getVideoPlaybackQuality === \"function\" ? video.getVideoPlaybackQuality() : null;\n return {\n currentSrc: video.currentSrc,\n currentTime: video.currentTime,\n duration: video.duration,\n ended: video.ended,\n error: video.error ? { code: video.error.code, message: video.error.message } : null,\n muted: video.muted,\n networkState: video.networkState,\n paused: video.paused,\n playbackRate: video.playbackRate,\n readyState: video.readyState,\n seeking: video.seeking,\n videoHeight: video.videoHeight,\n videoWidth: video.videoWidth,\n volume: video.volume,\n buffered: ranges(video.buffered),\n played: ranges(video.played),\n seekable: ranges(video.seekable),\n quality: quality\n ? {\n creationTime: quality.creationTime,\n droppedVideoFrames: quality.droppedVideoFrames,\n totalVideoFrames: quality.totalVideoFrames,\n }\n : null,\n };\n}\n\nfunction toMetadata(metadata: VideoFrameCallbackMetadata): FrameMetadata {\n const result: FrameMetadata = {\n presentationTime: metadata.presentationTime,\n expectedDisplayTime: metadata.expectedDisplayTime,\n width: metadata.width,\n height: metadata.height,\n mediaTime: metadata.mediaTime,\n presentedFrames: metadata.presentedFrames,\n };\n if (metadata.processingDuration !== undefined) result.processingDuration = metadata.processingDuration;\n if (metadata.captureTime !== undefined) result.captureTime = metadata.captureTime;\n if (metadata.receiveTime !== undefined) result.receiveTime = metadata.receiveTime;\n if (metadata.rtpTimestamp !== undefined) result.rtpTimestamp = metadata.rtpTimestamp;\n return result;\n}\n\nfunction syntheticMetadata(video: HTMLVideoElement, frame: VideoFrame): FrameMetadata {\n const now = performance.now();\n const quality = typeof video.getVideoPlaybackQuality === \"function\" ? video.getVideoPlaybackQuality() : null;\n return {\n presentationTime: now,\n expectedDisplayTime: now,\n width: frame.displayWidth,\n height: frame.displayHeight,\n mediaTime: frame.timestamp / 1e6,\n presentedFrames: quality?.totalVideoFrames ?? 0,\n };\n}\n\nfunction serializeError(error: unknown): SerializedError {\n if (error instanceof Error || error instanceof DOMException) return { name: error.name, message: error.message };\n return { name: \"Error\", message: String(error) };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-Be-N8xdd.js","names":[],"sources":["../src/shared/protocol.ts"],"sourcesContent":["export const CHANNEL = \"__htmlVideoElementWorkerPolyfill\" as const;\n\nexport const MEDIA_EVENTS: readonly string[] = [\n \"abort\",\n \"canplay\",\n \"canplaythrough\",\n \"durationchange\",\n \"emptied\",\n \"encrypted\",\n \"ended\",\n \"error\",\n \"loadeddata\",\n \"loadedmetadata\",\n \"loadstart\",\n \"pause\",\n \"play\",\n \"playing\",\n \"progress\",\n \"ratechange\",\n \"resize\",\n \"seeked\",\n \"seeking\",\n \"stalled\",\n \"suspend\",\n \"timeupdate\",\n \"volumechange\",\n \"waiting\",\n \"waitingforkey\",\n];\n\nexport const MIRRORED_PROPERTIES: readonly string[] = [\n \"autoplay\",\n \"controls\",\n \"crossOrigin\",\n \"defaultMuted\",\n \"defaultPlaybackRate\",\n \"disablePictureInPicture\",\n \"disableRemotePlayback\",\n \"height\",\n \"loop\",\n \"muted\",\n \"playbackRate\",\n \"playsInline\",\n \"poster\",\n \"preload\",\n \"preservesPitch\",\n \"volume\",\n \"width\",\n];\n\nexport type Ranges = Array<[start: number, end: number]>;\n\nexport interface SerializedMediaError {\n code: number;\n message: string;\n}\n\nexport interface SerializedPlaybackQuality {\n creationTime: number;\n droppedVideoFrames: number;\n totalVideoFrames: number;\n}\n\nexport interface MediaState {\n currentSrc: string;\n currentTime: number;\n duration: number;\n ended: boolean;\n error: SerializedMediaError | null;\n muted: boolean;\n networkState: number;\n paused: boolean;\n playbackRate: number;\n readyState: number;\n seeking: boolean;\n videoHeight: number;\n videoWidth: number;\n volume: number;\n buffered: Ranges;\n played: Ranges;\n seekable: Ranges;\n quality: SerializedPlaybackQuality | null;\n}\n\nexport interface FrameMetadata {\n presentationTime: number;\n expectedDisplayTime: number;\n width: number;\n height: number;\n mediaTime: number;\n presentedFrames: number;\n processingDuration?: number;\n captureTime?: number;\n receiveTime?: number;\n rtpTimestamp?: number;\n}\n\nexport interface SerializedError {\n name: string;\n message: string;\n}\n\nexport type ClientMessage =\n | { [CHANNEL]: 1; kind: \"create\"; id: number; seq: number; props: Record<string, unknown> }\n | { [CHANNEL]: 1; kind: \"set\"; id: number; seq: number; prop: string; value: unknown }\n | {\n [CHANNEL]: 1;\n kind: \"call\";\n id: number;\n seq: number;\n method: \"play\" | \"pause\" | \"load\" | \"fastSeek\" | \"removeAttribute\";\n args: unknown[];\n callId?: number;\n }\n | { [CHANNEL]: 1; kind: \"dispose\"; id: number; seq: number }\n | { [CHANNEL]: 1; kind: \"canPlayType\"; type: string; callId: number }\n | { [CHANNEL]: 1; kind: \"frameAck\"; id: number; seq: number }\n | { [CHANNEL]: 1; kind: \"hello\" };\n\nexport type HostMessage =\n | {\n [CHANNEL]: 1;\n kind: \"event\";\n id: number;\n ack: number;\n type: string;\n state: MediaState;\n frame?: VideoFrame;\n metadata?: FrameMetadata;\n }\n | {\n [CHANNEL]: 1;\n kind: \"frame\";\n id: number;\n ack: number;\n state: MediaState;\n frame: VideoFrame;\n metadata: FrameMetadata;\n }\n | { [CHANNEL]: 1; kind: \"state\"; id: number; ack: number; state: MediaState }\n | { [CHANNEL]: 1; kind: \"result\"; callId: number; value?: unknown; error?: SerializedError }\n | {\n [CHANNEL]: 1;\n kind: \"welcome\";\n timeOrigin: number;\n canPlayType: Record<string, CanPlayTypeResult>;\n };\n\nexport type CanPlayTypeResult = \"\" | \"maybe\" | \"probably\";\n\nexport interface MessageEndpoint {\n postMessage(message: unknown, transfer: Transferable[]): void;\n addEventListener(type: \"message\", listener: (event: MessageEvent) => void): void;\n removeEventListener(type: \"message\", listener: (event: MessageEvent) => void): void;\n start?: () => void;\n}\n\nexport function isProtocolMessage(data: unknown): boolean {\n return typeof data === \"object\" && data !== null && (data as Record<string, unknown>)[CHANNEL] === 1;\n}\n\nexport const COMMON_MIME_TYPES: readonly string[] = [\n \"video/mp4\",\n \"video/webm\",\n \"video/ogg\",\n \"video/quicktime\",\n \"video/x-matroska\",\n \"application/vnd.apple.mpegurl\",\n 'video/mp4; codecs=\"avc1.42E01E\"',\n 'video/mp4; codecs=\"avc1.4D401E\"',\n 'video/mp4; codecs=\"avc1.64001E\"',\n 'video/mp4; codecs=\"hvc1.1.6.L93.B0\"',\n 'video/mp4; codecs=\"av01.0.05M.08\"',\n 'video/mp4; codecs=\"vp09.00.10.08\"',\n 'video/webm; codecs=\"vp8\"',\n 'video/webm; codecs=\"vp9\"',\n 'video/webm; codecs=\"av01.0.05M.08\"',\n 'video/ogg; codecs=\"theora\"',\n \"audio/mpeg\",\n \"audio/mp4\",\n \"audio/ogg\",\n \"audio/webm\",\n \"audio/wav\",\n \"audio/flac\",\n];\n"],"mappings":";AAAA,MAAa,UAAU;AAEvB,MAAa,eAAkC;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,sBAAyC;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AA6GA,SAAgB,kBAAkB,MAAwB;CACxD,OAAO,OAAO,SAAS,YAAY,SAAS,QAAS,KAAA,wCAA8C;AACrG;AAEA,MAAa,oBAAuC;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|