@sarakusha/ebml 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +43 -0
  3. package/build/CancelError.cjs +14 -0
  4. package/build/CancelError.cjs.map +1 -0
  5. package/build/CancelError.d.cts +1 -0
  6. package/build/CancelError.d.mts +7 -0
  7. package/build/CancelError.d.mts.map +1 -0
  8. package/build/CancelError.mjs +10 -0
  9. package/build/CancelError.mjs.map +1 -0
  10. package/build/Deferred-7Cu0KIje.mjs +28 -0
  11. package/build/Deferred-7Cu0KIje.mjs.map +1 -0
  12. package/build/Deferred-CB69mtbF.cjs +33 -0
  13. package/build/Deferred-CB69mtbF.cjs.map +1 -0
  14. package/build/Element-8JyOKTYb.cjs +73 -0
  15. package/build/Element-8JyOKTYb.cjs.map +1 -0
  16. package/build/Element-CC4E6wMR.d.mts +134 -0
  17. package/build/Element-CC4E6wMR.d.mts.map +1 -0
  18. package/build/Element-ChEar-fo.mjs +20 -0
  19. package/build/Element-ChEar-fo.mjs.map +1 -0
  20. package/build/FadeTransform.cjs +90 -0
  21. package/build/FadeTransform.cjs.map +1 -0
  22. package/build/FadeTransform.d.cts +1 -0
  23. package/build/FadeTransform.d.mts +17 -0
  24. package/build/FadeTransform.d.mts.map +1 -0
  25. package/build/FadeTransform.mjs +86 -0
  26. package/build/FadeTransform.mjs.map +1 -0
  27. package/build/RangeFetcher.cjs +63 -0
  28. package/build/RangeFetcher.cjs.map +1 -0
  29. package/build/RangeFetcher.d.cts +1 -0
  30. package/build/RangeFetcher.d.mts +14 -0
  31. package/build/RangeFetcher.d.mts.map +1 -0
  32. package/build/RangeFetcher.mjs +59 -0
  33. package/build/RangeFetcher.mjs.map +1 -0
  34. package/build/ReducingValve.cjs +129 -0
  35. package/build/ReducingValve.cjs.map +1 -0
  36. package/build/ReducingValve.d.cts +1 -0
  37. package/build/ReducingValve.d.mts +17 -0
  38. package/build/ReducingValve.d.mts.map +1 -0
  39. package/build/ReducingValve.mjs +125 -0
  40. package/build/ReducingValve.mjs.map +1 -0
  41. package/build/VideoChunkGenerator.cjs +131 -0
  42. package/build/VideoChunkGenerator.cjs.map +1 -0
  43. package/build/VideoChunkGenerator.d.cts +1 -0
  44. package/build/VideoChunkGenerator.d.mts +13 -0
  45. package/build/VideoChunkGenerator.d.mts.map +1 -0
  46. package/build/VideoChunkGenerator.mjs +127 -0
  47. package/build/VideoChunkGenerator.mjs.map +1 -0
  48. package/build/VideoFrameGenerator.cjs +133 -0
  49. package/build/VideoFrameGenerator.cjs.map +1 -0
  50. package/build/VideoFrameGenerator.d.cts +1 -0
  51. package/build/VideoFrameGenerator.d.mts +10 -0
  52. package/build/VideoFrameGenerator.d.mts.map +1 -0
  53. package/build/VideoFrameGenerator.mjs +129 -0
  54. package/build/VideoFrameGenerator.mjs.map +1 -0
  55. package/build/index.cjs +6315 -0
  56. package/build/index.cjs.map +1 -0
  57. package/build/index.d.cts +1 -0
  58. package/build/index.d.mts +31 -0
  59. package/build/index.d.mts.map +1 -0
  60. package/build/index.mjs +6292 -0
  61. package/build/index.mjs.map +1 -0
  62. package/build/tools-CYLlbo9J.mjs +79 -0
  63. package/build/tools-CYLlbo9J.mjs.map +1 -0
  64. package/build/tools-DQrZvGBN.cjs +138 -0
  65. package/build/tools-DQrZvGBN.cjs.map +1 -0
  66. package/package.json +213 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FadeTransform.mjs","names":[],"sources":["../src/FadeTransform.ts"],"sourcesContent":["import Deferred from './Deferred';\n\nexport type FadeOptions = {\n disableIn?: boolean;\n disableOut?: boolean;\n duration?: number;\n};\n\nconst easeOutCubic = (t: number, b: number, c: number, d: number) =>\n // eslint-disable-next-line no-param-reassign\n c * ((t = t / d - 1) * t * t + 1) + b;\n\nexport default class FadeTransform extends TransformStream<VideoFrame, VideoFrame> {\n setDisableFadeOut: (value?: boolean) => void;\n\n constructor({ disableIn, disableOut, duration: fadeDuration = 200 }: FadeOptions = {}) {\n let deferred: Deferred | undefined;\n let last: VideoFrame | undefined;\n let ctx: OffscreenCanvasRenderingContext2D | null = null;\n let init: VideoFrameInit = {};\n let disableFadeOut = disableOut;\n const initialize = (chunk: VideoFrame): void => {\n if (!ctx) {\n const offscreen = new OffscreenCanvas(chunk.displayWidth, chunk.displayHeight);\n ctx = offscreen.getContext('2d');\n }\n if (!init) {\n const { displayWidth, displayHeight, visibleRect, duration, timestamp } = chunk;\n init = {\n displayWidth,\n displayHeight,\n visibleRect: visibleRect ?? undefined,\n duration: duration ?? undefined,\n timestamp: timestamp ?? undefined,\n };\n }\n };\n super({\n transform(chunk, controller) {\n if (!disableFadeOut) {\n last?.close();\n last = chunk.clone();\n }\n const timestamp = chunk.timestamp ? chunk.timestamp : 0;\n if (!disableIn && timestamp / 1000 < fadeDuration) {\n if (!ctx) initialize(chunk);\n if (ctx) {\n const brightness = easeOutCubic(timestamp / 1000, 0, 100, fadeDuration);\n ctx.filter = `brightness(${brightness}%)`;\n ctx.drawImage(chunk, 0, 0);\n chunk.close();\n init.timestamp = timestamp;\n const frame = new VideoFrame(ctx.canvas as unknown as ImageBitmap, init);\n controller.enqueue(frame);\n return;\n }\n }\n controller.enqueue(chunk);\n },\n flush: async (controller) => {\n if (last && last.timestamp && !disableFadeOut) {\n if (!ctx) initialize(last);\n if (ctx) {\n deferred = new Deferred();\n const context = ctx;\n const orig = last;\n const { timestamp: start } = last;\n const duration = last.duration ? last.duration / 1000 : 33;\n const fadeOut = (time: number) => {\n const brightness = easeOutCubic(\n Math.max(0, fadeDuration - time),\n 0,\n 100,\n fadeDuration,\n );\n context.filter = `brightness(${brightness}%)`;\n context.drawImage(orig, 0, 0);\n init.timestamp = start + time * 1000;\n const frame = new VideoFrame(context.canvas as unknown as ImageBitmap, init);\n controller.enqueue(frame);\n const next = time + duration;\n if (next > fadeDuration) {\n orig.close();\n deferred?.resolve();\n } else setTimeout(() => fadeOut(next), 0);\n };\n fadeOut(duration);\n }\n }\n await deferred?.promise;\n },\n });\n this.setDisableFadeOut = (value?: boolean) => {\n disableFadeOut = value;\n if (disableFadeOut) {\n last?.close();\n last = undefined;\n }\n };\n }\n}\n"],"mappings":";;AAQA,MAAM,gBAAgB,GAAW,GAAW,GAAW,MAErD,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAEtC,IAAqB,gBAArB,cAA2C,gBAAwC;CACjF;CAEA,YAAY,EAAE,WAAW,YAAY,UAAU,eAAe,QAAqB,CAAC,GAAG;EACrF,IAAI;EACJ,IAAI;EACJ,IAAI,MAAgD;EACpD,IAAI,OAAuB,CAAC;EAC5B,IAAI,iBAAiB;EACrB,MAAM,cAAc,UAA4B;GAC9C,IAAI,CAAC,KAEH,MAAM,IADgB,gBAAgB,MAAM,cAAc,MAAM,aAClD,EAAE,WAAW,IAAI;GAEjC,IAAI,CAAC,MAAM;IACT,MAAM,EAAE,cAAc,eAAe,aAAa,UAAU,cAAc;IAC1E,OAAO;KACL;KACA;KACA,aAAa,eAAe,KAAA;KAC5B,UAAU,YAAY,KAAA;KACtB,WAAW,aAAa,KAAA;IAC1B;GACF;EACF;EACA,MAAM;GACJ,UAAU,OAAO,YAAY;IAC3B,IAAI,CAAC,gBAAgB;KACnB,MAAM,MAAM;KACZ,OAAO,MAAM,MAAM;IACrB;IACA,MAAM,YAAY,MAAM,YAAY,MAAM,YAAY;IACtD,IAAI,CAAC,aAAa,YAAY,MAAO,cAAc;KACjD,IAAI,CAAC,KAAK,WAAW,KAAK;KAC1B,IAAI,KAAK;MACP,MAAM,aAAa,aAAa,YAAY,KAAM,GAAG,KAAK,YAAY;MACtE,IAAI,SAAS,cAAc,WAAW;MACtC,IAAI,UAAU,OAAO,GAAG,CAAC;MACzB,MAAM,MAAM;MACZ,KAAK,YAAY;MACjB,MAAM,QAAQ,IAAI,WAAW,IAAI,QAAkC,IAAI;MACvE,WAAW,QAAQ,KAAK;MACxB;KACF;IACF;IACA,WAAW,QAAQ,KAAK;GAC1B;GACA,OAAO,OAAO,eAAe;IAC3B,IAAI,QAAQ,KAAK,aAAa,CAAC,gBAAgB;KAC7C,IAAI,CAAC,KAAK,WAAW,IAAI;KACzB,IAAI,KAAK;MACP,WAAW,IAAI,SAAS;MACxB,MAAM,UAAU;MAChB,MAAM,OAAO;MACb,MAAM,EAAE,WAAW,UAAU;MAC7B,MAAM,WAAW,KAAK,WAAW,KAAK,WAAW,MAAO;MACxD,MAAM,WAAW,SAAiB;OAOhC,QAAQ,SAAS,cANE,aACjB,KAAK,IAAI,GAAG,eAAe,IAAI,GAC/B,GACA,KACA,YAEsC,EAAE;OAC1C,QAAQ,UAAU,MAAM,GAAG,CAAC;OAC5B,KAAK,YAAY,QAAQ,OAAO;OAChC,MAAM,QAAQ,IAAI,WAAW,QAAQ,QAAkC,IAAI;OAC3E,WAAW,QAAQ,KAAK;OACxB,MAAM,OAAO,OAAO;OACpB,IAAI,OAAO,cAAc;QACvB,KAAK,MAAM;QACX,UAAU,QAAQ;OACpB,OAAO,iBAAiB,QAAQ,IAAI,GAAG,CAAC;MAC1C;MACA,QAAQ,QAAQ;KAClB;IACF;IACA,MAAM,UAAU;GAClB;EACF,CAAC;EACD,KAAK,qBAAqB,UAAoB;GAC5C,iBAAiB;GACjB,IAAI,gBAAgB;IAClB,MAAM,MAAM;IACZ,OAAO,KAAA;GACT;EACF;CACF;AACF"}
@@ -0,0 +1,63 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_CancelError = require("./CancelError.cjs");
6
+ //#region src/RangeFetcher.ts
7
+ var RangeFetcher = class extends ReadableStream {
8
+ constructor(url, { chunkSize = 32768, abortController = new AbortController() }) {
9
+ let from = 0;
10
+ let total = Number.MAX_SAFE_INTEGER;
11
+ let cancelled = false;
12
+ super({
13
+ async start(controller) {
14
+ const res = await fetch(url, { method: "HEAD" });
15
+ if (res.ok && res.headers) {
16
+ const length = res.headers.get("content-length");
17
+ if (length) {
18
+ total = parseInt(length, 10);
19
+ if (Number.isNaN(total)) {
20
+ console.error(`Unknown size of ${url}`);
21
+ total = Number.MAX_SAFE_INTEGER;
22
+ } else if (total === 0) controller.close();
23
+ }
24
+ }
25
+ },
26
+ async pull(controller) {
27
+ try {
28
+ const res = await fetch(url, {
29
+ signal: abortController.signal,
30
+ headers: { range: `bytes=${from}-${Math.min(from + chunkSize, total) - 1}` }
31
+ });
32
+ if (!res.ok && !cancelled) controller.error(new Error(await res.text()));
33
+ if (!res.body || cancelled) {
34
+ controller.close();
35
+ return;
36
+ }
37
+ const reader = res.body.getReader();
38
+ let length = 0;
39
+ for (let result = await reader.read(); !result.done && !cancelled; result = await reader.read()) {
40
+ length += result.value.byteLength;
41
+ controller.enqueue(result.value);
42
+ }
43
+ from += length;
44
+ if (length === 0 || from === total || cancelled) controller.close();
45
+ } catch (error) {
46
+ if (cancelled || error instanceof require_CancelError.default) controller.close();
47
+ else {
48
+ controller.error(error);
49
+ console.error("error while fetch", error, url);
50
+ }
51
+ }
52
+ },
53
+ cancel() {
54
+ cancelled = true;
55
+ abortController.abort(new require_CancelError.default());
56
+ }
57
+ });
58
+ }
59
+ };
60
+ //#endregion
61
+ exports.default = RangeFetcher;
62
+
63
+ //# sourceMappingURL=RangeFetcher.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RangeFetcher.cjs","names":["CancelError"],"sources":["../src/RangeFetcher.ts"],"sourcesContent":["import CancelError from './CancelError';\n\ntype Options = {\n chunkSize?: number;\n abortController?: AbortController;\n};\n\nexport default class RangeFetcher extends ReadableStream<Uint8Array> {\n constructor(\n url: string,\n { chunkSize = 32768, abortController = new AbortController() }: Options,\n ) {\n let from = 0;\n let total = Number.MAX_SAFE_INTEGER;\n let cancelled = false;\n super({\n async start(controller) {\n const res = await fetch(url, { method: 'HEAD' });\n if (res.ok && res.headers) {\n const length = res.headers.get('content-length');\n if (length) {\n total = parseInt(length, 10);\n if (Number.isNaN(total)) {\n console.error(`Unknown size of ${url}`);\n total = Number.MAX_SAFE_INTEGER;\n } else if (total === 0) controller.close();\n }\n }\n },\n async pull(controller) {\n try {\n const res = await fetch(url, {\n signal: abortController.signal,\n headers: {\n range: `bytes=${from}-${Math.min(from + chunkSize, total) - 1}`,\n },\n });\n if (!res.ok && !cancelled) controller.error(new Error(await res.text()));\n if (!res.body || cancelled) {\n controller.close();\n return;\n }\n const reader = res.body.getReader();\n let length = 0;\n for (\n let result = await reader.read();\n !result.done && !cancelled;\n result = await reader.read()\n ) {\n length += result.value.byteLength;\n controller.enqueue(result.value);\n }\n from += length;\n if (length === 0 || from === total || cancelled) controller.close();\n } catch (error) {\n if (cancelled || error instanceof CancelError) {\n controller.close();\n } else {\n controller.error(error);\n console.error('error while fetch', error, url);\n }\n }\n },\n cancel() {\n cancelled = true;\n abortController.abort(new CancelError());\n },\n });\n }\n}\n"],"mappings":";;;;;;AAOA,IAAqB,eAArB,cAA0C,eAA2B;CACnE,YACE,KACA,EAAE,YAAY,OAAO,kBAAkB,IAAI,gBAAgB,KAC3D;EACA,IAAI,OAAO;EACX,IAAI,QAAQ,OAAO;EACnB,IAAI,YAAY;EAChB,MAAM;GACJ,MAAM,MAAM,YAAY;IACtB,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC;IAC/C,IAAI,IAAI,MAAM,IAAI,SAAS;KACzB,MAAM,SAAS,IAAI,QAAQ,IAAI,gBAAgB;KAC/C,IAAI,QAAQ;MACV,QAAQ,SAAS,QAAQ,EAAE;MAC3B,IAAI,OAAO,MAAM,KAAK,GAAG;OACvB,QAAQ,MAAM,mBAAmB,KAAK;OACtC,QAAQ,OAAO;MACjB,OAAO,IAAI,UAAU,GAAG,WAAW,MAAM;KAC3C;IACF;GACF;GACA,MAAM,KAAK,YAAY;IACrB,IAAI;KACF,MAAM,MAAM,MAAM,MAAM,KAAK;MAC3B,QAAQ,gBAAgB;MACxB,SAAS,EACP,OAAO,SAAS,KAAK,GAAG,KAAK,IAAI,OAAO,WAAW,KAAK,IAAI,IAC9D;KACF,CAAC;KACD,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,WAAW,MAAM,IAAI,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC;KACvE,IAAI,CAAC,IAAI,QAAQ,WAAW;MAC1B,WAAW,MAAM;MACjB;KACF;KACA,MAAM,SAAS,IAAI,KAAK,UAAU;KAClC,IAAI,SAAS;KACb,KACE,IAAI,SAAS,MAAM,OAAO,KAAK,GAC/B,CAAC,OAAO,QAAQ,CAAC,WACjB,SAAS,MAAM,OAAO,KAAK,GAC3B;MACA,UAAU,OAAO,MAAM;MACvB,WAAW,QAAQ,OAAO,KAAK;KACjC;KACA,QAAQ;KACR,IAAI,WAAW,KAAK,SAAS,SAAS,WAAW,WAAW,MAAM;IACpE,SAAS,OAAO;KACd,IAAI,aAAa,iBAAiBA,oBAAAA,SAChC,WAAW,MAAM;UACZ;MACL,WAAW,MAAM,KAAK;MACtB,QAAQ,MAAM,qBAAqB,OAAO,GAAG;KAC/C;IACF;GACF;GACA,SAAS;IACP,YAAY;IACZ,gBAAgB,MAAM,IAAIA,oBAAAA,QAAY,CAAC;GACzC;EACF,CAAC;CACH;AACF"}
@@ -0,0 +1 @@
1
+ export type * from './RangeFetcher.d.mts'
@@ -0,0 +1,14 @@
1
+ //#region src/RangeFetcher.d.ts
2
+ type Options = {
3
+ chunkSize?: number;
4
+ abortController?: AbortController;
5
+ };
6
+ declare class RangeFetcher extends ReadableStream<Uint8Array> {
7
+ constructor(url: string, {
8
+ chunkSize,
9
+ abortController
10
+ }: Options);
11
+ }
12
+ //#endregion
13
+ export { RangeFetcher as default };
14
+ //# sourceMappingURL=RangeFetcher.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RangeFetcher.d.mts","names":[],"sources":["../src/RangeFetcher.ts"],"mappings":";KAEK,OAAA;EACH,SAAA;EACA,eAAA,GAAkB,eAAe;AAAA;AAAA,cAGd,YAAA,SAAqB,cAAA,CAAe,UAAA;cAErD,GAAA;IACE,SAAA;IAAmB;EAAA,GAA2C,OAAA;AAAA"}
@@ -0,0 +1,59 @@
1
+ import CancelError from "./CancelError.mjs";
2
+ //#region src/RangeFetcher.ts
3
+ var RangeFetcher = class extends ReadableStream {
4
+ constructor(url, { chunkSize = 32768, abortController = new AbortController() }) {
5
+ let from = 0;
6
+ let total = Number.MAX_SAFE_INTEGER;
7
+ let cancelled = false;
8
+ super({
9
+ async start(controller) {
10
+ const res = await fetch(url, { method: "HEAD" });
11
+ if (res.ok && res.headers) {
12
+ const length = res.headers.get("content-length");
13
+ if (length) {
14
+ total = parseInt(length, 10);
15
+ if (Number.isNaN(total)) {
16
+ console.error(`Unknown size of ${url}`);
17
+ total = Number.MAX_SAFE_INTEGER;
18
+ } else if (total === 0) controller.close();
19
+ }
20
+ }
21
+ },
22
+ async pull(controller) {
23
+ try {
24
+ const res = await fetch(url, {
25
+ signal: abortController.signal,
26
+ headers: { range: `bytes=${from}-${Math.min(from + chunkSize, total) - 1}` }
27
+ });
28
+ if (!res.ok && !cancelled) controller.error(new Error(await res.text()));
29
+ if (!res.body || cancelled) {
30
+ controller.close();
31
+ return;
32
+ }
33
+ const reader = res.body.getReader();
34
+ let length = 0;
35
+ for (let result = await reader.read(); !result.done && !cancelled; result = await reader.read()) {
36
+ length += result.value.byteLength;
37
+ controller.enqueue(result.value);
38
+ }
39
+ from += length;
40
+ if (length === 0 || from === total || cancelled) controller.close();
41
+ } catch (error) {
42
+ if (cancelled || error instanceof CancelError) controller.close();
43
+ else {
44
+ controller.error(error);
45
+ console.error("error while fetch", error, url);
46
+ }
47
+ }
48
+ },
49
+ cancel() {
50
+ cancelled = true;
51
+ abortController.abort(new CancelError());
52
+ }
53
+ });
54
+ }
55
+ };
56
+ //#endregion
57
+ export { RangeFetcher as default };
58
+
59
+ //# sourceMappingURL=RangeFetcher.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RangeFetcher.mjs","names":[],"sources":["../src/RangeFetcher.ts"],"sourcesContent":["import CancelError from './CancelError';\n\ntype Options = {\n chunkSize?: number;\n abortController?: AbortController;\n};\n\nexport default class RangeFetcher extends ReadableStream<Uint8Array> {\n constructor(\n url: string,\n { chunkSize = 32768, abortController = new AbortController() }: Options,\n ) {\n let from = 0;\n let total = Number.MAX_SAFE_INTEGER;\n let cancelled = false;\n super({\n async start(controller) {\n const res = await fetch(url, { method: 'HEAD' });\n if (res.ok && res.headers) {\n const length = res.headers.get('content-length');\n if (length) {\n total = parseInt(length, 10);\n if (Number.isNaN(total)) {\n console.error(`Unknown size of ${url}`);\n total = Number.MAX_SAFE_INTEGER;\n } else if (total === 0) controller.close();\n }\n }\n },\n async pull(controller) {\n try {\n const res = await fetch(url, {\n signal: abortController.signal,\n headers: {\n range: `bytes=${from}-${Math.min(from + chunkSize, total) - 1}`,\n },\n });\n if (!res.ok && !cancelled) controller.error(new Error(await res.text()));\n if (!res.body || cancelled) {\n controller.close();\n return;\n }\n const reader = res.body.getReader();\n let length = 0;\n for (\n let result = await reader.read();\n !result.done && !cancelled;\n result = await reader.read()\n ) {\n length += result.value.byteLength;\n controller.enqueue(result.value);\n }\n from += length;\n if (length === 0 || from === total || cancelled) controller.close();\n } catch (error) {\n if (cancelled || error instanceof CancelError) {\n controller.close();\n } else {\n controller.error(error);\n console.error('error while fetch', error, url);\n }\n }\n },\n cancel() {\n cancelled = true;\n abortController.abort(new CancelError());\n },\n });\n }\n}\n"],"mappings":";;AAOA,IAAqB,eAArB,cAA0C,eAA2B;CACnE,YACE,KACA,EAAE,YAAY,OAAO,kBAAkB,IAAI,gBAAgB,KAC3D;EACA,IAAI,OAAO;EACX,IAAI,QAAQ,OAAO;EACnB,IAAI,YAAY;EAChB,MAAM;GACJ,MAAM,MAAM,YAAY;IACtB,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC;IAC/C,IAAI,IAAI,MAAM,IAAI,SAAS;KACzB,MAAM,SAAS,IAAI,QAAQ,IAAI,gBAAgB;KAC/C,IAAI,QAAQ;MACV,QAAQ,SAAS,QAAQ,EAAE;MAC3B,IAAI,OAAO,MAAM,KAAK,GAAG;OACvB,QAAQ,MAAM,mBAAmB,KAAK;OACtC,QAAQ,OAAO;MACjB,OAAO,IAAI,UAAU,GAAG,WAAW,MAAM;KAC3C;IACF;GACF;GACA,MAAM,KAAK,YAAY;IACrB,IAAI;KACF,MAAM,MAAM,MAAM,MAAM,KAAK;MAC3B,QAAQ,gBAAgB;MACxB,SAAS,EACP,OAAO,SAAS,KAAK,GAAG,KAAK,IAAI,OAAO,WAAW,KAAK,IAAI,IAC9D;KACF,CAAC;KACD,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,WAAW,MAAM,IAAI,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC;KACvE,IAAI,CAAC,IAAI,QAAQ,WAAW;MAC1B,WAAW,MAAM;MACjB;KACF;KACA,MAAM,SAAS,IAAI,KAAK,UAAU;KAClC,IAAI,SAAS;KACb,KACE,IAAI,SAAS,MAAM,OAAO,KAAK,GAC/B,CAAC,OAAO,QAAQ,CAAC,WACjB,SAAS,MAAM,OAAO,KAAK,GAC3B;MACA,UAAU,OAAO,MAAM;MACvB,WAAW,QAAQ,OAAO,KAAK;KACjC;KACA,QAAQ;KACR,IAAI,WAAW,KAAK,SAAS,SAAS,WAAW,WAAW,MAAM;IACpE,SAAS,OAAO;KACd,IAAI,aAAa,iBAAiB,aAChC,WAAW,MAAM;UACZ;MACL,WAAW,MAAM,KAAK;MACtB,QAAQ,MAAM,qBAAqB,OAAO,GAAG;KAC/C;IACF;GACF;GACA,SAAS;IACP,YAAY;IACZ,gBAAgB,MAAM,IAAI,YAAY,CAAC;GACzC;EACF,CAAC;CACH;AACF"}
@@ -0,0 +1,129 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_tools = require("./tools-DQrZvGBN.cjs");
6
+ const require_Deferred = require("./Deferred-CB69mtbF.cjs");
7
+ //#region src/ReducingValve.ts
8
+ const JITTER = 1e3 / 60;
9
+ const nextTick = (ms) => Math.ceil(ms / 1e3) * 1e3 - ms;
10
+ var ReducingValve = class extends TransformStream {
11
+ #baseTime = 0;
12
+ #closeTime = 0;
13
+ #state = "dry";
14
+ #deferred;
15
+ #timer = 0;
16
+ #dropped = 0;
17
+ #frames = 0;
18
+ id = Date.now().toString(16).slice(-6);
19
+ get state() {
20
+ return this.#state;
21
+ }
22
+ set state(value) {
23
+ const prev = this.#state;
24
+ if (prev !== value) {
25
+ this.#state = value;
26
+ switch (value) {
27
+ case "open":
28
+ if (prev === "closed") {
29
+ this.#baseTime += performance.now() - this.#closeTime;
30
+ this.#closeTime = 0;
31
+ if (this.#deferred) {
32
+ this.#deferred.resolve();
33
+ this.#deferred = void 0;
34
+ }
35
+ }
36
+ break;
37
+ case "closed":
38
+ clearTimeout(this.#timer);
39
+ if (this.#baseTime) this.#closeTime = performance.now();
40
+ if (this.#deferred) this.#deferred.resolve();
41
+ this.#deferred = new require_Deferred.Deferred();
42
+ break;
43
+ default: break;
44
+ }
45
+ postMessage({
46
+ state: value,
47
+ prev
48
+ });
49
+ }
50
+ }
51
+ constructor(closed) {
52
+ let total = 0;
53
+ super({
54
+ transform: async (frame, controller) => {
55
+ this.#frames += 1;
56
+ try {
57
+ if (this.#deferred) await this.#deferred.promise;
58
+ const { mediaTime } = this;
59
+ const { timestamp } = frame;
60
+ if (timestamp == null) {
61
+ console.warn(`ReducingValve#${this.id} empty timestamp, frame: ${this.#frames - 1}`);
62
+ frame.close();
63
+ return;
64
+ }
65
+ const frameDelay = mediaTime - timestamp / 1e3;
66
+ if (frameDelay > JITTER) {
67
+ const frameNo = this.#frames - 1;
68
+ this.#dropped += 1;
69
+ postMessage({
70
+ drop: frameNo,
71
+ frameDelay
72
+ });
73
+ frame.close();
74
+ return;
75
+ }
76
+ const timeUntilNextFrame = this.calculateTimeUntilNextFrame(timestamp);
77
+ if (timeUntilNextFrame) await require_tools.delay(timeUntilNextFrame);
78
+ controller.enqueue(frame);
79
+ total += 1;
80
+ } catch (err) {
81
+ controller.error(err);
82
+ console.error(`ReducingValve#${this.id} error: ${err}`);
83
+ frame.close();
84
+ }
85
+ },
86
+ flush: () => {
87
+ clearTimeout(this.#timer);
88
+ console.info(`!ReducingValve#${this.id}:flush, frames: ${this.#frames}, dropped: ${this.#dropped}(${(100 * this.#dropped / (this.#frames || 1)).toFixed(3)}%), outputs: ${total}`);
89
+ postMessage({
90
+ frames: this.#frames,
91
+ dropped: this.#dropped
92
+ });
93
+ }
94
+ }, new CountQueuingStrategy({ highWaterMark: 1 }));
95
+ if (closed) this.close();
96
+ }
97
+ close = () => {
98
+ this.state = "closed";
99
+ };
100
+ open = () => {
101
+ this.state = "open";
102
+ };
103
+ get mediaTime() {
104
+ if (!this.#baseTime) {
105
+ this.state = "open";
106
+ this.#baseTime = performance.now();
107
+ return 0;
108
+ }
109
+ return performance.now() - this.#baseTime;
110
+ }
111
+ timerTick = () => {
112
+ const { mediaTime } = this;
113
+ const timer = Math.round(mediaTime / 1e3);
114
+ postMessage({
115
+ timer,
116
+ dropped: this.#dropped
117
+ });
118
+ };
119
+ calculateTimeUntilNextFrame = (timestamp) => {
120
+ const { mediaTime } = this;
121
+ clearTimeout(this.#timer);
122
+ this.#timer = setTimeout(this.timerTick, nextTick(mediaTime));
123
+ return Math.max(0, timestamp / 1e3 - mediaTime);
124
+ };
125
+ };
126
+ //#endregion
127
+ exports.default = ReducingValve;
128
+
129
+ //# sourceMappingURL=ReducingValve.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReducingValve.cjs","names":["#state","#baseTime","#closeTime","#deferred","#timer","Deferred","#frames","#dropped","delay"],"sources":["../src/ReducingValve.ts"],"sourcesContent":["import Deferred from './Deferred';\nimport { delay } from './tools';\n\ntype ValveState = 'dry' | 'open' | 'closed';\n\nconst JITTER = 1000 / 60;\n\nconst nextTick = (ms: number): number => Math.ceil(ms / 1000) * 1000 - ms;\n\nexport default class ReducingValve extends TransformStream<VideoFrame, VideoFrame> {\n #baseTime = 0;\n\n #closeTime = 0;\n\n #state: ValveState = 'dry';\n\n #deferred?: Deferred;\n\n #timer = 0;\n\n #dropped = 0;\n\n #frames = 0;\n\n readonly id: string = Date.now().toString(16).slice(-6);\n\n get state(): ValveState {\n return this.#state;\n }\n\n protected set state(value) {\n const prev = this.#state;\n if (prev !== value) {\n this.#state = value;\n switch (value) {\n case 'open':\n if (prev === 'closed') {\n this.#baseTime += performance.now() - this.#closeTime;\n this.#closeTime = 0;\n if (this.#deferred) {\n this.#deferred.resolve();\n this.#deferred = undefined;\n }\n }\n break;\n case 'closed':\n clearTimeout(this.#timer);\n if (this.#baseTime) this.#closeTime = performance.now();\n if (this.#deferred) this.#deferred.resolve();\n this.#deferred = new Deferred();\n break;\n default:\n break;\n }\n postMessage({\n state: value,\n prev,\n });\n }\n }\n\n constructor(closed?: boolean) {\n let total = 0;\n super(\n {\n transform: async (frame, controller): Promise<void> => {\n this.#frames += 1;\n try {\n if (this.#deferred) await this.#deferred.promise;\n const { mediaTime } = this;\n const { timestamp } = frame;\n if (timestamp == null) {\n console.warn(`ReducingValve#${this.id} empty timestamp, frame: ${this.#frames - 1}`);\n frame.close();\n // controller.enqueue(frame);\n return;\n }\n const frameDelay = mediaTime - timestamp / 1000;\n if (frameDelay > JITTER) {\n const frameNo = this.#frames - 1;\n this.#dropped += 1;\n postMessage({ drop: frameNo, frameDelay });\n frame.close();\n return;\n }\n const timeUntilNextFrame = this.calculateTimeUntilNextFrame(timestamp);\n if (timeUntilNextFrame) await delay(timeUntilNextFrame);\n controller.enqueue(frame);\n total += 1;\n } catch (err) {\n controller.error(err);\n console.error(`ReducingValve#${this.id} error: ${err}`);\n frame.close();\n }\n },\n flush: () => {\n clearTimeout(this.#timer);\n console.info(\n `!ReducingValve#${this.id}:flush, frames: ${this.#frames}, dropped: ${this.#dropped}(${(\n (100 * this.#dropped) /\n (this.#frames || 1)\n ).toFixed(3)}%), outputs: ${total}`,\n );\n postMessage({ frames: this.#frames, dropped: this.#dropped });\n },\n },\n new CountQueuingStrategy({ highWaterMark: 1 }),\n );\n if (closed) this.close();\n }\n\n close = (): void => {\n this.state = 'closed';\n };\n\n open = (): void => {\n this.state = 'open';\n };\n\n protected get mediaTime(): number {\n if (!this.#baseTime) {\n this.state = 'open';\n this.#baseTime = performance.now();\n return 0;\n }\n return performance.now() - this.#baseTime;\n }\n\n private timerTick = (): void => {\n const { mediaTime } = this;\n const timer = Math.round(mediaTime / 1000);\n postMessage({\n timer,\n dropped: this.#dropped,\n });\n // this.#timer = window.setTimeout(this.timerTick, nextTick(mediaTime + 1));\n };\n\n protected calculateTimeUntilNextFrame = (timestamp: number): number => {\n const { mediaTime } = this;\n clearTimeout(this.#timer);\n this.#timer = setTimeout(this.timerTick, nextTick(mediaTime)) as unknown as number;\n return Math.max(0, timestamp / 1000 - mediaTime);\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export type * from './ReducingValve.d.mts'
@@ -0,0 +1,17 @@
1
+ //#region src/ReducingValve.d.ts
2
+ type ValveState = 'dry' | 'open' | 'closed';
3
+ declare class ReducingValve extends TransformStream<VideoFrame, VideoFrame> {
4
+ #private;
5
+ readonly id: string;
6
+ get state(): ValveState;
7
+ protected set state(value: ValveState);
8
+ constructor(closed?: boolean);
9
+ close: () => void;
10
+ open: () => void;
11
+ protected get mediaTime(): number;
12
+ private timerTick;
13
+ protected calculateTimeUntilNextFrame: (timestamp: number) => number;
14
+ }
15
+ //#endregion
16
+ export { ReducingValve as default };
17
+ //# sourceMappingURL=ReducingValve.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReducingValve.d.mts","names":[],"sources":["../src/ReducingValve.ts"],"mappings":";KAGK,UAAA;AAAA,cAMgB,aAAA,SAAsB,eAAA,CAAgB,UAAA,EAAY,UAAA;EAAA;WAe5D,EAAA;EAAA,IAEL,KAAA,CAAA,GAAS,UAAA;EAAA,cAIC,KAAA,CAAM,KAAA,EAJP,UAAA;cAmCD,MAAA;EAkDZ,KAAA;EAIA,IAAA;EAAA,cAIc,SAAA,CAAA;EAAA,QASN,SAAA;EAAA,UAUE,2BAAA,GAA+B,SAAA;AAAA"}
@@ -0,0 +1,125 @@
1
+ import { t as delay } from "./tools-CYLlbo9J.mjs";
2
+ import { t as Deferred } from "./Deferred-7Cu0KIje.mjs";
3
+ //#region src/ReducingValve.ts
4
+ const JITTER = 1e3 / 60;
5
+ const nextTick = (ms) => Math.ceil(ms / 1e3) * 1e3 - ms;
6
+ var ReducingValve = class extends TransformStream {
7
+ #baseTime = 0;
8
+ #closeTime = 0;
9
+ #state = "dry";
10
+ #deferred;
11
+ #timer = 0;
12
+ #dropped = 0;
13
+ #frames = 0;
14
+ id = Date.now().toString(16).slice(-6);
15
+ get state() {
16
+ return this.#state;
17
+ }
18
+ set state(value) {
19
+ const prev = this.#state;
20
+ if (prev !== value) {
21
+ this.#state = value;
22
+ switch (value) {
23
+ case "open":
24
+ if (prev === "closed") {
25
+ this.#baseTime += performance.now() - this.#closeTime;
26
+ this.#closeTime = 0;
27
+ if (this.#deferred) {
28
+ this.#deferred.resolve();
29
+ this.#deferred = void 0;
30
+ }
31
+ }
32
+ break;
33
+ case "closed":
34
+ clearTimeout(this.#timer);
35
+ if (this.#baseTime) this.#closeTime = performance.now();
36
+ if (this.#deferred) this.#deferred.resolve();
37
+ this.#deferred = new Deferred();
38
+ break;
39
+ default: break;
40
+ }
41
+ postMessage({
42
+ state: value,
43
+ prev
44
+ });
45
+ }
46
+ }
47
+ constructor(closed) {
48
+ let total = 0;
49
+ super({
50
+ transform: async (frame, controller) => {
51
+ this.#frames += 1;
52
+ try {
53
+ if (this.#deferred) await this.#deferred.promise;
54
+ const { mediaTime } = this;
55
+ const { timestamp } = frame;
56
+ if (timestamp == null) {
57
+ console.warn(`ReducingValve#${this.id} empty timestamp, frame: ${this.#frames - 1}`);
58
+ frame.close();
59
+ return;
60
+ }
61
+ const frameDelay = mediaTime - timestamp / 1e3;
62
+ if (frameDelay > JITTER) {
63
+ const frameNo = this.#frames - 1;
64
+ this.#dropped += 1;
65
+ postMessage({
66
+ drop: frameNo,
67
+ frameDelay
68
+ });
69
+ frame.close();
70
+ return;
71
+ }
72
+ const timeUntilNextFrame = this.calculateTimeUntilNextFrame(timestamp);
73
+ if (timeUntilNextFrame) await delay(timeUntilNextFrame);
74
+ controller.enqueue(frame);
75
+ total += 1;
76
+ } catch (err) {
77
+ controller.error(err);
78
+ console.error(`ReducingValve#${this.id} error: ${err}`);
79
+ frame.close();
80
+ }
81
+ },
82
+ flush: () => {
83
+ clearTimeout(this.#timer);
84
+ console.info(`!ReducingValve#${this.id}:flush, frames: ${this.#frames}, dropped: ${this.#dropped}(${(100 * this.#dropped / (this.#frames || 1)).toFixed(3)}%), outputs: ${total}`);
85
+ postMessage({
86
+ frames: this.#frames,
87
+ dropped: this.#dropped
88
+ });
89
+ }
90
+ }, new CountQueuingStrategy({ highWaterMark: 1 }));
91
+ if (closed) this.close();
92
+ }
93
+ close = () => {
94
+ this.state = "closed";
95
+ };
96
+ open = () => {
97
+ this.state = "open";
98
+ };
99
+ get mediaTime() {
100
+ if (!this.#baseTime) {
101
+ this.state = "open";
102
+ this.#baseTime = performance.now();
103
+ return 0;
104
+ }
105
+ return performance.now() - this.#baseTime;
106
+ }
107
+ timerTick = () => {
108
+ const { mediaTime } = this;
109
+ const timer = Math.round(mediaTime / 1e3);
110
+ postMessage({
111
+ timer,
112
+ dropped: this.#dropped
113
+ });
114
+ };
115
+ calculateTimeUntilNextFrame = (timestamp) => {
116
+ const { mediaTime } = this;
117
+ clearTimeout(this.#timer);
118
+ this.#timer = setTimeout(this.timerTick, nextTick(mediaTime));
119
+ return Math.max(0, timestamp / 1e3 - mediaTime);
120
+ };
121
+ };
122
+ //#endregion
123
+ export { ReducingValve as default };
124
+
125
+ //# sourceMappingURL=ReducingValve.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReducingValve.mjs","names":["#state","#baseTime","#closeTime","#deferred","#timer","#frames","#dropped"],"sources":["../src/ReducingValve.ts"],"sourcesContent":["import Deferred from './Deferred';\nimport { delay } from './tools';\n\ntype ValveState = 'dry' | 'open' | 'closed';\n\nconst JITTER = 1000 / 60;\n\nconst nextTick = (ms: number): number => Math.ceil(ms / 1000) * 1000 - ms;\n\nexport default class ReducingValve extends TransformStream<VideoFrame, VideoFrame> {\n #baseTime = 0;\n\n #closeTime = 0;\n\n #state: ValveState = 'dry';\n\n #deferred?: Deferred;\n\n #timer = 0;\n\n #dropped = 0;\n\n #frames = 0;\n\n readonly id: string = Date.now().toString(16).slice(-6);\n\n get state(): ValveState {\n return this.#state;\n }\n\n protected set state(value) {\n const prev = this.#state;\n if (prev !== value) {\n this.#state = value;\n switch (value) {\n case 'open':\n if (prev === 'closed') {\n this.#baseTime += performance.now() - this.#closeTime;\n this.#closeTime = 0;\n if (this.#deferred) {\n this.#deferred.resolve();\n this.#deferred = undefined;\n }\n }\n break;\n case 'closed':\n clearTimeout(this.#timer);\n if (this.#baseTime) this.#closeTime = performance.now();\n if (this.#deferred) this.#deferred.resolve();\n this.#deferred = new Deferred();\n break;\n default:\n break;\n }\n postMessage({\n state: value,\n prev,\n });\n }\n }\n\n constructor(closed?: boolean) {\n let total = 0;\n super(\n {\n transform: async (frame, controller): Promise<void> => {\n this.#frames += 1;\n try {\n if (this.#deferred) await this.#deferred.promise;\n const { mediaTime } = this;\n const { timestamp } = frame;\n if (timestamp == null) {\n console.warn(`ReducingValve#${this.id} empty timestamp, frame: ${this.#frames - 1}`);\n frame.close();\n // controller.enqueue(frame);\n return;\n }\n const frameDelay = mediaTime - timestamp / 1000;\n if (frameDelay > JITTER) {\n const frameNo = this.#frames - 1;\n this.#dropped += 1;\n postMessage({ drop: frameNo, frameDelay });\n frame.close();\n return;\n }\n const timeUntilNextFrame = this.calculateTimeUntilNextFrame(timestamp);\n if (timeUntilNextFrame) await delay(timeUntilNextFrame);\n controller.enqueue(frame);\n total += 1;\n } catch (err) {\n controller.error(err);\n console.error(`ReducingValve#${this.id} error: ${err}`);\n frame.close();\n }\n },\n flush: () => {\n clearTimeout(this.#timer);\n console.info(\n `!ReducingValve#${this.id}:flush, frames: ${this.#frames}, dropped: ${this.#dropped}(${(\n (100 * this.#dropped) /\n (this.#frames || 1)\n ).toFixed(3)}%), outputs: ${total}`,\n );\n postMessage({ frames: this.#frames, dropped: this.#dropped });\n },\n },\n new CountQueuingStrategy({ highWaterMark: 1 }),\n );\n if (closed) this.close();\n }\n\n close = (): void => {\n this.state = 'closed';\n };\n\n open = (): void => {\n this.state = 'open';\n };\n\n protected get mediaTime(): number {\n if (!this.#baseTime) {\n this.state = 'open';\n this.#baseTime = performance.now();\n return 0;\n }\n return performance.now() - this.#baseTime;\n }\n\n private timerTick = (): void => {\n const { mediaTime } = this;\n const timer = Math.round(mediaTime / 1000);\n postMessage({\n timer,\n dropped: this.#dropped,\n });\n // this.#timer = window.setTimeout(this.timerTick, nextTick(mediaTime + 1));\n };\n\n protected calculateTimeUntilNextFrame = (timestamp: number): number => {\n const { mediaTime } = this;\n clearTimeout(this.#timer);\n this.#timer = setTimeout(this.timerTick, nextTick(mediaTime)) as unknown as number;\n return Math.max(0, timestamp / 1000 - mediaTime);\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_Element = require("./Element-8JyOKTYb.cjs");
6
+ const require_tools = require("./tools-DQrZvGBN.cjs");
7
+ const require_Deferred = require("./Deferred-CB69mtbF.cjs");
8
+ //#region src/VideoChunkGenerator.ts
9
+ const VIDEO = 1;
10
+ const getCodec = (element) => {
11
+ switch (element.value) {
12
+ case "V_MPEG4/ISO/AVC": return "avc1.";
13
+ case "V_VP9": return "vp09.00.50.08";
14
+ case "V_VP8": return "vp8";
15
+ default: return;
16
+ }
17
+ };
18
+ var VideoChunkGenerator = class extends TransformStream {
19
+ #config = new require_Deferred.Deferred();
20
+ clusters = [];
21
+ get config() {
22
+ return this.#config.promise;
23
+ }
24
+ id = Date.now().toString(16).slice(-6);
25
+ constructor() {
26
+ let trackType;
27
+ let offset = 0;
28
+ let block;
29
+ let hasReference = false;
30
+ let total = 0;
31
+ const config = {};
32
+ const elements = {};
33
+ const required = {
34
+ PixelWidth: "codedWidth",
35
+ PixelHeight: "codedHeight",
36
+ CodecPrivate: "codec",
37
+ CodecID: "codec"
38
+ };
39
+ const parseConfig = (meta) => {
40
+ switch (meta.name) {
41
+ case "CodecID": {
42
+ const codec = getCodec(meta);
43
+ if (codec) {
44
+ config.codec = codec;
45
+ if (!codec.endsWith(".")) delete required.CodecPrivate;
46
+ }
47
+ break;
48
+ }
49
+ case "CodecPrivate":
50
+ if (config.codec === "avc1.") {
51
+ const codecPrivate = meta;
52
+ config.codec += require_tools.readHexString(codecPrivate.data.subarray(1, 4));
53
+ config.description = codecPrivate.data.slice();
54
+ }
55
+ break;
56
+ default: {
57
+ const name = required[meta.name];
58
+ if (name) config[name] = meta.value;
59
+ }
60
+ }
61
+ };
62
+ super({
63
+ transform: async (element, controller) => {
64
+ elements[element.name] = (elements[element.name] ?? 0) + 1;
65
+ try {
66
+ if (require_Element.isTrackType(element)) {
67
+ trackType = element.value;
68
+ return;
69
+ }
70
+ if (require_Element.isContentElement(element) && required[element.name] && (trackType == null || trackType === VIDEO)) {
71
+ parseConfig(element);
72
+ delete required[element.name];
73
+ if (Object.keys(required).length === 0) this.#config.resolve(config);
74
+ return;
75
+ }
76
+ if (require_Element.isTimestamp(element)) {
77
+ offset = element.value;
78
+ return;
79
+ }
80
+ if (require_Element.isDuration(element)) {
81
+ postMessage({ duration: element.value / 1e3 });
82
+ return;
83
+ }
84
+ if (require_Element.isSimpleBlockElement(element)) {
85
+ if (trackType === VIDEO) {
86
+ controller.enqueue(new EncodedVideoChunk({
87
+ type: element.keyframe ? "key" : "delta",
88
+ timestamp: (offset + element.value) * 1e3,
89
+ data: element.payload
90
+ }));
91
+ total += 1;
92
+ }
93
+ return;
94
+ }
95
+ if (require_Element.isBlockElement(element)) {
96
+ block = element;
97
+ return;
98
+ }
99
+ if (element.name === "ReferenceBlock") {
100
+ hasReference = true;
101
+ return;
102
+ }
103
+ if (require_Element.isBlockGroupElement(element) && element.isClosing) {
104
+ if (block) {
105
+ controller.enqueue(new EncodedVideoChunk({
106
+ type: hasReference ? "delta" : "key",
107
+ timestamp: (block.value + offset) * 1e3,
108
+ data: block.payload
109
+ }));
110
+ total += 1;
111
+ }
112
+ block = void 0;
113
+ hasReference = false;
114
+ }
115
+ if (require_Element.isMasterElement(element) && element.name === "Cluster" && !element.isClosing) this.clusters.push(total);
116
+ } catch (err) {
117
+ console.error(`VideoChunkGenerator#${this.id} error while ELEMENT: ${err}`);
118
+ controller.error(err);
119
+ this.#config.reject(err);
120
+ }
121
+ },
122
+ flush: (controller) => {
123
+ controller.terminate();
124
+ }
125
+ });
126
+ }
127
+ };
128
+ //#endregion
129
+ exports.default = VideoChunkGenerator;
130
+
131
+ //# sourceMappingURL=VideoChunkGenerator.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoChunkGenerator.cjs","names":["Deferred","#config","readHexString","isTrackType","isContentElement","isTimestamp","isDuration","isSimpleBlockElement","isBlockElement","isBlockGroupElement","isMasterElement"],"sources":["../src/VideoChunkGenerator.ts"],"sourcesContent":["import Deferred from './Deferred';\nimport {\n isBlockElement,\n isBlockGroupElement,\n isContentElement,\n isDuration,\n isMasterElement,\n isSimpleBlockElement,\n isTimestamp,\n isTrackType,\n} from './Element';\nimport type { BlockElement, ContentElement, Element } from './Element';\nimport { readHexString } from './tools';\n\nconst VIDEO = 1;\n\nconst getCodec = (element: ContentElement<'string' | 'utf-8'>): string | undefined => {\n switch (element.value) {\n case 'V_MPEG4/ISO/AVC':\n return 'avc1.';\n case 'V_VP9':\n return 'vp09.00.50.08';\n case 'V_VP8':\n return 'vp8'; // 'vp08.00.41.08';\n default:\n return undefined;\n }\n};\n\nexport default class VideoChunkGenerator extends TransformStream<Element, EncodedVideoChunk> {\n #config = new Deferred<VideoDecoderConfig>();\n\n readonly clusters: number[] = [];\n\n get config(): Promise<VideoDecoderConfig> {\n return this.#config.promise;\n }\n\n readonly id: string = Date.now().toString(16).slice(-6);\n\n constructor() {\n let trackType: number | undefined;\n let offset = 0;\n let block: BlockElement | undefined;\n let hasReference = false;\n let total = 0;\n const config: Partial<VideoDecoderConfig> = {};\n const elements: Record<string, number> = {};\n const required: Record<string, keyof VideoDecoderConfig> = {\n PixelWidth: 'codedWidth',\n PixelHeight: 'codedHeight',\n CodecPrivate: 'codec',\n CodecID: 'codec',\n };\n\n const parseConfig = (meta: ContentElement): void => {\n switch (meta.name) {\n case 'CodecID': {\n const codec = getCodec(meta as ContentElement<'string'>);\n if (codec) {\n config.codec = codec;\n if (!codec.endsWith('.')) {\n delete required.CodecPrivate;\n }\n }\n break;\n }\n case 'CodecPrivate':\n if (config.codec === 'avc1.') {\n const codecPrivate = meta as ContentElement<'binary'>;\n config.codec += readHexString(codecPrivate.data.subarray(1, 4));\n config.description = codecPrivate.data.slice();\n }\n break;\n default: {\n const name = required[meta.name];\n if (name) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n config[name] = meta.value as any;\n }\n }\n }\n };\n super({\n transform: async (element, controller) => {\n elements[element.name] = (elements[element.name] ?? 0) + 1;\n try {\n if (isTrackType(element)) {\n trackType = element.value as number;\n return;\n }\n if (\n isContentElement(element) &&\n required[element.name] &&\n (trackType == null || trackType === VIDEO)\n ) {\n parseConfig(element);\n delete required[element.name];\n if (Object.keys(required).length === 0) {\n // console.info(`VideoChunkGenerator#${this.id}:config ${JSON.stringify(config)}`);\n this.#config.resolve(config as VideoDecoderConfig);\n }\n return;\n }\n\n if (isTimestamp(element)) {\n offset = element.value as number;\n return;\n }\n\n if (isDuration(element)) {\n postMessage({ duration: element.value / 1000 });\n return;\n }\n\n if (isSimpleBlockElement(element)) {\n if (trackType === VIDEO) {\n controller.enqueue(\n new EncodedVideoChunk({\n type: element.keyframe ? 'key' : 'delta',\n timestamp: (offset + element.value) * 1000,\n data: element.payload,\n }),\n );\n total += 1;\n }\n return;\n }\n\n if (isBlockElement(element)) {\n block = element;\n return;\n }\n\n if (element.name === 'ReferenceBlock') {\n hasReference = true;\n return;\n }\n\n if (isBlockGroupElement(element) && element.isClosing) {\n if (block) {\n controller.enqueue(\n new EncodedVideoChunk({\n type: hasReference ? 'delta' : 'key',\n timestamp: (block.value + offset) * 1000,\n data: block.payload,\n }),\n );\n total += 1;\n }\n block = undefined;\n hasReference = false;\n }\n if (isMasterElement(element) && element.name === 'Cluster' && !element.isClosing)\n this.clusters.push(total);\n } catch (err) {\n console.error(`VideoChunkGenerator#${this.id} error while ELEMENT: ${err}`);\n controller.error(err);\n this.#config.reject(err as Error);\n }\n },\n flush: (controller) => {\n // console.info(\n // `VideoChunkGenerator#${this.id}:flush total: ${total}, clusters: ${this.clusters.join()}`\n // );\n controller.terminate();\n },\n });\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export type * from './VideoChunkGenerator.d.mts'
@@ -0,0 +1,13 @@
1
+ import { i as Element } from "./Element-CC4E6wMR.mjs";
2
+
3
+ //#region src/VideoChunkGenerator.d.ts
4
+ declare class VideoChunkGenerator extends TransformStream<Element, EncodedVideoChunk> {
5
+ #private;
6
+ readonly clusters: number[];
7
+ get config(): Promise<VideoDecoderConfig>;
8
+ readonly id: string;
9
+ constructor();
10
+ }
11
+ //#endregion
12
+ export { VideoChunkGenerator as default };
13
+ //# sourceMappingURL=VideoChunkGenerator.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoChunkGenerator.d.mts","names":[],"sources":["../src/VideoChunkGenerator.ts"],"mappings":";;;cA6BqB,mBAAA,SAA4B,eAAA,CAAgB,OAAA,EAAS,iBAAA;EAAA;WAG/D,QAAA;EAAA,IAEL,MAAA,CAAA,GAAU,OAAA,CAAQ,kBAAA;EAAA,SAIb,EAAA"}