@mediafox/core 1.2.6 → 1.2.7
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/dist/compositor/audio-manager.d.ts +1 -0
- package/dist/compositor/audio-manager.d.ts.map +1 -1
- package/dist/compositor/compositor-worker.d.ts +2 -0
- package/dist/compositor/compositor-worker.d.ts.map +1 -0
- package/dist/compositor/compositor.d.ts +10 -1
- package/dist/compositor/compositor.d.ts.map +1 -1
- package/dist/compositor/index.d.ts +1 -1
- package/dist/compositor/index.d.ts.map +1 -1
- package/dist/compositor/source-pool.d.ts.map +1 -1
- package/dist/compositor/types.d.ts +7 -0
- package/dist/compositor/types.d.ts.map +1 -1
- package/dist/compositor/worker-client.d.ts +30 -0
- package/dist/compositor/worker-client.d.ts.map +1 -0
- package/dist/compositor/worker-types.d.ts +57 -0
- package/dist/compositor/worker-types.d.ts.map +1 -0
- package/dist/compositor-worker.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-manager.d.ts","sourceRoot":"","sources":["../../src/compositor/audio-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAkB5D,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,6BAAkC;IAkBvD;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI;IA2B3E;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUxC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpC;;;OAGG;IACH,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"audio-manager.d.ts","sourceRoot":"","sources":["../../src/compositor/audio-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAkB5D,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,sBAAsB,CAAqB;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,6BAAkC;IAkBvD;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI;IA2B3E;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUxC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpC;;;OAGG;IACH,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAmDjE;;OAEG;IACG,IAAI,CAAC,QAAQ,GAAE,MAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5D;;;OAGG;IACH,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAO/D,OAAO,CAAC,qBAAqB;YAiBf,qBAAqB;YAoDrB,cAAc;IAoB5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5C,OAAO,CAAC,eAAe;IAkBvB;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKpC,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,eAAe,IAAI,YAAY;IAI/B;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,OAAO,IAAI,IAAI;CAqBhB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compositor-worker.d.ts","sourceRoot":"","sources":["../../src/compositor/compositor-worker.ts"],"names":[],"mappings":""}
|
|
@@ -31,17 +31,22 @@ export declare class Compositor {
|
|
|
31
31
|
private backgroundColor;
|
|
32
32
|
private sourcePool;
|
|
33
33
|
private audioManager;
|
|
34
|
+
private workerClient;
|
|
35
|
+
private workerSources;
|
|
36
|
+
private workerAudioSources;
|
|
34
37
|
private emitter;
|
|
35
38
|
private state;
|
|
36
39
|
private animationFrameId;
|
|
37
40
|
private lastFrameTime;
|
|
41
|
+
private lastRenderTime;
|
|
38
42
|
private previewOptions;
|
|
39
43
|
private disposed;
|
|
40
44
|
private renderBuffers;
|
|
41
45
|
private lastTimeUpdateEmit;
|
|
42
46
|
private timeUpdateThrottleMs;
|
|
43
47
|
private renderPending;
|
|
44
|
-
private
|
|
48
|
+
private activeAudioSourceIds;
|
|
49
|
+
private audioScratch;
|
|
45
50
|
private registeredAudioSources;
|
|
46
51
|
/**
|
|
47
52
|
* Creates a new Compositor instance.
|
|
@@ -101,6 +106,10 @@ export declare class Compositor {
|
|
|
101
106
|
*/
|
|
102
107
|
render(frame: CompositionFrame): Promise<boolean>;
|
|
103
108
|
private renderLayer;
|
|
109
|
+
private createWorkerSource;
|
|
110
|
+
private loadWorkerAudio;
|
|
111
|
+
private unloadWorkerAudio;
|
|
112
|
+
private serializeWorkerFrame;
|
|
104
113
|
/**
|
|
105
114
|
* Clears the canvas with the background color.
|
|
106
115
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compositor.d.ts","sourceRoot":"","sources":["../../src/compositor/compositor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,KAAK,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAElB,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACf,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"compositor.d.ts","sourceRoot":"","sources":["../../src/compositor/compositor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,KAAK,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAElB,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACf,MAAM,SAAS,CAAC;AAkBjB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,GAAG,CAA6E;IACxF,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAS;IAGzB,OAAO,CAAC,aAAa,CAA4E;IACjG,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,oBAAoB,CAAO;IACnC,OAAO,CAAC,aAAa,CAAS;IAG9B,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,YAAY,CAIlB;IACF,OAAO,CAAC,sBAAsB,CAAqB;IAEnD;;;OAGG;gBACS,OAAO,EAAE,iBAAiB;IAoEtC;;;;;OAKG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAqBnG;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAcxE;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAqBlG;;;;OAIG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAwBjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2C1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAOnD;;;OAGG;IACH,aAAa,IAAI,gBAAgB,EAAE;IASnC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAqEvD,OAAO,CAAC,WAAW;IA4DnB,OAAO,CAAC,kBAAkB;YAyBZ,eAAe;IAgB7B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAQtC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBvC,OAAO,CAAC,eAAe;IAgEvB,OAAO,CAAC,cAAc;IAStB;;;;;OAKG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAiCvF,wCAAwC;IACxC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,4DAA4D;IAC5D,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,mDAAmD;IACnD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,kDAAkD;IAClD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,mDAAmD;IACnD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAIlB;;;OAGG;IACH,SAAS,IAAI,MAAM;IAInB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAe3C;;;;;OAKG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAIlG;;;;;OAKG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAIpG;;;;OAIG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,IAAI;IAM9F;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B;;;OAGG;IACH,eAAe,IAAI,YAAY;IAS/B,OAAO,CAAC,aAAa;IAMrB;;;OAGG;IACH,OAAO,IAAI,IAAI;CAoBhB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Compositor } from './compositor';
|
|
2
2
|
export { SourcePool } from './source-pool';
|
|
3
|
-
export type { AudioLayer, CompositionFrame, CompositionProvider, CompositorEventListener, CompositorEventMap, CompositorLayer, CompositorOptions, CompositorRendererType, CompositorSource, CompositorSourceOptions, FrameExportOptions, LayerTransform, PreviewOptions, SourceType, } from './types';
|
|
3
|
+
export type { AudioLayer, CompositionFrame, CompositionProvider, CompositorEventListener, CompositorEventMap, CompositorLayer, CompositorOptions, CompositorRendererType, CompositorSource, CompositorSourceOptions, CompositorWorkerOptions, FrameExportOptions, LayerTransform, PreviewOptions, SourceType, } from './types';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compositor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,GACX,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compositor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,GACX,MAAM,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-pool.d.ts","sourceRoot":"","sources":["../../src/compositor/source-pool.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAc,MAAM,SAAS,CAAC;AAwMrF,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAK;gBAEP,YAAY,CAAC,EAAE,YAAY;IAIvC,OAAO,CAAC,UAAU;IAIZ,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmFhG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"source-pool.d.ts","sourceRoot":"","sources":["../../src/compositor/source-pool.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAc,MAAM,SAAS,CAAC;AAwMrF,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAK;gBAEP,YAAY,CAAC,EAAE,YAAY;IAIvC,OAAO,CAAC,UAAU;IAIZ,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmFhG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkClE,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyCtG,OAAO,CAAC,WAAW;IA0BnB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAInD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI9B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAUjC,aAAa,IAAI,gBAAgB,EAAE;IAInC,KAAK,IAAI,IAAI;IAOb,OAAO,IAAI,IAAI;CAOhB"}
|
|
@@ -6,6 +6,8 @@ export interface CompositorOptions {
|
|
|
6
6
|
height?: number;
|
|
7
7
|
renderer?: CompositorRendererType;
|
|
8
8
|
backgroundColor?: string;
|
|
9
|
+
enableAudio?: boolean;
|
|
10
|
+
worker?: boolean | CompositorWorkerOptions;
|
|
9
11
|
}
|
|
10
12
|
export interface LayerTransform {
|
|
11
13
|
x?: number;
|
|
@@ -45,6 +47,11 @@ export interface PreviewOptions {
|
|
|
45
47
|
fps?: number;
|
|
46
48
|
loop?: boolean;
|
|
47
49
|
}
|
|
50
|
+
export interface CompositorWorkerOptions {
|
|
51
|
+
enabled?: boolean;
|
|
52
|
+
url?: string;
|
|
53
|
+
type?: 'classic' | 'module';
|
|
54
|
+
}
|
|
48
55
|
export interface FrameExportOptions {
|
|
49
56
|
format?: 'png' | 'jpeg' | 'webp';
|
|
50
57
|
quality?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compositor/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compositor/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,GAAG,uBAAuB,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,mBAAmB,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC5D,kBAAkB,CAAC,IAAI,OAAO,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACnE,QAAQ,CAAC,IAAI,OAAO,CAAC;IACrB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,UAAU,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC;IACvD,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,iBAAiB,EAAE,SAAS,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,MAAM,kBAAkB,IAAI,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MediaSource } from '../types';
|
|
2
|
+
import type { CompositorWorkerOptions, CompositorSourceOptions, FrameExportOptions } from './types';
|
|
3
|
+
import type { CompositorWorkerFrame, CompositorWorkerSourceInfo } from './worker-types';
|
|
4
|
+
interface CompositorWorkerClientOptions {
|
|
5
|
+
canvas: HTMLCanvasElement;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
backgroundColor: string;
|
|
9
|
+
worker: CompositorWorkerOptions | boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class CompositorWorkerClient {
|
|
12
|
+
private worker;
|
|
13
|
+
private nextId;
|
|
14
|
+
private pending;
|
|
15
|
+
private ready;
|
|
16
|
+
constructor(options: CompositorWorkerClientOptions);
|
|
17
|
+
private postMessage;
|
|
18
|
+
private call;
|
|
19
|
+
loadSource(source: MediaSource, options?: CompositorSourceOptions): Promise<CompositorWorkerSourceInfo>;
|
|
20
|
+
loadImage(source: string | Blob | File): Promise<CompositorWorkerSourceInfo>;
|
|
21
|
+
loadAudio(source: MediaSource, options?: CompositorSourceOptions): Promise<CompositorWorkerSourceInfo>;
|
|
22
|
+
unloadSource(id: string): Promise<boolean>;
|
|
23
|
+
render(frame: CompositorWorkerFrame): Promise<boolean>;
|
|
24
|
+
clear(): Promise<boolean>;
|
|
25
|
+
resize(width: number, height: number): Promise<boolean>;
|
|
26
|
+
exportFrame(frame: CompositorWorkerFrame, options?: FrameExportOptions): Promise<Blob | null>;
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=worker-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-client.d.ts","sourceRoot":"","sources":["../../src/compositor/worker-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,KAAK,EAEV,qBAAqB,EAMrB,0BAA0B,EAE3B,MAAM,gBAAgB,CAAC;AAExB,UAAU,6BAA6B;IACrC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC;CAC3C;AAOD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,KAAK,CAAgB;gBAEjB,OAAO,EAAE,6BAA6B;IAoClD,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,IAAI;IAON,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAMvG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAM5E,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAMtG,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM1C,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC;IAMtD,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAKzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMvD,WAAW,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAMnG,OAAO,IAAI,IAAI;CAShB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { MediaSource } from '../types';
|
|
2
|
+
import type { FrameExportOptions, LayerTransform, CompositorSourceOptions, SourceType } from './types';
|
|
3
|
+
export interface CompositorWorkerLayer {
|
|
4
|
+
sourceId: string;
|
|
5
|
+
sourceTime?: number;
|
|
6
|
+
transform?: LayerTransform;
|
|
7
|
+
visible?: boolean;
|
|
8
|
+
zIndex?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CompositorWorkerFrame {
|
|
11
|
+
time: number;
|
|
12
|
+
layers: CompositorWorkerLayer[];
|
|
13
|
+
}
|
|
14
|
+
export interface CompositorWorkerSourceInfo {
|
|
15
|
+
id: string;
|
|
16
|
+
type: SourceType;
|
|
17
|
+
duration: number;
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
hasAudio?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface CompositorWorkerRequest {
|
|
23
|
+
id: number;
|
|
24
|
+
kind: string;
|
|
25
|
+
payload?: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface CompositorWorkerResponse {
|
|
28
|
+
id: number;
|
|
29
|
+
ok: boolean;
|
|
30
|
+
result?: unknown;
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface CompositorWorkerInitPayload {
|
|
34
|
+
canvas: OffscreenCanvas;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
backgroundColor: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CompositorWorkerLoadPayload {
|
|
40
|
+
source: MediaSource;
|
|
41
|
+
options?: CompositorSourceOptions;
|
|
42
|
+
}
|
|
43
|
+
export interface CompositorWorkerUnloadPayload {
|
|
44
|
+
id: string;
|
|
45
|
+
}
|
|
46
|
+
export interface CompositorWorkerRenderPayload {
|
|
47
|
+
frame: CompositorWorkerFrame;
|
|
48
|
+
}
|
|
49
|
+
export interface CompositorWorkerResizePayload {
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}
|
|
53
|
+
export interface CompositorWorkerExportPayload {
|
|
54
|
+
frame: CompositorWorkerFrame;
|
|
55
|
+
options?: FrameExportOptions;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=worker-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-types.d.ts","sourceRoot":"","sources":["../../src/compositor/worker-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEvG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,uBAAuB,CAAC;CACnC;AAED,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,qBAAqB,CAAC;CAC9B;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,qBAAqB,CAAC;IAC7B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class O{events=new Map;maxListeners;captureRejections;emitCache=[];constructor(o={}){this.maxListeners=o.maxListeners??10,this.captureRejections=o.captureRejections??!1}on(o,C){if(!this.events.has(o))this.events.set(o,new Set);let W=this.events.get(o);if(!W)return()=>{};if(W.size>=this.maxListeners)console.warn(`MaxListenersExceededWarning: Possible EventEmitter memory leak detected. ${W.size} ${String(o)} listeners added. Use emitter.setMaxListeners() to increase limit`);let w=C;return W.add(w),()=>{W.delete(w)}}once(o,C){let W=(w)=>{this.off(o,W),C(w)};return this.on(o,W)}off(o,C){let W=this.events.get(o);if(!W)return;if(C){let w=C;W.delete(w)}else W.clear()}emit(o,C){let W=this.events.get(o);if(!W||W.size===0)return;let w=this.emitCache;w.length=0;for(let k of W)w.push(k);for(let k=0;k<w.length;k++){let P=w[k];try{let r=P(C);if(this.captureRejections&&N(r))this.handlePromiseRejection(r)}catch(r){if(this.captureRejections&&this.events.has("error"))this.emit("error",r);else throw r}}}handlePromiseRejection(o){o.catch((C)=>{if(this.events.has("error"))this.emit("error",C);else throw C})}removeAllListeners(o){if(o)this.events.delete(o);else this.events.clear()}setMaxListeners(o){this.maxListeners=o}getMaxListeners(){return this.maxListeners}listeners(o){let C=this.events.get(o);return C?Array.from(C):[]}listenerCount(o){let C=this.events.get(o);return C?C.size:0}eventNames(){return Array.from(this.events.keys())}}function N(o){if(!o||typeof o!=="object"&&typeof o!=="function")return!1;let C=o;return typeof C.then==="function"&&typeof C.catch==="function"}class J{audioContext;masterGain;activeSources=new Map;activeSourceIdsScratch=new Set;playing=!1;disposed=!1;playbackId=0;startContextTime=0;startMediaTime=0;pauseTime=0;masterVolume=1;masterMuted=!1;constructor(o={}){if(o.audioContext)this.audioContext=o.audioContext;else{let C=globalThis,W=C.AudioContext||C.webkitAudioContext;if(!W)throw Error("AudioContext is not supported in this environment");this.audioContext=new W}this.masterGain=this.audioContext.createGain(),this.masterGain.connect(this.audioContext.destination)}registerSource(o,C){if(this.disposed)return;let W=this.audioContext.createGain(),w=this.audioContext.createStereoPanner();W.connect(w),w.connect(this.masterGain),this.activeSources.set(o.id,{sourceId:o.id,bufferSink:C,iterator:null,gainNode:W,panNode:w,queuedNodes:new Set,volume:1,pan:0,muted:!1,startSourceTime:0,currentSourceTime:0,iteratorStartTime:0,lastScheduledTime:0})}unregisterSource(o){let C=this.activeSources.get(o);if(!C)return;this.stopSourceAudio(C),C.gainNode.disconnect(),C.panNode.disconnect(),this.activeSources.delete(o)}hasSource(o){return this.activeSources.has(o)}processAudioLayers(o,C){if(this.disposed||!this.playing)return;let W=this.activeSourceIdsScratch;W.clear();for(let w of o){let k=w.source.id;W.add(k);let P=this.activeSources.get(k);if(!P)continue;let r=w.volume??1,p=w.pan??0,n=w.muted??!1,t=w.sourceTime??C;if(P.volume!==r||P.muted!==n)P.volume=r,P.muted=n,P.gainNode.gain.value=n?0:r*r;if(P.pan!==p)P.pan=p,P.panNode.pan.value=Math.max(-1,Math.min(1,p));if(Math.abs(t-P.currentSourceTime)>0.5&&P.iterator!==null)this.restartSourceIterator(P,t);P.currentSourceTime=t}for(let[w,k]of this.activeSources)if(!W.has(w)&&k.iterator!==null)this.stopSourceAudio(k)}async play(o=this.pauseTime){if(this.playing||this.disposed)return;if(this.audioContext.state==="suspended")await this.audioContext.resume();this.playbackId++,this.playing=!0,this.startContextTime=this.audioContext.currentTime,this.startMediaTime=o,this.pauseTime=o}startSourcePlayback(o,C){let W=this.activeSources.get(o);if(!W||W.iterator!==null)return;this.restartSourceIterator(W,C)}restartSourceIterator(o,C){this.stopSourceAudio(o),o.startSourceTime=C,o.currentSourceTime=C,o.iteratorStartTime=this.audioContext.currentTime,o.iterator=o.bufferSink.buffers(C),o.lastScheduledTime=C,this.scheduleSourceBuffers(o,this.playbackId)}async scheduleSourceBuffers(o,C){let W=o.iterator;if(!W)return;try{for await(let{buffer:w,timestamp:k}of W){if(C!==this.playbackId||this.disposed||!this.playing)break;let P=this.audioContext.createBufferSource();P.buffer=w,P.connect(o.gainNode);let r=k-o.startSourceTime,p=o.iteratorStartTime+r;if(p>=this.audioContext.currentTime)P.start(p);else{let E=this.audioContext.currentTime-p;if(E<w.duration)P.start(this.audioContext.currentTime,E);else continue}o.queuedNodes.add(P),P.onended=()=>{o.queuedNodes.delete(P)},o.lastScheduledTime=k;let n=this.audioContext.currentTime-o.iteratorStartTime;if(k-o.startSourceTime-n>1)await this.waitForCatchup(o,k)}}catch{}}async waitForCatchup(o,C){return new Promise((W)=>{let w=setInterval(()=>{if(!this.playing||this.disposed){clearInterval(w),W();return}let k=this.audioContext.currentTime-o.iteratorStartTime;if(C-o.startSourceTime-k<1)clearInterval(w),W()},100)})}pause(){if(!this.playing)return;this.pauseTime=this.getCurrentTime(),this.playing=!1;for(let o of this.activeSources.values())this.stopSourceAudio(o)}stop(){this.pause(),this.pauseTime=0,this.startContextTime=0,this.startMediaTime=0}async seek(o){let C=this.playing;if(this.pause(),this.pauseTime=o,this.startMediaTime=o,C)await this.play(o)}stopSourceAudio(o){for(let C of o.queuedNodes)try{C.stop()}catch{}if(o.queuedNodes.clear(),o.iterator)o.iterator.return(),o.iterator=null}getCurrentTime(){if(this.playing)return this.startMediaTime+(this.audioContext.currentTime-this.startContextTime);return this.pauseTime}setMasterVolume(o){this.masterVolume=Math.max(0,Math.min(1,o)),this.updateMasterGain()}setMasterMuted(o){this.masterMuted=o,this.updateMasterGain()}updateMasterGain(){let o=this.masterMuted?0:this.masterVolume;this.masterGain.gain.value=o*o}getAudioContext(){return this.audioContext}isPlaying(){return this.playing}dispose(){if(this.disposed)return;this.disposed=!0,this.playbackId++,this.stop();for(let o of this.activeSources.values())this.stopSourceAudio(o),o.gainNode.disconnect(),o.panNode.disconnect();if(this.activeSources.clear(),this.masterGain.disconnect(),this.audioContext.state!=="closed")this.audioContext.close()}}import{ALL_FORMATS as X,AudioBufferSink as Z,BlobSource as Y,BufferSource as j,CanvasSink as L,FilePathSource as A,Input as I,ReadableStreamSource as a,UrlSource as S}from"mediabunny";class b{cache=new Map;maxSize;constructor(o){this.maxSize=o}get(o){let C=this.cache.get(o);if(C!==void 0)this.cache.delete(o),this.cache.set(o,C);return C}set(o,C){if(this.cache.has(o))this.cache.delete(o);else if(this.cache.size>=this.maxSize){let W=this.cache.keys().next().value;if(W!==void 0)this.cache.delete(W)}this.cache.set(o,C)}clear(){this.cache.clear()}get size(){return this.cache.size}}class B{id;type="video";duration;width;height;data;disposed=!1;constructor(o,C,W,w,k){this.id=o,this.data=C,this.duration=W,this.width=w,this.height=k}async getFrameAt(o){if(this.disposed)return null;let C=this.data.frameIntervalMs,W=Math.floor(o*1000/C)*C,w=this.data.frameCache.get(W);if(w)return w.canvas;try{let k=await this.data.canvasSink.getCanvas(o);if(!k)return null;return this.data.frameCache.set(W,k),k.canvas}catch{return null}}getAudioBufferSink(){return this.data.audioBufferSink}hasAudio(){return this.data.audioBufferSink!==null}clearCache(){this.data.frameCache.clear()}dispose(){if(this.disposed)return;this.disposed=!0,this.data.frameCache.clear(),this.data.input.dispose()}}class K{id;type="image";duration=1/0;width;height;data;disposed=!1;constructor(o,C){this.id=o,this.data=C,this.width=C.image.width,this.height=C.image.height}async getFrameAt(o){if(this.disposed)return null;return this.data.image}dispose(){if(this.disposed)return;if(this.disposed=!0,"close"in this.data.image)this.data.image.close()}}class V{id;type="audio";duration;width=0;height=0;data;disposed=!1;constructor(o,C,W){this.id=o,this.data=C,this.duration=W}async getFrameAt(o){return null}getAudioBufferSink(){return this.data.audioBufferSink}dispose(){if(this.disposed)return;this.disposed=!0,this.data.input.dispose()}}class Q{sources=new Map;audioContext=null;nextId=0;constructor(o){this.audioContext=o??null}generateId(){return`source_${this.nextId++}`}async loadVideo(o,C={}){let W=C.id??this.generateId(),w=this.createInput(o),k=await w.getVideoTracks();if(k.length===0)throw w.dispose(),Error("Source has no video track");let P=k[0];if(!await P.canDecode())throw w.dispose(),Error(`Cannot decode video track with codec: ${P.codec}`);let p=new L(P,{poolSize:4}),n=await P.computeDuration(),t=30;try{let F=await P.computePacketStats(100);if(F.averagePacketRate>0)t=F.averagePacketRate}catch{}let E=1000/t,h=P.displayWidth*P.displayHeight,q=h>2073600?15:h>921600?30:60,g=null,M=null;try{let F=await w.getAudioTracks();if(F.length>0){if(g=F[0],await g.canDecode())M=new Z(g)}}catch{}let $=new B(W,{input:w,videoTrack:P,canvasSink:p,frameCache:new b(q),frameIntervalMs:E,audioTrack:g,audioBufferSink:M},n,P.displayWidth,P.displayHeight);return this.sources.set(W,$),$}async loadImage(o){let C=this.generateId(),W;if(typeof o!=="string")W=await createImageBitmap(o);else if(typeof Image>"u"){let k=await fetch(o);if(!k.ok)throw Error(`Failed to load image: ${o}`);let P=await k.blob();W=await createImageBitmap(P)}else W=await new Promise((k,P)=>{let r=new Image;r.onload=()=>k(r),r.onerror=()=>P(Error(`Failed to load image: ${o}`)),r.crossOrigin="anonymous",r.src=o});let w=new K(C,{image:W});return this.sources.set(C,w),w}async loadAudio(o,C={}){let W=C.id??this.generateId(),w=this.createInput(o),k=await w.getAudioTracks();if(k.length===0)throw w.dispose(),Error("Source has no audio track");let P=k[0];if(!await P.canDecode())throw w.dispose(),Error(`Cannot decode audio track with codec: ${P.codec}`);let p=await P.computeDuration(),n=new Z(P),t=new V(W,{input:w,audioTrack:P,audioBufferSink:n},p);return this.sources.set(W,t),t}createInput(o){let C;if(o instanceof File||o instanceof Blob)C=new Y(o);else if(o instanceof ArrayBuffer||o instanceof Uint8Array)C=new j(o);else if(typeof o==="string"||o instanceof URL){let W=o instanceof URL?o.href:o;if(typeof window>"u"&&!W.startsWith("http"))C=new A(W);else C=new S(W)}else if(typeof ReadableStream<"u"&&o instanceof ReadableStream)C=new a(o);else throw Error("Unsupported source type");return new I({source:C,formats:X})}getSource(o){return this.sources.get(o)}hasSource(o){return this.sources.has(o)}unloadSource(o){let C=this.sources.get(o);if(C)return C.dispose(),this.sources.delete(o),!0;return!1}getAllSources(){return Array.from(this.sources.values())}clear(){for(let o of this.sources.values())o.dispose();this.sources.clear()}dispose(){if(this.clear(),this.audioContext&&this.audioContext.state!=="closed")this.audioContext.close();this.audioContext=null}}class _{worker;nextId=1;pending=new Map;ready;constructor(o){let C=typeof o.worker==="boolean"?{}:o.worker??{},W=C.type??"module",w=C.url??new URL("./compositor-worker.js",import.meta.url);this.worker=new Worker(w,{type:W}),this.worker.onmessage=(r)=>{let{id:p,ok:n,result:t,error:E}=r.data,h=this.pending.get(p);if(!h)return;if(this.pending.delete(p),n)h.resolve(t);else h.reject(Error(E??"Worker error"))},this.worker.onerror=(r)=>{let p=r.error instanceof Error?r.error:Error("Worker error");for(let n of this.pending.values())n.reject(p);this.pending.clear()};let k=o.canvas.transferControlToOffscreen(),P={canvas:k,width:o.width,height:o.height,backgroundColor:o.backgroundColor};this.ready=this.call("init",P,[k])}postMessage(o,C,W){let w=this.nextId++;return this.worker.postMessage({id:w,kind:o,payload:C},W??[]),w}call(o,C,W){let w=this.postMessage(o,C,W);return new Promise((k,P)=>{this.pending.set(w,{resolve:k,reject:P})})}async loadSource(o,C){await this.ready;let W={source:o,options:C};return this.call("loadSource",W)}async loadImage(o){await this.ready;let C={source:o};return this.call("loadImage",C)}async loadAudio(o,C){await this.ready;let W={source:o,options:C};return this.call("loadAudio",W)}async unloadSource(o){await this.ready;let C={id:o};return this.call("unloadSource",C)}async render(o){await this.ready;let C={frame:o};return this.call("render",C)}async clear(){return await this.ready,this.call("clear")}async resize(o,C){await this.ready;let W={width:o,height:C};return this.call("resize",W)}async exportFrame(o,C){await this.ready;let W={frame:o,options:C};return this.call("exportFrame",W)}dispose(){try{this.worker.postMessage({id:this.nextId++,kind:"dispose"})}catch{}this.worker.terminate(),this.pending.clear()}}class D{canvas;ctx=null;width;height;backgroundColor;sourcePool;audioManager=null;workerClient=null;workerSources=new Map;workerAudioSources=new Map;emitter;state;animationFrameId=null;lastFrameTime=0;lastRenderTime=0;previewOptions=null;disposed=!1;renderBuffers={visibleLayers:[],framePromises:[],frameImages:[]};lastTimeUpdateEmit=0;timeUpdateThrottleMs=100;renderPending=!1;activeAudioSourceIds=new Set;audioScratch={nextActiveSourceIds:new Set,newSourceIds:[],newSourceTimes:[]};registeredAudioSources=new Set;constructor(o){this.canvas=o.canvas,this.width=o.width??(this.canvas.width||1920),this.height=o.height??(this.canvas.height||1080),this.backgroundColor=o.backgroundColor??"#000000",this.emitter=new O({maxListeners:50}),this.state={playing:!1,currentTime:0,duration:0,seeking:!1},this.canvas.width=this.width,this.canvas.height=this.height;let C=typeof o.worker==="boolean"?o.worker:o.worker?o.worker.enabled??!0:!1,W=C&&typeof Worker<"u"&&typeof OffscreenCanvas<"u"&&typeof this.canvas.transferControlToOffscreen==="function"&&!(this.canvas instanceof OffscreenCanvas);if(C&&!W)throw Error("Worker compositor requires HTMLCanvasElement, OffscreenCanvas, and Worker support");if(this.sourcePool=new Q,W)this.workerClient=new _({canvas:this.canvas,width:this.width,height:this.height,backgroundColor:this.backgroundColor,worker:o.worker??!0});if(o.enableAudio!==!1)this.audioManager=new J;if(!this.workerClient){if(this.ctx=this.canvas.getContext("2d",{alpha:!1,desynchronized:!0}),!this.ctx)throw Error("Failed to get 2D context for compositor canvas");this.clear()}}async loadSource(o,C){if(this.checkDisposed(),this.workerClient){let w=await this.workerClient.loadSource(o,C),k=this.createWorkerSource(w);if(this.audioManager&&w.hasAudio)await this.loadWorkerAudio(o,k.id);return this.emitter.emit("sourceloaded",{id:k.id,source:k}),k}let W=await this.sourcePool.loadVideo(o,C);return this.registerSourceAudio(W),this.emitter.emit("sourceloaded",{id:W.id,source:W}),W}async loadImage(o){if(this.checkDisposed(),this.workerClient){let W=await this.workerClient.loadImage(o),w=this.createWorkerSource(W);return this.emitter.emit("sourceloaded",{id:w.id,source:w}),w}let C=await this.sourcePool.loadImage(o);return this.emitter.emit("sourceloaded",{id:C.id,source:C}),C}async loadAudio(o,C){if(this.checkDisposed(),this.workerClient){let w=await this.workerClient.loadAudio(o,C),k=this.createWorkerSource(w);if(this.audioManager)await this.loadWorkerAudio(o,k.id);return this.emitter.emit("sourceloaded",{id:k.id,source:k}),k}let W=await this.sourcePool.loadAudio(o,C);return this.registerSourceAudio(W),this.emitter.emit("sourceloaded",{id:W.id,source:W}),W}unloadSource(o){if(this.workerClient){if(!this.workerSources.get(o))return!1;return this.workerClient.unloadSource(o),this.workerSources.delete(o),this.unloadWorkerAudio(o),this.emitter.emit("sourceunloaded",{id:o}),!0}if(this.registeredAudioSources.has(o))this.audioManager?.unregisterSource(o),this.registeredAudioSources.delete(o);let C=this.sourcePool.unloadSource(o);if(C)this.emitter.emit("sourceunloaded",{id:o});return C}registerSourceAudio(o){if(!this.audioManager)return;if(this.registeredAudioSources.has(o.id))return;let C=o.getAudioBufferSink?.();if(C)this.audioManager.registerSource(o,C),this.registeredAudioSources.add(o.id)}processAudioLayers(o,C){if(!this.audioManager)return;let W=this.audioScratch.newSourceIds,w=this.audioScratch.newSourceTimes,k=this.audioScratch.nextActiveSourceIds,P=this.activeAudioSourceIds;W.length=0,w.length=0,k.clear();for(let r=0;r<o.length;r++){let p=o[r];if(p.muted)continue;let n=p.source.id;if(!this.audioManager.hasSource(n))continue;if(k.add(n),!P.has(n))W.push(n),w.push(p.sourceTime??C)}if(P.size>0)P.clear();for(let r of k)P.add(r);this.audioManager.processAudioLayers(o,C);for(let r=0;r<W.length;r++)this.audioManager.startSourcePlayback(W[r],w[r])}getSource(o){if(this.workerClient)return this.workerSources.get(o);return this.sourcePool.getSource(o)}getAllSources(){if(this.workerClient)return Array.from(this.workerSources.values());return this.sourcePool.getAllSources()}async render(o){if(this.checkDisposed(),this.workerClient){let t=this.serializeWorkerFrame(o);return this.workerClient.render(t)}let C=this.ctx;if(!C)return!1;let{visibleLayers:W,framePromises:w,frameImages:k}=this.renderBuffers;W.length=0,w.length=0,k.length=0;let P=!1,r=-1/0,p=o.layers;for(let t=0;t<p.length;t++){let E=p[t];if(E.visible===!1)continue;let h=E.zIndex??0;if(h<r)P=!0;r=h,W.push(E)}if(W.length===0)return C.fillStyle=this.backgroundColor,C.fillRect(0,0,this.width,this.height),!0;if(P)W.sort((t,E)=>(t.zIndex??0)-(E.zIndex??0));for(let t=0;t<W.length;t++){let E=W[t],h=E.sourceTime??o.time;w[t]=E.source.getFrameAt(h)}let n=await Promise.all(w);for(let t=0;t<n.length;t++)k[t]=n[t]??null;C.fillStyle=this.backgroundColor,C.fillRect(0,0,this.width,this.height);for(let t=0;t<W.length;t++){let E=k[t];if(E)this.renderLayer(E,W[t])}return!0}renderLayer(o,C){let W=this.ctx;if(!W)return;let w=C.transform,k=C.source.width??this.width,P=C.source.height??this.height;if(!w){W.drawImage(o,0,0,k,P);return}let r=w.width??k,p=w.height??P,n=w.x??0,t=w.y??0,E=w.rotation??0,h=w.scaleX??1,q=w.scaleY??1,g=w.opacity??1,M=g!==1;if(!M&&!(E!==0||h!==1||q!==1)){W.drawImage(o,n,t,r,p);return}let F=w.anchorX??0.5,l=w.anchorY??0.5;if(W.save(),M)W.globalAlpha=g;if(W.translate(n+r*F,t+p*l),E!==0)W.rotate(E*Math.PI/180);if(h!==1||q!==1)W.scale(h,q);W.drawImage(o,-r*F,-p*l,r,p),W.restore()}createWorkerSource(o){let C={id:o.id,type:o.type,duration:o.duration,width:o.width,height:o.height,async getFrameAt(){throw Error("getFrameAt is not available when worker rendering is enabled")},getAudioBufferSink(){return null},hasAudio(){return o.hasAudio??!1},dispose(){}};return this.workerSources.set(C.id,C),C}async loadWorkerAudio(o,C){if(!this.audioManager)return;if(this.workerAudioSources.has(C))this.unloadWorkerAudio(C);try{let W=await this.sourcePool.loadAudio(o,{id:C});this.workerAudioSources.set(C,W),this.registerSourceAudio(W)}catch{}}unloadWorkerAudio(o){if(!this.audioManager)return;if(this.workerAudioSources.has(o))this.audioManager.unregisterSource(o),this.registeredAudioSources.delete(o),this.sourcePool.unloadSource(o),this.workerAudioSources.delete(o)}serializeWorkerFrame(o){if(!this.workerClient)throw Error("Worker compositor not initialized");let C=o.layers,W=Array(C.length);for(let w=0;w<C.length;w++){let k=C[w],P=k.source.id;if(!this.workerSources.has(P))throw Error(`Layer source ${P} is not managed by this compositor`);W[w]={sourceId:P,sourceTime:k.sourceTime,transform:k.transform,visible:k.visible,zIndex:k.zIndex}}return{time:o.time,layers:W}}clear(){if(this.workerClient){this.workerClient.clear();return}if(!this.ctx)return;this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,0,this.width,this.height)}preview(o){this.checkDisposed(),this.previewOptions=o,this.state.duration=o.duration,this.lastRenderTime=0,this.emitter.emit("compositionchange",void 0)}async play(){if(this.checkDisposed(),this.state.playing)return;if(!this.previewOptions)throw Error("No preview configured. Call preview() first.");if(this.state.playing=!0,this.lastFrameTime=performance.now(),this.lastRenderTime=this.lastFrameTime,this.emitter.emit("play",void 0),this.audioManager)await this.audioManager.play(this.state.currentTime);this.startRenderLoop()}pause(){if(this.checkDisposed(),!this.state.playing)return;if(this.state.playing=!1,this.stopRenderLoop(),this.audioManager)this.audioManager.pause();this.emitter.emit("pause",void 0)}async seek(o){if(this.checkDisposed(),!this.previewOptions)return;let C=Math.max(0,Math.min(o,this.state.duration));if(this.state.seeking=!0,this.emitter.emit("seeking",{time:C}),this.state.currentTime=C,this.audioManager)await this.audioManager.seek(C);let W=this.previewOptions.getComposition(C);await this.render(W),this.state.seeking=!1,this.emitter.emit("seeked",{time:C}),this.emitter.emit("timeupdate",{currentTime:C})}startRenderLoop(){if(this.animationFrameId!==null)return;let o=()=>{if(!this.state.playing||!this.previewOptions)return;this.animationFrameId=requestAnimationFrame(o);let C=performance.now(),W=(C-this.lastFrameTime)/1000;if(this.lastFrameTime=C,this.state.currentTime+=W,this.state.currentTime>=this.state.duration)if(this.previewOptions.loop)this.state.currentTime=0;else{this.state.currentTime=this.state.duration,this.pause(),this.emitter.emit("ended",void 0);return}let w=this.previewOptions.fps??0,k=w>0?1000/w:0;if(!this.renderPending&&(k===0||C-this.lastRenderTime>=k)){this.renderPending=!0,this.lastRenderTime=C;let r=this.previewOptions.getComposition(this.state.currentTime);if(this.audioManager)this.processAudioLayers(r.audio??[],this.state.currentTime);this.render(r).catch(()=>{}).finally(()=>{this.renderPending=!1})}if(C-this.lastTimeUpdateEmit>=this.timeUpdateThrottleMs)this.lastTimeUpdateEmit=C,this.emitter.emit("timeupdate",{currentTime:this.state.currentTime})};this.animationFrameId=requestAnimationFrame(o)}stopRenderLoop(){if(this.animationFrameId!==null)cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null}async exportFrame(o,C={}){if(this.checkDisposed(),!this.previewOptions)return null;let W=this.previewOptions.getComposition(o);if(this.workerClient){let w=this.serializeWorkerFrame(W);return this.workerClient.exportFrame(w,C)}if(await this.render(W),"toBlob"in this.canvas)return new Promise((w)=>{this.canvas.toBlob((k)=>w(k),`image/${C.format??"png"}`,C.quality)});else return this.canvas.convertToBlob({type:`image/${C.format??"png"}`,quality:C.quality})}get currentTime(){return this.state.currentTime}get duration(){return this.state.duration}get playing(){return this.state.playing}get paused(){return!this.state.playing}get seeking(){return this.state.seeking}getWidth(){return this.width}getHeight(){return this.height}resize(o,C){if(this.checkDisposed(),this.width=o,this.height=C,this.canvas.width=o,this.canvas.height=C,this.workerClient){this.workerClient.resize(o,C);return}this.clear()}on(o,C){return this.emitter.on(o,C)}once(o,C){return this.emitter.once(o,C)}off(o,C){this.emitter.off(o,C)}setVolume(o){this.audioManager?.setMasterVolume(o)}setMuted(o){this.audioManager?.setMasterMuted(o)}getAudioContext(){if(!this.audioManager)throw Error("Audio is disabled for this compositor");return this.audioManager.getAudioContext()}checkDisposed(){if(this.disposed)throw Error("Compositor has been disposed")}dispose(){if(this.disposed)return;this.disposed=!0,this.stopRenderLoop(),this.audioManager?.dispose(),this.workerClient?.dispose(),this.workerClient=null,this.sourcePool.dispose(),this.registeredAudioSources.clear(),this.activeAudioSourceIds.clear(),this.audioScratch.nextActiveSourceIds.clear(),this.audioScratch.newSourceIds.length=0,this.audioScratch.newSourceTimes.length=0,this.workerSources.clear(),this.workerAudioSources.clear(),this.emitter.removeAllListeners(),this.ctx=null,this.previewOptions=null}}var H=self,R=null,U=null,G=(o)=>({id:o.id,type:o.type,duration:o.duration,width:o.width,height:o.height,hasAudio:o.type==="audio"?!0:o.hasAudio?o.hasAudio():!1}),y=(o)=>{if(!R)throw Error("Compositor not initialized");let C=Array(o.layers.length);for(let W=0;W<o.layers.length;W++){let w=o.layers[W],k=R.getSource(w.sourceId);if(!k)throw Error(`Unknown source: ${w.sourceId}`);C[W]={source:k,sourceTime:w.sourceTime,transform:w.transform,visible:w.visible,zIndex:w.zIndex}}return{time:o.time,layers:C}},z=(o,C)=>{H.postMessage(o,C??[])};H.onmessage=async(o)=>{let{id:C,kind:W,payload:w}=o.data;try{switch(W){case"init":{let k=w;U=k.canvas,R=new D({canvas:U,width:k.width,height:k.height,backgroundColor:k.backgroundColor,enableAudio:!1}),z({id:C,ok:!0});return}case"loadSource":{let{source:k,options:P}=w;if(!R)throw Error("Compositor not initialized");let r=await R.loadSource(k,P);z({id:C,ok:!0,result:G(r)});return}case"loadImage":{let{source:k}=w;if(!R)throw Error("Compositor not initialized");let P=await R.loadImage(k);z({id:C,ok:!0,result:G(P)});return}case"loadAudio":{let{source:k,options:P}=w;if(!R)throw Error("Compositor not initialized");let r=await R.loadAudio(k,P);z({id:C,ok:!0,result:G(r)});return}case"unloadSource":{if(!R)throw Error("Compositor not initialized");let{id:k}=w,P=R.unloadSource(k);z({id:C,ok:!0,result:P});return}case"render":{if(!R)throw Error("Compositor not initialized");let{frame:k}=w,P=y(k),r=await R.render(P);z({id:C,ok:!0,result:r});return}case"clear":{if(!R)throw Error("Compositor not initialized");R.clear(),z({id:C,ok:!0,result:!0});return}case"resize":{if(!R)throw Error("Compositor not initialized");let{width:k,height:P}=w;R.resize(k,P),z({id:C,ok:!0,result:!0});return}case"exportFrame":{if(!R||!U)throw Error("Compositor not initialized");let{frame:k,options:P}=w,r=y(k);await R.render(r);let p=`image/${P?.format??"png"}`,n=await U.convertToBlob({type:p,quality:P?.quality});z({id:C,ok:!0,result:n});return}case"dispose":{R?.dispose(),R=null,U=null,z({id:C,ok:!0,result:!0});return}default:throw Error(`Unknown worker command: ${W}`)}}catch(k){let P=k instanceof Error?k.message:"Worker error";z({id:C,ok:!1,error:P})}};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { AttachedImage, AudioCodec, AudioSample, EncodedPacket, InputFormat, MetadataTags, OutputFormat, Quality, SubtitleCodec, VideoCodec, VideoSample, } from 'mediabunny';
|
|
2
|
-
export type { AudioLayer, CompositionFrame, CompositionProvider, CompositorEventListener, CompositorEventMap, CompositorLayer, CompositorOptions, CompositorRendererType, CompositorSource, CompositorSourceOptions, FrameExportOptions, LayerTransform, PreviewOptions, SourceType, } from './compositor';
|
|
2
|
+
export type { AudioLayer, CompositionFrame, CompositionProvider, CompositorEventListener, CompositorEventMap, CompositorLayer, CompositorOptions, CompositorRendererType, CompositorSource, CompositorSourceOptions, CompositorWorkerOptions, FrameExportOptions, LayerTransform, PreviewOptions, SourceType, } from './compositor';
|
|
3
3
|
export { Compositor, SourcePool } from './compositor';
|
|
4
4
|
export { EventEmitter } from './events/emitter';
|
|
5
5
|
export type { TypedEventEmitter, UnsubscribeFn } from './events/types';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,GACX,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,YAAY,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,YAAY,EACV,cAAc,EACd,WAAW,EACX,QAAQ,EACR,WAAW,EACX,SAAS,EAET,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EAEf,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,EACL,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAGtB,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,eAAe,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,GACX,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,YAAY,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,YAAY,EACV,cAAc,EACd,WAAW,EACX,QAAQ,EACR,WAAW,EACX,SAAS,EAET,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EAEf,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,EACL,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAGtB,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,eAAe,QAAQ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class f{events=new Map;maxListeners;captureRejections;emitCache=[];constructor(O={}){this.maxListeners=O.maxListeners??10,this.captureRejections=O.captureRejections??!1}on(O,$){if(!this.events.has(O))this.events.set(O,new Set);let A=this.events.get(O);if(!A)return()=>{};if(A.size>=this.maxListeners)console.warn(`MaxListenersExceededWarning: Possible EventEmitter memory leak detected. ${A.size} ${String(O)} listeners added. Use emitter.setMaxListeners() to increase limit`);let Q=$;return A.add(Q),()=>{A.delete(Q)}}once(O,$){let A=(Q)=>{this.off(O,A),$(Q)};return this.on(O,A)}off(O,$){let A=this.events.get(O);if(!A)return;if($){let Q=$;A.delete(Q)}else A.clear()}emit(O,$){let A=this.events.get(O);if(!A||A.size===0)return;let Q=this.emitCache;Q.length=0;for(let V of A)Q.push(V);for(let V=0;V<Q.length;V++){let J=Q[V];try{let K=J($);if(this.captureRejections&&NO(K))this.handlePromiseRejection(K)}catch(K){if(this.captureRejections&&this.events.has("error"))this.emit("error",K);else throw K}}}handlePromiseRejection(O){O.catch(($)=>{if(this.events.has("error"))this.emit("error",$);else throw $})}removeAllListeners(O){if(O)this.events.delete(O);else this.events.clear()}setMaxListeners(O){this.maxListeners=O}getMaxListeners(){return this.maxListeners}listeners(O){let $=this.events.get(O);return $?Array.from($):[]}listenerCount(O){let $=this.events.get(O);return $?$.size:0}eventNames(){return Array.from(this.events.keys())}}function NO(O){if(!O||typeof O!=="object"&&typeof O!=="function")return!1;let $=O;return typeof $.then==="function"&&typeof $.catch==="function"}class n{audioContext;masterGain;activeSources=new Map;playing=!1;disposed=!1;playbackId=0;startContextTime=0;startMediaTime=0;pauseTime=0;masterVolume=1;masterMuted=!1;constructor(O={}){if(O.audioContext)this.audioContext=O.audioContext;else{let $=globalThis,A=$.AudioContext||$.webkitAudioContext;if(!A)throw Error("AudioContext is not supported in this environment");this.audioContext=new A}this.masterGain=this.audioContext.createGain(),this.masterGain.connect(this.audioContext.destination)}registerSource(O,$){if(this.disposed)return;let A=this.audioContext.createGain(),Q=this.audioContext.createStereoPanner();A.connect(Q),Q.connect(this.masterGain),this.activeSources.set(O.id,{sourceId:O.id,bufferSink:$,iterator:null,gainNode:A,panNode:Q,queuedNodes:new Set,volume:1,pan:0,muted:!1,startSourceTime:0,currentSourceTime:0,iteratorStartTime:0,lastScheduledTime:0})}unregisterSource(O){let $=this.activeSources.get(O);if(!$)return;this.stopSourceAudio($),$.gainNode.disconnect(),$.panNode.disconnect(),this.activeSources.delete(O)}hasSource(O){return this.activeSources.has(O)}processAudioLayers(O,$){if(this.disposed||!this.playing)return;let A=new Set;for(let Q of O){let V=Q.source.id;A.add(V);let J=this.activeSources.get(V);if(!J)continue;let K=Q.volume??1,Z=Q.pan??0,G=Q.muted??!1,j=Q.sourceTime??$;if(J.volume!==K||J.muted!==G)J.volume=K,J.muted=G,J.gainNode.gain.value=G?0:K*K;if(J.pan!==Z)J.pan=Z,J.panNode.pan.value=Math.max(-1,Math.min(1,Z));if(Math.abs(j-J.currentSourceTime)>0.5&&J.iterator!==null)this.restartSourceIterator(J,j);J.currentSourceTime=j}for(let[Q,V]of this.activeSources)if(!A.has(Q)&&V.iterator!==null)this.stopSourceAudio(V)}async play(O=this.pauseTime){if(this.playing||this.disposed)return;if(this.audioContext.state==="suspended")await this.audioContext.resume();this.playbackId++,this.playing=!0,this.startContextTime=this.audioContext.currentTime,this.startMediaTime=O,this.pauseTime=O}startSourcePlayback(O,$){let A=this.activeSources.get(O);if(!A||A.iterator!==null)return;this.restartSourceIterator(A,$)}restartSourceIterator(O,$){this.stopSourceAudio(O),O.startSourceTime=$,O.currentSourceTime=$,O.iteratorStartTime=this.audioContext.currentTime,O.iterator=O.bufferSink.buffers($),O.lastScheduledTime=$,this.scheduleSourceBuffers(O,this.playbackId)}async scheduleSourceBuffers(O,$){let A=O.iterator;if(!A)return;try{for await(let{buffer:Q,timestamp:V}of A){if($!==this.playbackId||this.disposed||!this.playing)break;let J=this.audioContext.createBufferSource();J.buffer=Q,J.connect(O.gainNode);let K=V-O.startSourceTime,Z=O.iteratorStartTime+K;if(Z>=this.audioContext.currentTime)J.start(Z);else{let U=this.audioContext.currentTime-Z;if(U<Q.duration)J.start(this.audioContext.currentTime,U);else continue}O.queuedNodes.add(J),J.onended=()=>{O.queuedNodes.delete(J)},O.lastScheduledTime=V;let G=this.audioContext.currentTime-O.iteratorStartTime;if(V-O.startSourceTime-G>1)await this.waitForCatchup(O,V)}}catch{}}async waitForCatchup(O,$){return new Promise((A)=>{let Q=setInterval(()=>{if(!this.playing||this.disposed){clearInterval(Q),A();return}let V=this.audioContext.currentTime-O.iteratorStartTime;if($-O.startSourceTime-V<1)clearInterval(Q),A()},100)})}pause(){if(!this.playing)return;this.pauseTime=this.getCurrentTime(),this.playing=!1;for(let O of this.activeSources.values())this.stopSourceAudio(O)}stop(){this.pause(),this.pauseTime=0,this.startContextTime=0,this.startMediaTime=0}async seek(O){let $=this.playing;if(this.pause(),this.pauseTime=O,this.startMediaTime=O,$)await this.play(O)}stopSourceAudio(O){for(let $ of O.queuedNodes)try{$.stop()}catch{}if(O.queuedNodes.clear(),O.iterator)O.iterator.return(),O.iterator=null}getCurrentTime(){if(this.playing)return this.startMediaTime+(this.audioContext.currentTime-this.startContextTime);return this.pauseTime}setMasterVolume(O){this.masterVolume=Math.max(0,Math.min(1,O)),this.updateMasterGain()}setMasterMuted(O){this.masterMuted=O,this.updateMasterGain()}updateMasterGain(){let O=this.masterMuted?0:this.masterVolume;this.masterGain.gain.value=O*O}getAudioContext(){return this.audioContext}isPlaying(){return this.playing}dispose(){if(this.disposed)return;this.disposed=!0,this.playbackId++,this.stop();for(let O of this.activeSources.values())this.stopSourceAudio(O),O.gainNode.disconnect(),O.panNode.disconnect();if(this.activeSources.clear(),this.masterGain.disconnect(),this.audioContext.state!=="closed")this.audioContext.close()}}import{ALL_FORMATS as _O,AudioBufferSink as JO,BlobSource as DO,BufferSource as qO,CanvasSink as MO,FilePathSource as EO,Input as PO,ReadableStreamSource as RO,UrlSource as FO}from"mediabunny";class KO{cache=new Map;maxSize;constructor(O){this.maxSize=O}get(O){let $=this.cache.get(O);if($!==void 0)this.cache.delete(O),this.cache.set(O,$);return $}set(O,$){if(this.cache.has(O))this.cache.delete(O);else if(this.cache.size>=this.maxSize){let A=this.cache.keys().next().value;if(A!==void 0)this.cache.delete(A)}this.cache.set(O,$)}clear(){this.cache.clear()}get size(){return this.cache.size}}class ZO{id;type="video";duration;width;height;data;disposed=!1;constructor(O,$,A,Q,V){this.id=O,this.data=$,this.duration=A,this.width=Q,this.height=V}async getFrameAt(O){if(this.disposed)return null;let $=this.data.frameIntervalMs,A=Math.floor(O*1000/$)*$,Q=this.data.frameCache.get(A);if(Q)return Q.canvas;try{let V=await this.data.canvasSink.getCanvas(O);if(!V)return null;return this.data.frameCache.set(A,V),V.canvas}catch{return null}}getAudioBufferSink(){return this.data.audioBufferSink}hasAudio(){return this.data.audioBufferSink!==null}clearCache(){this.data.frameCache.clear()}dispose(){if(this.disposed)return;this.disposed=!0,this.data.frameCache.clear(),this.data.input.dispose()}}class jO{id;type="image";duration=1/0;width;height;data;disposed=!1;constructor(O,$){this.id=O,this.data=$,this.width=$.image.width,this.height=$.image.height}async getFrameAt(O){if(this.disposed)return null;return this.data.image}dispose(){if(this.disposed)return;if(this.disposed=!0,"close"in this.data.image)this.data.image.close()}}class GO{id;type="audio";duration;width=0;height=0;data;disposed=!1;constructor(O,$,A){this.id=O,this.data=$,this.duration=A}async getFrameAt(O){return null}getAudioBufferSink(){return this.data.audioBufferSink}dispose(){if(this.disposed)return;this.disposed=!0,this.data.input.dispose()}}class y{sources=new Map;audioContext=null;nextId=0;constructor(O){this.audioContext=O??null}generateId(){return`source_${this.nextId++}`}async loadVideo(O,$={}){let A=$.id??this.generateId(),Q=this.createInput(O),V=await Q.getVideoTracks();if(V.length===0)throw Q.dispose(),Error("Source has no video track");let J=V[0];if(!await J.canDecode())throw Q.dispose(),Error(`Cannot decode video track with codec: ${J.codec}`);let Z=new MO(J,{poolSize:4}),G=await J.computeDuration(),j=30;try{let L=await J.computePacketStats(100);if(L.averagePacketRate>0)j=L.averagePacketRate}catch{}let U=1000/j,X=J.displayWidth*J.displayHeight,z=X>2073600?15:X>921600?30:60,D=null,q=null;try{let L=await Q.getAudioTracks();if(L.length>0){if(D=L[0],await D.canDecode())q=new JO(D)}}catch{}let M=new ZO(A,{input:Q,videoTrack:J,canvasSink:Z,frameCache:new KO(z),frameIntervalMs:U,audioTrack:D,audioBufferSink:q},G,J.displayWidth,J.displayHeight);return this.sources.set(A,M),M}async loadImage(O){let $=this.generateId(),A;if(typeof O!=="string")A=await createImageBitmap(O);else A=await new Promise((V,J)=>{let K=new Image;K.onload=()=>V(K),K.onerror=()=>J(Error(`Failed to load image: ${O}`)),K.crossOrigin="anonymous",K.src=O});let Q=new jO($,{image:A});return this.sources.set($,Q),Q}async loadAudio(O,$={}){let A=$.id??this.generateId(),Q=this.createInput(O),V=await Q.getAudioTracks();if(V.length===0)throw Q.dispose(),Error("Source has no audio track");let J=V[0];if(!await J.canDecode())throw Q.dispose(),Error(`Cannot decode audio track with codec: ${J.codec}`);let Z=await J.computeDuration(),G=new JO(J),j=new GO(A,{input:Q,audioTrack:J,audioBufferSink:G},Z);return this.sources.set(A,j),j}createInput(O){let $;if(O instanceof File||O instanceof Blob)$=new DO(O);else if(O instanceof ArrayBuffer||O instanceof Uint8Array)$=new qO(O);else if(typeof O==="string"||O instanceof URL){let A=O instanceof URL?O.href:O;if(typeof window>"u"&&!A.startsWith("http"))$=new EO(A);else $=new FO(A)}else if(typeof ReadableStream<"u"&&O instanceof ReadableStream)$=new RO(O);else throw Error("Unsupported source type");return new PO({source:$,formats:_O})}getSource(O){return this.sources.get(O)}hasSource(O){return this.sources.has(O)}unloadSource(O){let $=this.sources.get(O);if($)return $.dispose(),this.sources.delete(O),!0;return!1}getAllSources(){return Array.from(this.sources.values())}clear(){for(let O of this.sources.values())O.dispose();this.sources.clear()}dispose(){if(this.clear(),this.audioContext&&this.audioContext.state!=="closed")this.audioContext.close();this.audioContext=null}}class i{canvas;ctx=null;width;height;backgroundColor;sourcePool;audioManager;emitter;state;animationFrameId=null;lastFrameTime=0;previewOptions=null;disposed=!1;renderBuffers={frameData:[],visibleLayers:[]};lastTimeUpdateEmit=0;timeUpdateThrottleMs=100;renderPending=!1;activeAudioLayers=[];registeredAudioSources=new Set;constructor(O){if(this.canvas=O.canvas,this.width=O.width??(this.canvas.width||1920),this.height=O.height??(this.canvas.height||1080),this.backgroundColor=O.backgroundColor??"#000000",this.sourcePool=new y,this.audioManager=new n,this.emitter=new f({maxListeners:50}),this.state={playing:!1,currentTime:0,duration:0,seeking:!1},this.canvas.width=this.width,this.canvas.height=this.height,this.ctx=this.canvas.getContext("2d",{alpha:!1,desynchronized:!0}),!this.ctx)throw Error("Failed to get 2D context for compositor canvas");this.clear()}async loadSource(O,$){this.checkDisposed();let A=await this.sourcePool.loadVideo(O,$);return this.registerSourceAudio(A),this.emitter.emit("sourceloaded",{id:A.id,source:A}),A}async loadImage(O){this.checkDisposed();let $=await this.sourcePool.loadImage(O);return this.emitter.emit("sourceloaded",{id:$.id,source:$}),$}async loadAudio(O,$){this.checkDisposed();let A=await this.sourcePool.loadAudio(O,$);return this.registerSourceAudio(A),this.emitter.emit("sourceloaded",{id:A.id,source:A}),A}unloadSource(O){if(this.registeredAudioSources.has(O))this.audioManager.unregisterSource(O),this.registeredAudioSources.delete(O);let $=this.sourcePool.unloadSource(O);if($)this.emitter.emit("sourceunloaded",{id:O});return $}registerSourceAudio(O){if(this.registeredAudioSources.has(O.id))return;let $=O.getAudioBufferSink?.();if($)this.audioManager.registerSource(O,$),this.registeredAudioSources.add(O.id)}processAudioLayers(O,$){let A=[];for(let Q of O){if(Q.muted)continue;let V=Q.source.id;if(!this.audioManager.hasSource(V))continue;if(!this.activeAudioLayers.some((K)=>K.source.id===V))A.push(V)}this.activeAudioLayers=O,this.audioManager.processAudioLayers(O,$);for(let Q of A){let V=O.find((J)=>J.source.id===Q);if(V){let J=V.sourceTime??$;this.audioManager.startSourcePlayback(Q,J)}}}getSource(O){return this.sourcePool.getSource(O)}getAllSources(){return this.sourcePool.getAllSources()}async render(O){if(this.checkDisposed(),!this.ctx)return!1;let{frameData:$,visibleLayers:A}=this.renderBuffers;$.length=0,A.length=0;for(let V=0;V<O.layers.length;V++){let J=O.layers[V];if(J.visible!==!1)A.push(J)}A.sort((V,J)=>(V.zIndex??0)-(J.zIndex??0));let Q=[];for(let V=0;V<A.length;V++){let J=A[V],K=V;Q.push((async()=>{let Z=J.sourceTime??O.time,G=await J.source.getFrameAt(Z);if(G)$[K]={layer:J,image:G}})())}await Promise.all(Q),this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,0,this.width,this.height);for(let V=0;V<$.length;V++){let J=$[V];if(J)this.renderLayer(J.image,J.layer)}return!0}renderLayer(O,$){if(!this.ctx)return;let A=$.transform,Q=$.source.width??this.width,V=$.source.height??this.height;if(!A){this.ctx.drawImage(O,0,0,Q,V);return}let J=A.width??Q,K=A.height??V,Z=A.x??0,G=A.y??0,j=A.rotation??0,U=A.scaleX??1,X=A.scaleY??1,z=A.opacity??1,D=z!==1;if(!D&&!(j!==0||U!==1||X!==1)){this.ctx.drawImage(O,Z,G,J,K);return}let M=A.anchorX??0.5,L=A.anchorY??0.5;if(this.ctx.save(),D)this.ctx.globalAlpha=z;if(this.ctx.translate(Z+J*M,G+K*L),j!==0)this.ctx.rotate(j*Math.PI/180);if(U!==1||X!==1)this.ctx.scale(U,X);this.ctx.drawImage(O,-J*M,-K*L,J,K),this.ctx.restore()}clear(){if(!this.ctx)return;this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,0,this.width,this.height)}preview(O){this.checkDisposed(),this.previewOptions=O,this.state.duration=O.duration,this.emitter.emit("compositionchange",void 0)}async play(){if(this.checkDisposed(),this.state.playing)return;if(!this.previewOptions)throw Error("No preview configured. Call preview() first.");this.state.playing=!0,this.lastFrameTime=performance.now(),this.emitter.emit("play",void 0),await this.audioManager.play(this.state.currentTime),this.startRenderLoop()}pause(){if(this.checkDisposed(),!this.state.playing)return;this.state.playing=!1,this.stopRenderLoop(),this.audioManager.pause(),this.emitter.emit("pause",void 0)}async seek(O){if(this.checkDisposed(),!this.previewOptions)return;let $=Math.max(0,Math.min(O,this.state.duration));this.state.seeking=!0,this.emitter.emit("seeking",{time:$}),this.state.currentTime=$,await this.audioManager.seek($);let A=this.previewOptions.getComposition($);await this.render(A),this.state.seeking=!1,this.emitter.emit("seeked",{time:$}),this.emitter.emit("timeupdate",{currentTime:$})}startRenderLoop(){if(this.animationFrameId!==null)return;let O=()=>{if(!this.state.playing||!this.previewOptions)return;this.animationFrameId=requestAnimationFrame(O);let $=performance.now(),A=($-this.lastFrameTime)/1000;if(this.lastFrameTime=$,this.state.currentTime+=A,this.state.currentTime>=this.state.duration)if(this.previewOptions.loop)this.state.currentTime=0;else{this.state.currentTime=this.state.duration,this.pause(),this.emitter.emit("ended",void 0);return}if(this.renderPending)return;this.renderPending=!0;let Q=this.previewOptions.getComposition(this.state.currentTime);if(this.processAudioLayers(Q.audio??[],this.state.currentTime),this.render(Q).catch(()=>{}).finally(()=>{this.renderPending=!1}),$-this.lastTimeUpdateEmit>=this.timeUpdateThrottleMs)this.lastTimeUpdateEmit=$,this.emitter.emit("timeupdate",{currentTime:this.state.currentTime})};this.animationFrameId=requestAnimationFrame(O)}stopRenderLoop(){if(this.animationFrameId!==null)cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null}async exportFrame(O,$={}){if(this.checkDisposed(),!this.previewOptions)return null;let A=this.previewOptions.getComposition(O);if(await this.render(A),"toBlob"in this.canvas)return new Promise((Q)=>{this.canvas.toBlob((V)=>Q(V),`image/${$.format??"png"}`,$.quality)});else return this.canvas.convertToBlob({type:`image/${$.format??"png"}`,quality:$.quality})}get currentTime(){return this.state.currentTime}get duration(){return this.state.duration}get playing(){return this.state.playing}get paused(){return!this.state.playing}get seeking(){return this.state.seeking}getWidth(){return this.width}getHeight(){return this.height}resize(O,$){this.checkDisposed(),this.width=O,this.height=$,this.canvas.width=O,this.canvas.height=$,this.clear()}on(O,$){return this.emitter.on(O,$)}once(O,$){return this.emitter.once(O,$)}off(O,$){this.emitter.off(O,$)}setVolume(O){this.audioManager.setMasterVolume(O)}setMuted(O){this.audioManager.setMasterMuted(O)}getAudioContext(){return this.audioManager.getAudioContext()}checkDisposed(){if(this.disposed)throw Error("Compositor has been disposed")}dispose(){if(this.disposed)return;this.disposed=!0,this.stopRenderLoop(),this.audioManager.dispose(),this.sourcePool.dispose(),this.registeredAudioSources.clear(),this.activeAudioLayers=[],this.emitter.removeAllListeners(),this.ctx=null,this.previewOptions=null}}import{CanvasSink as SO,VideoSampleSink as HO}from"mediabunny";class W{canvas;ctx=null;isInitialized=!1;rotation=0;constructor(O){this.canvas=O.canvas,this.rotation=O.rotation??0,this.initialize()}initialize(){try{if(this.ctx=this.canvas.getContext("2d",{alpha:!1,desynchronized:!0}),!this.ctx)return!1;return this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.isInitialized=!0,!0}catch{return!1}}isReady(){return this.isInitialized&&this.ctx!==null}render(O){if(!this.isReady()||!this.ctx)return!1;try{let{width:$,height:A}=O;if($===0||A===0)return!1;let Q=this.canvas.width,V=this.canvas.height;if(Q===0||V===0)return!1;let J=this.rotation===90||this.rotation===270,K=J?A:$,Z=J?$:A,G=Math.min(Q/K,V/Z),j=Math.round(K*G),U=Math.round(Z*G),X=Math.round((Q-j)/2),z=Math.round((V-U)/2);if(this.ctx.fillStyle="black",this.ctx.fillRect(0,0,Q,V),this.ctx.save(),this.ctx.translate(X+j/2,z+U/2),this.rotation!==0)this.ctx.rotate(this.rotation*Math.PI/180);if(J)this.ctx.drawImage(O,0,0,$,A,-U/2,-j/2,U,j);else this.ctx.drawImage(O,0,0,$,A,-j/2,-U/2,j,U);return this.ctx.restore(),!0}catch{return!1}}clear(){if(!this.isReady()||!this.ctx)return;this.ctx.fillStyle="black",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}setRotation(O){this.rotation=O}getRotation(){return this.rotation}dispose(){this.ctx=null,this.isInitialized=!1}}class s{resources;isInitialized=!1;canvas;textureWidth=0;textureHeight=0;options;boundHandleContextLost=null;boundHandleContextRestored=null;rotation=0;positionsArray=new Float32Array(8);vertexShaderSource=`
|
|
1
|
+
class y{events=new Map;maxListeners;captureRejections;emitCache=[];constructor(O={}){this.maxListeners=O.maxListeners??10,this.captureRejections=O.captureRejections??!1}on(O,$){if(!this.events.has(O))this.events.set(O,new Set);let A=this.events.get(O);if(!A)return()=>{};if(A.size>=this.maxListeners)console.warn(`MaxListenersExceededWarning: Possible EventEmitter memory leak detected. ${A.size} ${String(O)} listeners added. Use emitter.setMaxListeners() to increase limit`);let j=$;return A.add(j),()=>{A.delete(j)}}once(O,$){let A=(j)=>{this.off(O,A),$(j)};return this.on(O,A)}off(O,$){let A=this.events.get(O);if(!A)return;if($){let j=$;A.delete(j)}else A.clear()}emit(O,$){let A=this.events.get(O);if(!A||A.size===0)return;let j=this.emitCache;j.length=0;for(let Q of A)j.push(Q);for(let Q=0;Q<j.length;Q++){let V=j[Q];try{let J=V($);if(this.captureRejections&&NO(J))this.handlePromiseRejection(J)}catch(J){if(this.captureRejections&&this.events.has("error"))this.emit("error",J);else throw J}}}handlePromiseRejection(O){O.catch(($)=>{if(this.events.has("error"))this.emit("error",$);else throw $})}removeAllListeners(O){if(O)this.events.delete(O);else this.events.clear()}setMaxListeners(O){this.maxListeners=O}getMaxListeners(){return this.maxListeners}listeners(O){let $=this.events.get(O);return $?Array.from($):[]}listenerCount(O){let $=this.events.get(O);return $?$.size:0}eventNames(){return Array.from(this.events.keys())}}function NO(O){if(!O||typeof O!=="object"&&typeof O!=="function")return!1;let $=O;return typeof $.then==="function"&&typeof $.catch==="function"}class n{audioContext;masterGain;activeSources=new Map;activeSourceIdsScratch=new Set;playing=!1;disposed=!1;playbackId=0;startContextTime=0;startMediaTime=0;pauseTime=0;masterVolume=1;masterMuted=!1;constructor(O={}){if(O.audioContext)this.audioContext=O.audioContext;else{let $=globalThis,A=$.AudioContext||$.webkitAudioContext;if(!A)throw Error("AudioContext is not supported in this environment");this.audioContext=new A}this.masterGain=this.audioContext.createGain(),this.masterGain.connect(this.audioContext.destination)}registerSource(O,$){if(this.disposed)return;let A=this.audioContext.createGain(),j=this.audioContext.createStereoPanner();A.connect(j),j.connect(this.masterGain),this.activeSources.set(O.id,{sourceId:O.id,bufferSink:$,iterator:null,gainNode:A,panNode:j,queuedNodes:new Set,volume:1,pan:0,muted:!1,startSourceTime:0,currentSourceTime:0,iteratorStartTime:0,lastScheduledTime:0})}unregisterSource(O){let $=this.activeSources.get(O);if(!$)return;this.stopSourceAudio($),$.gainNode.disconnect(),$.panNode.disconnect(),this.activeSources.delete(O)}hasSource(O){return this.activeSources.has(O)}processAudioLayers(O,$){if(this.disposed||!this.playing)return;let A=this.activeSourceIdsScratch;A.clear();for(let j of O){let Q=j.source.id;A.add(Q);let V=this.activeSources.get(Q);if(!V)continue;let J=j.volume??1,K=j.pan??0,Z=j.muted??!1,U=j.sourceTime??$;if(V.volume!==J||V.muted!==Z)V.volume=J,V.muted=Z,V.gainNode.gain.value=Z?0:J*J;if(V.pan!==K)V.pan=K,V.panNode.pan.value=Math.max(-1,Math.min(1,K));if(Math.abs(U-V.currentSourceTime)>0.5&&V.iterator!==null)this.restartSourceIterator(V,U);V.currentSourceTime=U}for(let[j,Q]of this.activeSources)if(!A.has(j)&&Q.iterator!==null)this.stopSourceAudio(Q)}async play(O=this.pauseTime){if(this.playing||this.disposed)return;if(this.audioContext.state==="suspended")await this.audioContext.resume();this.playbackId++,this.playing=!0,this.startContextTime=this.audioContext.currentTime,this.startMediaTime=O,this.pauseTime=O}startSourcePlayback(O,$){let A=this.activeSources.get(O);if(!A||A.iterator!==null)return;this.restartSourceIterator(A,$)}restartSourceIterator(O,$){this.stopSourceAudio(O),O.startSourceTime=$,O.currentSourceTime=$,O.iteratorStartTime=this.audioContext.currentTime,O.iterator=O.bufferSink.buffers($),O.lastScheduledTime=$,this.scheduleSourceBuffers(O,this.playbackId)}async scheduleSourceBuffers(O,$){let A=O.iterator;if(!A)return;try{for await(let{buffer:j,timestamp:Q}of A){if($!==this.playbackId||this.disposed||!this.playing)break;let V=this.audioContext.createBufferSource();V.buffer=j,V.connect(O.gainNode);let J=Q-O.startSourceTime,K=O.iteratorStartTime+J;if(K>=this.audioContext.currentTime)V.start(K);else{let G=this.audioContext.currentTime-K;if(G<j.duration)V.start(this.audioContext.currentTime,G);else continue}O.queuedNodes.add(V),V.onended=()=>{O.queuedNodes.delete(V)},O.lastScheduledTime=Q;let Z=this.audioContext.currentTime-O.iteratorStartTime;if(Q-O.startSourceTime-Z>1)await this.waitForCatchup(O,Q)}}catch{}}async waitForCatchup(O,$){return new Promise((A)=>{let j=setInterval(()=>{if(!this.playing||this.disposed){clearInterval(j),A();return}let Q=this.audioContext.currentTime-O.iteratorStartTime;if($-O.startSourceTime-Q<1)clearInterval(j),A()},100)})}pause(){if(!this.playing)return;this.pauseTime=this.getCurrentTime(),this.playing=!1;for(let O of this.activeSources.values())this.stopSourceAudio(O)}stop(){this.pause(),this.pauseTime=0,this.startContextTime=0,this.startMediaTime=0}async seek(O){let $=this.playing;if(this.pause(),this.pauseTime=O,this.startMediaTime=O,$)await this.play(O)}stopSourceAudio(O){for(let $ of O.queuedNodes)try{$.stop()}catch{}if(O.queuedNodes.clear(),O.iterator)O.iterator.return(),O.iterator=null}getCurrentTime(){if(this.playing)return this.startMediaTime+(this.audioContext.currentTime-this.startContextTime);return this.pauseTime}setMasterVolume(O){this.masterVolume=Math.max(0,Math.min(1,O)),this.updateMasterGain()}setMasterMuted(O){this.masterMuted=O,this.updateMasterGain()}updateMasterGain(){let O=this.masterMuted?0:this.masterVolume;this.masterGain.gain.value=O*O}getAudioContext(){return this.audioContext}isPlaying(){return this.playing}dispose(){if(this.disposed)return;this.disposed=!0,this.playbackId++,this.stop();for(let O of this.activeSources.values())this.stopSourceAudio(O),O.gainNode.disconnect(),O.panNode.disconnect();if(this.activeSources.clear(),this.masterGain.disconnect(),this.audioContext.state!=="closed")this.audioContext.close()}}import{ALL_FORMATS as DO,AudioBufferSink as JO,BlobSource as MO,BufferSource as _O,CanvasSink as EO,FilePathSource as qO,Input as CO,ReadableStreamSource as RO,UrlSource as WO}from"mediabunny";class KO{cache=new Map;maxSize;constructor(O){this.maxSize=O}get(O){let $=this.cache.get(O);if($!==void 0)this.cache.delete(O),this.cache.set(O,$);return $}set(O,$){if(this.cache.has(O))this.cache.delete(O);else if(this.cache.size>=this.maxSize){let A=this.cache.keys().next().value;if(A!==void 0)this.cache.delete(A)}this.cache.set(O,$)}clear(){this.cache.clear()}get size(){return this.cache.size}}class UO{id;type="video";duration;width;height;data;disposed=!1;constructor(O,$,A,j,Q){this.id=O,this.data=$,this.duration=A,this.width=j,this.height=Q}async getFrameAt(O){if(this.disposed)return null;let $=this.data.frameIntervalMs,A=Math.floor(O*1000/$)*$,j=this.data.frameCache.get(A);if(j)return j.canvas;try{let Q=await this.data.canvasSink.getCanvas(O);if(!Q)return null;return this.data.frameCache.set(A,Q),Q.canvas}catch{return null}}getAudioBufferSink(){return this.data.audioBufferSink}hasAudio(){return this.data.audioBufferSink!==null}clearCache(){this.data.frameCache.clear()}dispose(){if(this.disposed)return;this.disposed=!0,this.data.frameCache.clear(),this.data.input.dispose()}}class ZO{id;type="image";duration=1/0;width;height;data;disposed=!1;constructor(O,$){this.id=O,this.data=$,this.width=$.image.width,this.height=$.image.height}async getFrameAt(O){if(this.disposed)return null;return this.data.image}dispose(){if(this.disposed)return;if(this.disposed=!0,"close"in this.data.image)this.data.image.close()}}class GO{id;type="audio";duration;width=0;height=0;data;disposed=!1;constructor(O,$,A){this.id=O,this.data=$,this.duration=A}async getFrameAt(O){return null}getAudioBufferSink(){return this.data.audioBufferSink}dispose(){if(this.disposed)return;this.disposed=!0,this.data.input.dispose()}}class x{sources=new Map;audioContext=null;nextId=0;constructor(O){this.audioContext=O??null}generateId(){return`source_${this.nextId++}`}async loadVideo(O,$={}){let A=$.id??this.generateId(),j=this.createInput(O),Q=await j.getVideoTracks();if(Q.length===0)throw j.dispose(),Error("Source has no video track");let V=Q[0];if(!await V.canDecode())throw j.dispose(),Error(`Cannot decode video track with codec: ${V.codec}`);let K=new EO(V,{poolSize:4}),Z=await V.computeDuration(),U=30;try{let Y=await V.computePacketStats(100);if(Y.averagePacketRate>0)U=Y.averagePacketRate}catch{}let G=1000/U,L=V.displayWidth*V.displayHeight,P=L>2073600?15:L>921600?30:60,M=null,X=null;try{let Y=await j.getAudioTracks();if(Y.length>0){if(M=Y[0],await M.canDecode())X=new JO(M)}}catch{}let E=new UO(A,{input:j,videoTrack:V,canvasSink:K,frameCache:new KO(P),frameIntervalMs:G,audioTrack:M,audioBufferSink:X},Z,V.displayWidth,V.displayHeight);return this.sources.set(A,E),E}async loadImage(O){let $=this.generateId(),A;if(typeof O!=="string")A=await createImageBitmap(O);else if(typeof Image>"u"){let Q=await fetch(O);if(!Q.ok)throw Error(`Failed to load image: ${O}`);let V=await Q.blob();A=await createImageBitmap(V)}else A=await new Promise((Q,V)=>{let J=new Image;J.onload=()=>Q(J),J.onerror=()=>V(Error(`Failed to load image: ${O}`)),J.crossOrigin="anonymous",J.src=O});let j=new ZO($,{image:A});return this.sources.set($,j),j}async loadAudio(O,$={}){let A=$.id??this.generateId(),j=this.createInput(O),Q=await j.getAudioTracks();if(Q.length===0)throw j.dispose(),Error("Source has no audio track");let V=Q[0];if(!await V.canDecode())throw j.dispose(),Error(`Cannot decode audio track with codec: ${V.codec}`);let K=await V.computeDuration(),Z=new JO(V),U=new GO(A,{input:j,audioTrack:V,audioBufferSink:Z},K);return this.sources.set(A,U),U}createInput(O){let $;if(O instanceof File||O instanceof Blob)$=new MO(O);else if(O instanceof ArrayBuffer||O instanceof Uint8Array)$=new _O(O);else if(typeof O==="string"||O instanceof URL){let A=O instanceof URL?O.href:O;if(typeof window>"u"&&!A.startsWith("http"))$=new qO(A);else $=new WO(A)}else if(typeof ReadableStream<"u"&&O instanceof ReadableStream)$=new RO(O);else throw Error("Unsupported source type");return new CO({source:$,formats:DO})}getSource(O){return this.sources.get(O)}hasSource(O){return this.sources.has(O)}unloadSource(O){let $=this.sources.get(O);if($)return $.dispose(),this.sources.delete(O),!0;return!1}getAllSources(){return Array.from(this.sources.values())}clear(){for(let O of this.sources.values())O.dispose();this.sources.clear()}dispose(){if(this.clear(),this.audioContext&&this.audioContext.state!=="closed")this.audioContext.close();this.audioContext=null}}class s{worker;nextId=1;pending=new Map;ready;constructor(O){let $=typeof O.worker==="boolean"?{}:O.worker??{},A=$.type??"module",j=$.url??new URL("./compositor-worker.js",import.meta.url);this.worker=new Worker(j,{type:A}),this.worker.onmessage=(J)=>{let{id:K,ok:Z,result:U,error:G}=J.data,L=this.pending.get(K);if(!L)return;if(this.pending.delete(K),Z)L.resolve(U);else L.reject(Error(G??"Worker error"))},this.worker.onerror=(J)=>{let K=J.error instanceof Error?J.error:Error("Worker error");for(let Z of this.pending.values())Z.reject(K);this.pending.clear()};let Q=O.canvas.transferControlToOffscreen(),V={canvas:Q,width:O.width,height:O.height,backgroundColor:O.backgroundColor};this.ready=this.call("init",V,[Q])}postMessage(O,$,A){let j=this.nextId++;return this.worker.postMessage({id:j,kind:O,payload:$},A??[]),j}call(O,$,A){let j=this.postMessage(O,$,A);return new Promise((Q,V)=>{this.pending.set(j,{resolve:Q,reject:V})})}async loadSource(O,$){await this.ready;let A={source:O,options:$};return this.call("loadSource",A)}async loadImage(O){await this.ready;let $={source:O};return this.call("loadImage",$)}async loadAudio(O,$){await this.ready;let A={source:O,options:$};return this.call("loadAudio",A)}async unloadSource(O){await this.ready;let $={id:O};return this.call("unloadSource",$)}async render(O){await this.ready;let $={frame:O};return this.call("render",$)}async clear(){return await this.ready,this.call("clear")}async resize(O,$){await this.ready;let A={width:O,height:$};return this.call("resize",A)}async exportFrame(O,$){await this.ready;let A={frame:O,options:$};return this.call("exportFrame",A)}dispose(){try{this.worker.postMessage({id:this.nextId++,kind:"dispose"})}catch{}this.worker.terminate(),this.pending.clear()}}class i{canvas;ctx=null;width;height;backgroundColor;sourcePool;audioManager=null;workerClient=null;workerSources=new Map;workerAudioSources=new Map;emitter;state;animationFrameId=null;lastFrameTime=0;lastRenderTime=0;previewOptions=null;disposed=!1;renderBuffers={visibleLayers:[],framePromises:[],frameImages:[]};lastTimeUpdateEmit=0;timeUpdateThrottleMs=100;renderPending=!1;activeAudioSourceIds=new Set;audioScratch={nextActiveSourceIds:new Set,newSourceIds:[],newSourceTimes:[]};registeredAudioSources=new Set;constructor(O){this.canvas=O.canvas,this.width=O.width??(this.canvas.width||1920),this.height=O.height??(this.canvas.height||1080),this.backgroundColor=O.backgroundColor??"#000000",this.emitter=new y({maxListeners:50}),this.state={playing:!1,currentTime:0,duration:0,seeking:!1},this.canvas.width=this.width,this.canvas.height=this.height;let $=typeof O.worker==="boolean"?O.worker:O.worker?O.worker.enabled??!0:!1,A=$&&typeof Worker<"u"&&typeof OffscreenCanvas<"u"&&typeof this.canvas.transferControlToOffscreen==="function"&&!(this.canvas instanceof OffscreenCanvas);if($&&!A)throw Error("Worker compositor requires HTMLCanvasElement, OffscreenCanvas, and Worker support");if(this.sourcePool=new x,A)this.workerClient=new s({canvas:this.canvas,width:this.width,height:this.height,backgroundColor:this.backgroundColor,worker:O.worker??!0});if(O.enableAudio!==!1)this.audioManager=new n;if(!this.workerClient){if(this.ctx=this.canvas.getContext("2d",{alpha:!1,desynchronized:!0}),!this.ctx)throw Error("Failed to get 2D context for compositor canvas");this.clear()}}async loadSource(O,$){if(this.checkDisposed(),this.workerClient){let j=await this.workerClient.loadSource(O,$),Q=this.createWorkerSource(j);if(this.audioManager&&j.hasAudio)await this.loadWorkerAudio(O,Q.id);return this.emitter.emit("sourceloaded",{id:Q.id,source:Q}),Q}let A=await this.sourcePool.loadVideo(O,$);return this.registerSourceAudio(A),this.emitter.emit("sourceloaded",{id:A.id,source:A}),A}async loadImage(O){if(this.checkDisposed(),this.workerClient){let A=await this.workerClient.loadImage(O),j=this.createWorkerSource(A);return this.emitter.emit("sourceloaded",{id:j.id,source:j}),j}let $=await this.sourcePool.loadImage(O);return this.emitter.emit("sourceloaded",{id:$.id,source:$}),$}async loadAudio(O,$){if(this.checkDisposed(),this.workerClient){let j=await this.workerClient.loadAudio(O,$),Q=this.createWorkerSource(j);if(this.audioManager)await this.loadWorkerAudio(O,Q.id);return this.emitter.emit("sourceloaded",{id:Q.id,source:Q}),Q}let A=await this.sourcePool.loadAudio(O,$);return this.registerSourceAudio(A),this.emitter.emit("sourceloaded",{id:A.id,source:A}),A}unloadSource(O){if(this.workerClient){if(!this.workerSources.get(O))return!1;return this.workerClient.unloadSource(O),this.workerSources.delete(O),this.unloadWorkerAudio(O),this.emitter.emit("sourceunloaded",{id:O}),!0}if(this.registeredAudioSources.has(O))this.audioManager?.unregisterSource(O),this.registeredAudioSources.delete(O);let $=this.sourcePool.unloadSource(O);if($)this.emitter.emit("sourceunloaded",{id:O});return $}registerSourceAudio(O){if(!this.audioManager)return;if(this.registeredAudioSources.has(O.id))return;let $=O.getAudioBufferSink?.();if($)this.audioManager.registerSource(O,$),this.registeredAudioSources.add(O.id)}processAudioLayers(O,$){if(!this.audioManager)return;let A=this.audioScratch.newSourceIds,j=this.audioScratch.newSourceTimes,Q=this.audioScratch.nextActiveSourceIds,V=this.activeAudioSourceIds;A.length=0,j.length=0,Q.clear();for(let J=0;J<O.length;J++){let K=O[J];if(K.muted)continue;let Z=K.source.id;if(!this.audioManager.hasSource(Z))continue;if(Q.add(Z),!V.has(Z))A.push(Z),j.push(K.sourceTime??$)}if(V.size>0)V.clear();for(let J of Q)V.add(J);this.audioManager.processAudioLayers(O,$);for(let J=0;J<A.length;J++)this.audioManager.startSourcePlayback(A[J],j[J])}getSource(O){if(this.workerClient)return this.workerSources.get(O);return this.sourcePool.getSource(O)}getAllSources(){if(this.workerClient)return Array.from(this.workerSources.values());return this.sourcePool.getAllSources()}async render(O){if(this.checkDisposed(),this.workerClient){let U=this.serializeWorkerFrame(O);return this.workerClient.render(U)}let $=this.ctx;if(!$)return!1;let{visibleLayers:A,framePromises:j,frameImages:Q}=this.renderBuffers;A.length=0,j.length=0,Q.length=0;let V=!1,J=-1/0,K=O.layers;for(let U=0;U<K.length;U++){let G=K[U];if(G.visible===!1)continue;let L=G.zIndex??0;if(L<J)V=!0;J=L,A.push(G)}if(A.length===0)return $.fillStyle=this.backgroundColor,$.fillRect(0,0,this.width,this.height),!0;if(V)A.sort((U,G)=>(U.zIndex??0)-(G.zIndex??0));for(let U=0;U<A.length;U++){let G=A[U],L=G.sourceTime??O.time;j[U]=G.source.getFrameAt(L)}let Z=await Promise.all(j);for(let U=0;U<Z.length;U++)Q[U]=Z[U]??null;$.fillStyle=this.backgroundColor,$.fillRect(0,0,this.width,this.height);for(let U=0;U<A.length;U++){let G=Q[U];if(G)this.renderLayer(G,A[U])}return!0}renderLayer(O,$){let A=this.ctx;if(!A)return;let j=$.transform,Q=$.source.width??this.width,V=$.source.height??this.height;if(!j){A.drawImage(O,0,0,Q,V);return}let J=j.width??Q,K=j.height??V,Z=j.x??0,U=j.y??0,G=j.rotation??0,L=j.scaleX??1,P=j.scaleY??1,M=j.opacity??1,X=M!==1;if(!X&&!(G!==0||L!==1||P!==1)){A.drawImage(O,Z,U,J,K);return}let Y=j.anchorX??0.5,q=j.anchorY??0.5;if(A.save(),X)A.globalAlpha=M;if(A.translate(Z+J*Y,U+K*q),G!==0)A.rotate(G*Math.PI/180);if(L!==1||P!==1)A.scale(L,P);A.drawImage(O,-J*Y,-K*q,J,K),A.restore()}createWorkerSource(O){let $={id:O.id,type:O.type,duration:O.duration,width:O.width,height:O.height,async getFrameAt(){throw Error("getFrameAt is not available when worker rendering is enabled")},getAudioBufferSink(){return null},hasAudio(){return O.hasAudio??!1},dispose(){}};return this.workerSources.set($.id,$),$}async loadWorkerAudio(O,$){if(!this.audioManager)return;if(this.workerAudioSources.has($))this.unloadWorkerAudio($);try{let A=await this.sourcePool.loadAudio(O,{id:$});this.workerAudioSources.set($,A),this.registerSourceAudio(A)}catch{}}unloadWorkerAudio(O){if(!this.audioManager)return;if(this.workerAudioSources.has(O))this.audioManager.unregisterSource(O),this.registeredAudioSources.delete(O),this.sourcePool.unloadSource(O),this.workerAudioSources.delete(O)}serializeWorkerFrame(O){if(!this.workerClient)throw Error("Worker compositor not initialized");let $=O.layers,A=Array($.length);for(let j=0;j<$.length;j++){let Q=$[j],V=Q.source.id;if(!this.workerSources.has(V))throw Error(`Layer source ${V} is not managed by this compositor`);A[j]={sourceId:V,sourceTime:Q.sourceTime,transform:Q.transform,visible:Q.visible,zIndex:Q.zIndex}}return{time:O.time,layers:A}}clear(){if(this.workerClient){this.workerClient.clear();return}if(!this.ctx)return;this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,0,this.width,this.height)}preview(O){this.checkDisposed(),this.previewOptions=O,this.state.duration=O.duration,this.lastRenderTime=0,this.emitter.emit("compositionchange",void 0)}async play(){if(this.checkDisposed(),this.state.playing)return;if(!this.previewOptions)throw Error("No preview configured. Call preview() first.");if(this.state.playing=!0,this.lastFrameTime=performance.now(),this.lastRenderTime=this.lastFrameTime,this.emitter.emit("play",void 0),this.audioManager)await this.audioManager.play(this.state.currentTime);this.startRenderLoop()}pause(){if(this.checkDisposed(),!this.state.playing)return;if(this.state.playing=!1,this.stopRenderLoop(),this.audioManager)this.audioManager.pause();this.emitter.emit("pause",void 0)}async seek(O){if(this.checkDisposed(),!this.previewOptions)return;let $=Math.max(0,Math.min(O,this.state.duration));if(this.state.seeking=!0,this.emitter.emit("seeking",{time:$}),this.state.currentTime=$,this.audioManager)await this.audioManager.seek($);let A=this.previewOptions.getComposition($);await this.render(A),this.state.seeking=!1,this.emitter.emit("seeked",{time:$}),this.emitter.emit("timeupdate",{currentTime:$})}startRenderLoop(){if(this.animationFrameId!==null)return;let O=()=>{if(!this.state.playing||!this.previewOptions)return;this.animationFrameId=requestAnimationFrame(O);let $=performance.now(),A=($-this.lastFrameTime)/1000;if(this.lastFrameTime=$,this.state.currentTime+=A,this.state.currentTime>=this.state.duration)if(this.previewOptions.loop)this.state.currentTime=0;else{this.state.currentTime=this.state.duration,this.pause(),this.emitter.emit("ended",void 0);return}let j=this.previewOptions.fps??0,Q=j>0?1000/j:0;if(!this.renderPending&&(Q===0||$-this.lastRenderTime>=Q)){this.renderPending=!0,this.lastRenderTime=$;let J=this.previewOptions.getComposition(this.state.currentTime);if(this.audioManager)this.processAudioLayers(J.audio??[],this.state.currentTime);this.render(J).catch(()=>{}).finally(()=>{this.renderPending=!1})}if($-this.lastTimeUpdateEmit>=this.timeUpdateThrottleMs)this.lastTimeUpdateEmit=$,this.emitter.emit("timeupdate",{currentTime:this.state.currentTime})};this.animationFrameId=requestAnimationFrame(O)}stopRenderLoop(){if(this.animationFrameId!==null)cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null}async exportFrame(O,$={}){if(this.checkDisposed(),!this.previewOptions)return null;let A=this.previewOptions.getComposition(O);if(this.workerClient){let j=this.serializeWorkerFrame(A);return this.workerClient.exportFrame(j,$)}if(await this.render(A),"toBlob"in this.canvas)return new Promise((j)=>{this.canvas.toBlob((Q)=>j(Q),`image/${$.format??"png"}`,$.quality)});else return this.canvas.convertToBlob({type:`image/${$.format??"png"}`,quality:$.quality})}get currentTime(){return this.state.currentTime}get duration(){return this.state.duration}get playing(){return this.state.playing}get paused(){return!this.state.playing}get seeking(){return this.state.seeking}getWidth(){return this.width}getHeight(){return this.height}resize(O,$){if(this.checkDisposed(),this.width=O,this.height=$,this.canvas.width=O,this.canvas.height=$,this.workerClient){this.workerClient.resize(O,$);return}this.clear()}on(O,$){return this.emitter.on(O,$)}once(O,$){return this.emitter.once(O,$)}off(O,$){this.emitter.off(O,$)}setVolume(O){this.audioManager?.setMasterVolume(O)}setMuted(O){this.audioManager?.setMasterMuted(O)}getAudioContext(){if(!this.audioManager)throw Error("Audio is disabled for this compositor");return this.audioManager.getAudioContext()}checkDisposed(){if(this.disposed)throw Error("Compositor has been disposed")}dispose(){if(this.disposed)return;this.disposed=!0,this.stopRenderLoop(),this.audioManager?.dispose(),this.workerClient?.dispose(),this.workerClient=null,this.sourcePool.dispose(),this.registeredAudioSources.clear(),this.activeAudioSourceIds.clear(),this.audioScratch.nextActiveSourceIds.clear(),this.audioScratch.newSourceIds.length=0,this.audioScratch.newSourceTimes.length=0,this.workerSources.clear(),this.workerAudioSources.clear(),this.emitter.removeAllListeners(),this.ctx=null,this.previewOptions=null}}import{CanvasSink as FO,VideoSampleSink as SO}from"mediabunny";class S{canvas;ctx=null;isInitialized=!1;rotation=0;constructor(O){this.canvas=O.canvas,this.rotation=O.rotation??0,this.initialize()}initialize(){try{if(this.ctx=this.canvas.getContext("2d",{alpha:!1,desynchronized:!0}),!this.ctx)return!1;return this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.isInitialized=!0,!0}catch{return!1}}isReady(){return this.isInitialized&&this.ctx!==null}render(O){if(!this.isReady()||!this.ctx)return!1;try{let{width:$,height:A}=O;if($===0||A===0)return!1;let j=this.canvas.width,Q=this.canvas.height;if(j===0||Q===0)return!1;let V=this.rotation===90||this.rotation===270,J=V?A:$,K=V?$:A,Z=Math.min(j/J,Q/K),U=Math.round(J*Z),G=Math.round(K*Z),L=Math.round((j-U)/2),P=Math.round((Q-G)/2);if(this.ctx.fillStyle="black",this.ctx.fillRect(0,0,j,Q),this.ctx.save(),this.ctx.translate(L+U/2,P+G/2),this.rotation!==0)this.ctx.rotate(this.rotation*Math.PI/180);if(V)this.ctx.drawImage(O,0,0,$,A,-G/2,-U/2,G,U);else this.ctx.drawImage(O,0,0,$,A,-U/2,-G/2,U,G);return this.ctx.restore(),!0}catch{return!1}}clear(){if(!this.isReady()||!this.ctx)return;this.ctx.fillStyle="black",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}setRotation(O){this.rotation=O}getRotation(){return this.rotation}dispose(){this.ctx=null,this.isInitialized=!1}}class t{resources;isInitialized=!1;canvas;textureWidth=0;textureHeight=0;options;boundHandleContextLost=null;boundHandleContextRestored=null;rotation=0;positionsArray=new Float32Array(8);vertexShaderSource=`
|
|
2
2
|
attribute vec2 a_position;
|
|
3
3
|
attribute vec2 a_texCoord;
|
|
4
4
|
varying vec2 v_texCoord;
|
|
@@ -16,7 +16,7 @@ class f{events=new Map;maxListeners;captureRejections;emitCache=[];constructor(O
|
|
|
16
16
|
vec4 color = texture2D(u_texture, v_texCoord);
|
|
17
17
|
gl_FragColor = color;
|
|
18
18
|
}
|
|
19
|
-
`;constructor(O){this.canvas=O.canvas,this.options=O,this.rotation=O.rotation??0,this.resources={gl:null,program:null,texture:null,vertexBuffer:null,texCoordBuffer:null,positionLocation:-1,texCoordLocation:-1,textureLocation:null},this.initialize()}initialize(){try{let O={alpha:this.options.alpha??!1,antialias:this.options.antialias??!1,depth:!1,stencil:!1,preserveDrawingBuffer:this.options.preserveDrawingBuffer??!1,powerPreference:this.options.powerPreference??"high-performance"},$=this.canvas.getContext("webgl",O);if(!$&&"getContext"in this.canvas)$=this.canvas.getContext("experimental-webgl",O);if(!$)return!1;this.resources.gl=$;let A=this.createShader($,$.VERTEX_SHADER,this.vertexShaderSource),
|
|
19
|
+
`;constructor(O){this.canvas=O.canvas,this.options=O,this.rotation=O.rotation??0,this.resources={gl:null,program:null,texture:null,vertexBuffer:null,texCoordBuffer:null,positionLocation:-1,texCoordLocation:-1,textureLocation:null},this.initialize()}initialize(){try{let O={alpha:this.options.alpha??!1,antialias:this.options.antialias??!1,depth:!1,stencil:!1,preserveDrawingBuffer:this.options.preserveDrawingBuffer??!1,powerPreference:this.options.powerPreference??"high-performance"},$=this.canvas.getContext("webgl",O);if(!$&&"getContext"in this.canvas)$=this.canvas.getContext("experimental-webgl",O);if(!$)return!1;this.resources.gl=$;let A=this.createShader($,$.VERTEX_SHADER,this.vertexShaderSource),j=this.createShader($,$.FRAGMENT_SHADER,this.fragmentShaderSource);if(!A||!j)throw Error("Failed to create shaders");let Q=$.createProgram();if(!Q)throw Error("Failed to create program");if($.attachShader(Q,A),$.attachShader(Q,j),$.linkProgram(Q),!$.getProgramParameter(Q,$.LINK_STATUS)){let J=$.getProgramInfoLog(Q);throw Error(`Failed to link program: ${J}`)}this.resources.program=Q,this.resources.positionLocation=$.getAttribLocation(Q,"a_position"),this.resources.texCoordLocation=$.getAttribLocation(Q,"a_texCoord"),this.resources.textureLocation=$.getUniformLocation(Q,"u_texture"),this.setupQuadBuffers($);let V=$.createTexture();if(!V)throw Error("Failed to create texture");if($.bindTexture($.TEXTURE_2D,V),$.texParameteri($.TEXTURE_2D,$.TEXTURE_WRAP_S,$.CLAMP_TO_EDGE),$.texParameteri($.TEXTURE_2D,$.TEXTURE_WRAP_T,$.CLAMP_TO_EDGE),$.texParameteri($.TEXTURE_2D,$.TEXTURE_MIN_FILTER,$.LINEAR),$.texParameteri($.TEXTURE_2D,$.TEXTURE_MAG_FILTER,$.LINEAR),this.resources.texture=V,$.disable($.DEPTH_TEST),$.disable($.CULL_FACE),$.disable($.BLEND),"addEventListener"in this.canvas)this.boundHandleContextLost=this.handleContextLost.bind(this),this.boundHandleContextRestored=this.handleContextRestored.bind(this),this.canvas.addEventListener("webglcontextlost",this.boundHandleContextLost,!1),this.canvas.addEventListener("webglcontextrestored",this.boundHandleContextRestored,!1);return this.isInitialized=!0,!0}catch{return this.cleanup(),!1}}createShader(O,$,A){let j=O.createShader($);if(!j)return null;if(O.shaderSource(j,A),O.compileShader(j),!O.getShaderParameter(j,O.COMPILE_STATUS))return O.deleteShader(j),null;return j}setupQuadBuffers(O){let $=new Float32Array([-1,-1,1,-1,-1,1,1,1]),A=new Float32Array([0,1,1,1,0,0,1,0]),j=O.createBuffer();O.bindBuffer(O.ARRAY_BUFFER,j),O.bufferData(O.ARRAY_BUFFER,$,O.STATIC_DRAW),this.resources.vertexBuffer=j;let Q=O.createBuffer();O.bindBuffer(O.ARRAY_BUFFER,Q),O.bufferData(O.ARRAY_BUFFER,A,O.STATIC_DRAW),this.resources.texCoordBuffer=Q}isReady(){return this.isInitialized&&this.resources.gl!==null}render(O){if(!this.isInitialized||!this.resources.gl)return!1;let $=this.resources.gl;try{let{width:A,height:j}=O;if(A===0||j===0)return!1;let Q=this.canvas.width,V=this.canvas.height;if(Q===0||V===0)return!1;if($.viewport(0,0,Q,V),$.bindTexture($.TEXTURE_2D,this.resources.texture),A!==this.textureWidth||j!==this.textureHeight)$.texImage2D($.TEXTURE_2D,0,$.RGBA,$.RGBA,$.UNSIGNED_BYTE,O),this.textureWidth=A,this.textureHeight=j;else $.texSubImage2D($.TEXTURE_2D,0,0,0,$.RGBA,$.UNSIGNED_BYTE,O);$.clearColor(0,0,0,1),$.clear($.COLOR_BUFFER_BIT);let J=this.rotation===90||this.rotation===270,K=J?this.textureHeight:this.textureWidth,Z=J?this.textureWidth:this.textureHeight,U=Math.min(Q/K,V/Z),G=Math.round(K*U),L=Math.round(Z*U),P=Math.round((Q-G)/2),M=Math.round((V-L)/2),X=P/Q*2-1,E=(P+G)/Q*2-1,Y=1-M/V*2,q=1-(M+L)/V*2,H=(X+E)/2,b=(Y+q)/2,w=(E-X)/2,T=(Y-q)/2,f=this.rotation*Math.PI/180,C=Math.cos(f),R=Math.sin(f),B=J?T:w,N=J?w:T,z=this.positionsArray;return z[0]=-B*C- -N*R+H,z[1]=-B*R+-N*C+b,z[2]=B*C- -N*R+H,z[3]=B*R+-N*C+b,z[4]=-B*C-N*R+H,z[5]=-B*R+N*C+b,z[6]=B*C-N*R+H,z[7]=B*R+N*C+b,$.bindBuffer($.ARRAY_BUFFER,this.resources.vertexBuffer),$.bufferData($.ARRAY_BUFFER,z,$.DYNAMIC_DRAW),$.useProgram(this.resources.program),$.bindBuffer($.ARRAY_BUFFER,this.resources.vertexBuffer),$.enableVertexAttribArray(this.resources.positionLocation),$.vertexAttribPointer(this.resources.positionLocation,2,$.FLOAT,!1,0,0),$.bindBuffer($.ARRAY_BUFFER,this.resources.texCoordBuffer),$.enableVertexAttribArray(this.resources.texCoordLocation),$.vertexAttribPointer(this.resources.texCoordLocation,2,$.FLOAT,!1,0,0),$.uniform1i(this.resources.textureLocation,0),$.drawArrays($.TRIANGLE_STRIP,0,4),!0}catch{return!1}}clear(){if(!this.resources.gl)return;let O=this.resources.gl;O.clearColor(0,0,0,1),O.clear(O.COLOR_BUFFER_BIT)}handleContextLost(O){O.preventDefault(),this.isInitialized=!1}handleContextRestored(){this.initialize()}cleanup(){let O=this.resources.gl;if(!O)return;if(this.resources.texture)O.deleteTexture(this.resources.texture);if(this.resources.vertexBuffer)O.deleteBuffer(this.resources.vertexBuffer);if(this.resources.texCoordBuffer)O.deleteBuffer(this.resources.texCoordBuffer);if(this.resources.program)O.deleteProgram(this.resources.program);this.resources={gl:null,program:null,texture:null,vertexBuffer:null,texCoordBuffer:null,positionLocation:-1,texCoordLocation:-1,textureLocation:null},this.isInitialized=!1}setRotation(O){this.rotation=O}getRotation(){return this.rotation}dispose(){if(this.resources.gl){let O=this.resources.gl.getExtension("WEBGL_lose_context");if(O)try{O.loseContext()}catch{}}if(this.cleanup(),"removeEventListener"in this.canvas){if(this.boundHandleContextLost)this.canvas.removeEventListener("webglcontextlost",this.boundHandleContextLost),this.boundHandleContextLost=null;if(this.boundHandleContextRestored)this.canvas.removeEventListener("webglcontextrestored",this.boundHandleContextRestored),this.boundHandleContextRestored=null}}}class r{canvas;device=null;context=null;pipeline=null;texture=null;sampler=null;bindGroup=null;vertexBuffer=null;isInitialized=!1;textureWidth=0;textureHeight=0;powerPreference;rotation=0;quadArray=new Float32Array(16);vertexShaderSource=`
|
|
20
20
|
struct VSOut {
|
|
21
21
|
@builtin(position) pos : vec4f,
|
|
22
22
|
@location(0) uv : vec2f,
|
|
@@ -37,4 +37,4 @@ class f{events=new Map;maxListeners;captureRejections;emitCache=[];constructor(O
|
|
|
37
37
|
fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
|
|
38
38
|
return textureSample(texture_view, texture_sampler, uv);
|
|
39
39
|
}
|
|
40
|
-
`;constructor(O){this.canvas=O.canvas,this.powerPreference=O.powerPreference||"high-performance",this.rotation=O.rotation??0,this.initialize().catch(($)=>{console.error("WebGPU initialization failed:",$)})}async initialize(){try{let O=navigator;if(!O.gpu)return console.log("WebGPU not available in navigator"),!1;let $=await O.gpu.requestAdapter({powerPreference:this.powerPreference});if(!$)return console.log("WebGPU adapter not available"),!1;if(this.device=await $.requestDevice(),!this.device)return console.log("WebGPU device not available"),!1;if("getContext"in this.canvas)this.context=this.canvas.getContext("webgpu");if(!this.context)return console.log("WebGPU context not available on canvas"),!1;let A=O.gpu.getPreferredCanvasFormat();return this.context.configure({device:this.device,format:A,usage:GPUTextureUsage.RENDER_ATTACHMENT,alphaMode:"opaque"}),await this.createRenderPipeline(),this.createVertexBuffer(),this.isInitialized=!0,console.log("WebGPU renderer initialized successfully"),!0}catch(O){return console.error("WebGPU initialization error:",O),!1}}async createRenderPipeline(){if(!this.device)return;let O=navigator;if(!O.gpu)return;let $=this.device.createShaderModule({code:this.vertexShaderSource}),A=this.device.createShaderModule({code:this.fragmentShaderSource});this.pipeline=this.device.createRenderPipeline({layout:"auto",vertex:{module:$,entryPoint:"vs_main",buffers:[{arrayStride:16,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"}]}]},fragment:{module:A,entryPoint:"fs_main",targets:[{format:O.gpu.getPreferredCanvasFormat()}]},primitive:{topology:"triangle-strip"}})}createVertexBuffer(){if(!this.device)return;this.vertexBuffer=this.device.createBuffer({size:64,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}createTexture(O,$){if(!this.device)return;if(this.texture)this.texture.destroy();if(this.texture=this.device.createTexture({size:{width:O,height:$},format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),!this.sampler)this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"});this.createBindGroup()}createBindGroup(){if(!this.device||!this.texture||!this.sampler||!this.pipeline)return;this.bindGroup=this.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:this.sampler},{binding:1,resource:this.texture.createView()}]})}isReady(){return this.isInitialized&&this.device!==null&&this.context!==null&&this.pipeline!==null}render(O){if(!this.isReady()||!this.device||!this.context||!this.pipeline)return!1;try{let{width:$,height:A}=O;if($===0||A===0)return console.warn(`WebGPU: Source canvas has zero dimensions (${$}x${A})`),!1;let Q=this.canvas.width,V=this.canvas.height;if(Q===0||V===0)return console.warn(`WebGPU: Output canvas has zero dimensions (${Q}x${V})`),!1;if($!==this.textureWidth||A!==this.textureHeight)this.createTexture($,A),this.textureWidth=$,this.textureHeight=A;if(!this.texture)return!1;try{this.device.queue.copyExternalImageToTexture({source:O},{texture:this.texture},{width:$,height:A})}catch{let VO=O.getContext("2d");if(!VO)return!1;let zO=VO.getImageData(0,0,$,A),BO=new Uint8Array(zO.data.buffer);this.device.queue.writeTexture({texture:this.texture,origin:{x:0,y:0,z:0}},BO,{bytesPerRow:$*4,rowsPerImage:A},{width:$,height:A,depthOrArrayLayers:1})}let J=this.device.createCommandEncoder(),K=this.context.getCurrentTexture().createView(),Z=J.beginRenderPass({colorAttachments:[{view:K,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]});if(Z.setPipeline(this.pipeline),this.bindGroup)Z.setBindGroup(0,this.bindGroup);let G=this.rotation===90||this.rotation===270,j=G?this.textureHeight:this.textureWidth,U=G?this.textureWidth:this.textureHeight,X=Math.min(Q/j,V/U),z=Math.round(j*X),D=Math.round(U*X),q=Math.round((Q-z)/2),M=Math.round((V-D)/2),L=q/Q*2-1,S=(q+z)/Q*2-1,C=1-M/V*2,b=1-(M+D)/V*2,T=(L+S)/2,w=(C+b)/2,x=(S-L)/2,P=(C-b)/2,R=this.rotation*Math.PI/180,B=Math.cos(R),N=Math.sin(R),Y=G?P:x,H=G?x:P,_=this.quadArray;if(_[0]=-Y*B- -H*N+T,_[1]=-Y*N+-H*B+w,_[2]=0,_[3]=1,_[4]=Y*B- -H*N+T,_[5]=Y*N+-H*B+w,_[6]=1,_[7]=1,_[8]=-Y*B-H*N+T,_[9]=-Y*N+H*B+w,_[10]=0,_[11]=0,_[12]=Y*B-H*N+T,_[13]=Y*N+H*B+w,_[14]=1,_[15]=0,this.vertexBuffer)this.device.queue.writeBuffer(this.vertexBuffer,0,_),Z.setVertexBuffer(0,this.vertexBuffer);return Z.draw(4,1,0,0),Z.end(),this.device.queue.submit([J.finish()]),!0}catch{return!1}}clear(){if(!this.isReady()||!this.device||!this.context)return;try{let O=this.device.createCommandEncoder(),$=this.context.getCurrentTexture().createView();O.beginRenderPass({colorAttachments:[{view:$,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]}).end(),this.device.queue.submit([O.finish()])}catch{}}setRotation(O){this.rotation=O}getRotation(){return this.rotation}dispose(){try{if(this.texture)this.texture.destroy(),this.texture=null;if(this.vertexBuffer)this.vertexBuffer.destroy(),this.vertexBuffer=null;this.device=null,this.context=null,this.pipeline=null,this.sampler=null,this.bindGroup=null,this.isInitialized=!1}catch{}}}class F{canvas;powerPreference;constructor(O){this.canvas=O.canvas,this.powerPreference=O.powerPreference||"high-performance"}async createRenderer(O){try{switch(O){case"webgpu":return await this.createWebGPURenderer();case"webgl":return this.createWebGLRenderer();case"canvas2d":return this.createCanvas2DRenderer();default:return null}}catch{return null}}async createRendererWithFallback(O){let $=[O];if(O!=="webgl")$.push("webgl");if(O!=="canvas2d")$.push("canvas2d");for(let Q of $){let V=await this.createRenderer(Q);if(V?.isReady())return{renderer:V,actualType:Q};if(V)V.dispose()}return{renderer:this.createCanvas2DRenderer(),actualType:"canvas2d"}}async createWebGPURenderer(){if(!navigator.gpu)return null;if(!("getContext"in this.canvas))return console.log("WebGPU requires HTMLCanvasElement, not OffscreenCanvas"),null;let $=new t({canvas:this.canvas,powerPreference:this.powerPreference}),A=1000,Q=performance.now();if(await(async()=>{while(!$.isReady()){if(performance.now()-Q>A)return console.log("WebGPU renderer initialization timed out"),!1;if("requestIdleCallback"in window)await new Promise((K)=>requestIdleCallback(()=>K(void 0)));else await new Promise((K)=>requestAnimationFrame(()=>K(void 0)))}return!0})())return console.log("WebGPU renderer initialized successfully"),$;return $.isReady()?$:null}createWebGLRenderer(){try{let O=new s({canvas:this.canvas,powerPreference:this.powerPreference,preserveDrawingBuffer:!1,antialias:!1,alpha:!1});return O.isReady()?O:null}catch{return null}}createCanvas2DRenderer(){return new W({canvas:this.canvas})}static getSupportedRenderers(){let O=[];if(navigator.gpu)O.push("webgpu");try{let A=document.createElement("canvas");if(A.getContext("webgl")||A.getContext("experimental-webgl"))O.push("webgl")}catch{}return O.push("canvas2d"),O}static getRendererDisplayName(O){switch(O){case"canvas2d":return"Canvas 2D";case"webgl":return"WebGL";case"webgpu":return"WebGPU";default:return"Unknown"}}static isRendererSupported(O){if(O==="canvas2d")return!0;return F.getSupportedRenderers().includes(O)}}var a=new WeakMap;function UO(O,$){a.set(O,$)}function WO(O){let $=a.get(O);if($)a.delete(O);return $}class k{canvas=null;canvasSink=null;sampleSink=null;options;frameIterator=null;currentFrame=null;nextFrame=null;disposed=!1;renderingId=0;renderer=null;rendererType="canvas2d";onRendererChange;onRendererFallback;onRotationChange;initPromise=null;resizeObserver=null;lastObservedWidth=0;lastObservedHeight=0;videoAspectRatio=null;debug=!1;pluginManager=null;overlayCanvas=null;overlayCtx=null;lastOverlayTime=0;rotation=0;sourceWidth=0;sourceHeight=0;updateFrameResult={frameUpdated:!1,isStarving:!1};constructor(O={}){if(this.options={poolSize:O.poolSize??2,rendererType:O.rendererType??"webgpu",...O},this.rendererType=this.options.rendererType??"webgpu",this.debug=O.debug??!1,this.initPromise=null,O.canvas){if(this.canvas=O.canvas,this.options.width!==void 0)O.canvas.width=this.options.width;if(this.options.height!==void 0)O.canvas.height=this.options.height;this.initPromise=this.initializeRenderer(O.canvas,this.rendererType).catch(($)=>{if(this.debug)console.error("Failed to initialize renderer:",$)}),this.setupResizeObserver(O.canvas)}}setupResizeObserver(O){if(!("getBoundingClientRect"in O)||typeof ResizeObserver>"u")return;if(this.options.width!==void 0||this.options.height!==void 0)return;this.cleanupResizeObserver();let $=O;this.resizeObserver=new ResizeObserver((A)=>{if(this.disposed||!this.resizeObserver)return;for(let Q of A){let{width:V,height:J}=this.getCanvasDimensionsFromEntry(Q,$);if(V!==this.lastObservedWidth||J!==this.lastObservedHeight){if(this.lastObservedWidth=V,this.lastObservedHeight=J,$.width!==V||$.height!==J){if($.width=V,$.height=J,this.updateCanvasAspectRatio(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}}}});try{this.resizeObserver.observe($,{box:"device-pixel-content-box"})}catch{try{this.resizeObserver.observe($,{box:"content-box"})}catch{this.resizeObserver.observe($)}}requestAnimationFrame(()=>{if(this.disposed||!this.resizeObserver)return;let{width:A,height:Q}=this.getCanvasDimensionsFromCanvas($);if(this.lastObservedWidth=A,this.lastObservedHeight=Q,$.width!==A||$.height!==Q){if($.width=A,$.height=Q,this.updateCanvasAspectRatio(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}})}getCanvasDimensionsFromEntry(O,$){let A=0,Q=0,V=window.devicePixelRatio||1;if(O.devicePixelContentBoxSize?.length)A=O.devicePixelContentBoxSize[0].inlineSize,Q=O.devicePixelContentBoxSize[0].blockSize;else if(O.contentBoxSize?.length)A=Math.round(O.contentBoxSize[0].inlineSize*V),Q=Math.round(O.contentBoxSize[0].blockSize*V);else if(O.contentRect)A=Math.round(O.contentRect.width*V),Q=Math.round(O.contentRect.height*V);if(A===0||Q===0)return this.getCanvasDimensionsFromCanvas($);return{width:Math.max(1,A),height:Math.max(1,Q)}}getCanvasDimensionsFromCanvas(O){let $=0,A=0,Q=window.devicePixelRatio||1,V=O.getBoundingClientRect();if($=Math.round(V.width*Q),A=Math.round(V.height*Q),$===0||A===0)$=Math.round(O.clientWidth*Q)||$,A=Math.round(O.clientHeight*Q)||A;if($===0||A===0)console.warn("Canvas has zero dimensions after all fallbacks, using 1x1");return{width:Math.max(1,$),height:Math.max(1,A)}}cleanupResizeObserver(){if(this.resizeObserver)this.resizeObserver.disconnect(),this.resizeObserver=null,this.lastObservedWidth=0,this.lastObservedHeight=0}retryUntilCanvasReady(O,$,A=60){let Q=0,V=()=>{if(Q++,O.canvas.width>0&&O.canvas.height>0)$();else if(Q<A)requestAnimationFrame(V);else{if(this.debug)console.warn("Canvas dimensions timeout, forcing action");$()}};requestAnimationFrame(V)}updateCanvasAspectRatio(){if(!this.canvas||!this.videoAspectRatio||!("style"in this.canvas))return;this.canvas.style.aspectRatio=this.videoAspectRatio}updateCanvasBackingBuffer(O){let{width:$,height:A}=this.getCanvasDimensionsFromCanvas(O);if(O.width!==$||O.height!==A)return O.width=$,O.height=A,!0;return!1}async initializeRenderer(O,$){if(this.debug)console.log(`Initializing renderer: ${$}`);let Q=await new F({canvas:O}).createRendererWithFallback($);if(this.debug)console.log(`Renderer factory result: ${Q.actualType}`);if(!Q.renderer.isReady()){if(this.debug)console.warn(`VideoRenderer: Renderer (${Q.actualType}) not ready`);throw Q.renderer.dispose(),Error(`Failed to initialize renderer: ${Q.actualType}`)}if(this.renderer=Q.renderer,this.rendererType=Q.actualType,this.debug)console.log(`Initialized renderer: ${this.rendererType}`);if(Q.actualType!==$){if(this.onRendererFallback)this.onRendererFallback($,Q.actualType)}if(this.onRendererChange){if(this.debug)console.log(`Emitting renderer change: ${this.rendererType}`);this.onRendererChange(this.rendererType)}if(this.currentFrame&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log(`Rendering initial frame with ${this.rendererType}`);if(this.currentFrame.canvas.width===0||this.currentFrame.canvas.height===0){if(this.debug)console.log("Initial frame has zero dimensions, scheduling render when ready...");this.retryUntilCanvasReady(this.currentFrame,()=>{if(this.currentFrame&&this.debug)console.log(`Canvas ready (${this.currentFrame.canvas.width}x${this.currentFrame.canvas.height}), rendering initial frame`);if(this.currentFrame)this.renderFrame(this.currentFrame)})}else this.renderFrame(this.currentFrame)}}async setCanvas(O){if(this.cleanupOverlayCanvas(),this.canvas=O,this.renderer)this.renderer.dispose(),this.renderer=null;if(this.options.width!==void 0)O.width=this.options.width;if(this.options.height!==void 0)O.height=this.options.height;this.setupResizeObserver(O);try{await this.initializeRenderer(O,this.rendererType)}catch($){if(this.debug)console.error("Failed to initialize renderer:",$);if(!this.renderer){if(this.renderer=new W({canvas:O}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}async setVideoTrack(O){if(await this.disposeVideoResources(),O.codec===null)throw Error("Unsupported video codec");if(!await O.canDecode())throw Error(`Cannot decode video track with codec: ${O.codec}`);let A=WO(O);if(this.sourceWidth=O.displayWidth,this.sourceHeight=O.displayHeight,!this.videoAspectRatio&&O.displayWidth&&O.displayHeight){let Q=(Z,G)=>G===0?Z:Q(G,Z%G),V=Q(O.displayWidth,O.displayHeight),J=O.displayWidth/V,K=O.displayHeight/V;this.videoAspectRatio=`${J}/${K}`,this.updateCanvasAspectRatio()}if(this.notifyRotationChange(),this.initPromise)try{await this.initPromise}catch(Q){if(this.debug)console.error("Renderer initialization failed:",Q)}if(!this.renderer){if(this.debug)console.warn("Renderer not ready, creating Canvas2D fallback");if(this.canvas){if(this.renderer=new W({canvas:this.canvas}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}if(this.canvas){if(this.options.width!==void 0||this.options.height!==void 0){let Q=this.options.width??O.displayWidth,V=this.options.height??O.displayHeight;if(this.canvas.width!==Q||this.canvas.height!==V)this.canvas.width=Q,this.canvas.height=V,this.updateCanvasAspectRatio()}else if(!this.resizeObserver){if(this.canvas.width===0||this.canvas.height===0)this.canvas.width=O.displayWidth,this.canvas.height=O.displayHeight,this.updateCanvasAspectRatio()}}if(A?.canvasSink)this.canvasSink=A.canvasSink;else this.canvasSink=new SO(O,{rotation:this.options.rotation,poolSize:this.options.poolSize});if(this.sampleSink=new HO(O),this.disposed=!1,A?.firstFrame){if(this.currentFrame=A.firstFrame,this.currentFrame.canvas.width>0&&this.currentFrame.canvas.height>0)this.renderFrame(this.currentFrame);else this.retryUntilCanvasReady(this.currentFrame,()=>{if(this.currentFrame)this.renderFrame(this.currentFrame)},30);this.frameIterator=this.canvasSink.canvases(0),this.frameIterator.next().then(()=>{this.fetchNextFrame()})}else try{await this.seek(0)}catch(Q){if(this.debug)console.error("Initial seek failed:",Q)}requestAnimationFrame(()=>{if(this.resizeObserver&&this.canvas&&"getBoundingClientRect"in this.canvas)this.updateCanvasBackingBuffer(this.canvas);if(this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)})}async seek(O){if(!this.canvasSink)return;this.renderingId++;let $=this.renderingId;if(this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}let A=this.canvasSink.canvases(O);this.frameIterator=A;try{let Q=await A.next(),V=await A.next();if($!==this.renderingId)return;let J=Q.value??null,K=V.value??null;if(J)if(this.currentFrame=J,J.canvas.width>0&&J.canvas.height>0)this.renderFrame(J);else this.retryUntilCanvasReady(J,()=>this.renderFrame(J),30);if(this.nextFrame=K,!this.nextFrame)this.fetchNextFrame()}catch{}}updateFrame(O){let $=this.updateFrameResult;if(this.disposed)return $.frameUpdated=!1,$.isStarving=!1,$;if(!this.nextFrame){if(this.frameIterator)this.fetchNextFrame();return $.frameUpdated=!1,$.isStarving=!0,$}if(this.nextFrame.timestamp<=O){if(this.currentFrame=this.nextFrame,this.nextFrame=null,this.renderFrame(this.currentFrame),this.frameIterator)this.fetchNextFrame();return $.frameUpdated=!0,$.isStarving=!1,$}return $.frameUpdated=!1,$.isStarving=!1,$}async fetchNextFrame(){let O=this.frameIterator;if(!O||this.disposed)return;let $=this.renderingId;try{let Q=(await O.next()).value??null;if(!Q||$!==this.renderingId||this.disposed)return;this.nextFrame=Q}catch{}}renderFrame(O){if(this.currentFrame=O,!this.renderer||!this.canvas){if(this.initPromise)this.initPromise.then(()=>{if(this.currentFrame===O&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log("Rendering frame after renderer initialization");this.renderFrameWithPlugins(O)}});return}if(!this.renderer.isReady()){if(this.debug)console.warn(`VideoRenderer: Renderer (${this.rendererType}) not ready, skipping frame`);return}this.renderFrameWithPlugins(O)}renderFrameWithPlugins(O){if(!this.renderer||!this.canvas)return;let $=O.timestamp;if(this.pluginManager){if(this.pluginManager.executeBeforeRender(O,$)?.skip)return}let A=O;if(this.pluginManager)A=this.pluginManager.executeTransformFrame(O);if(!this.renderer.render(A.canvas)){if(this.debug)console.warn(`Failed to render frame with ${this.rendererType} (canvas: ${A.canvas.width}x${A.canvas.height})`);if(A.canvas.width===0||A.canvas.height===0)this.retryUntilCanvasReady(A,()=>{if(this.currentFrame===O&&this.renderer&&this.renderer.isReady()){if(!this.renderer.render(A.canvas)&&this.debug)console.warn("Retry render also failed")}},1);return}if(this.executeOverlays($),this.pluginManager)this.pluginManager.executeAfterRender(this.canvas)}executeOverlays(O){if(!this.pluginManager||!this.canvas)return;this.lastOverlayTime=O;let $={width:this.canvas.width,height:this.canvas.height};if(this.rendererType==="canvas2d"){let A=this.canvas.getContext("2d");if(!A)return;this.pluginManager.executeOverlays(A,O,$)}else{if(this.ensureOverlayCanvas(),!this.overlayCanvas||!this.overlayCtx)return;this.overlayCtx.clearRect(0,0,this.overlayCanvas.width,this.overlayCanvas.height),this.pluginManager.executeOverlays(this.overlayCtx,O,$)}}refreshOverlays(){if(!this.canvas)return;if(this.rendererType==="canvas2d"){if(this.currentFrame&&this.renderer?.isReady())this.renderer.render(this.currentFrame.canvas),this.executeOverlays(this.lastOverlayTime)}else if(this.overlayCanvas&&this.overlayCtx){if(this.overlayCtx.clearRect(0,0,this.overlayCanvas.width,this.overlayCanvas.height),this.pluginManager){let O={width:this.canvas.width,height:this.canvas.height};this.pluginManager.executeOverlays(this.overlayCtx,this.lastOverlayTime,O)}}}ensureOverlayCanvas(){if(!this.canvas||!(this.canvas instanceof HTMLCanvasElement))return;if(!this.overlayCanvas){this.overlayCanvas=document.createElement("canvas"),this.overlayCanvas.style.position="absolute",this.overlayCanvas.style.top="0",this.overlayCanvas.style.left="0",this.overlayCanvas.style.width="100%",this.overlayCanvas.style.height="100%",this.overlayCanvas.style.pointerEvents="none",this.overlayCanvas.style.zIndex="1",this.overlayCtx=this.overlayCanvas.getContext("2d");let O=this.canvas.parentElement;if(O){if(getComputedStyle(O).position==="static")O.style.position="relative";O.insertBefore(this.overlayCanvas,this.canvas.nextSibling)}}if(this.overlayCanvas.width!==this.canvas.width||this.overlayCanvas.height!==this.canvas.height)this.overlayCanvas.width=this.canvas.width,this.overlayCanvas.height=this.canvas.height}cleanupOverlayCanvas(){if(this.overlayCanvas)this.overlayCanvas.remove(),this.overlayCanvas=null,this.overlayCtx=null}async getFrameAt(O){if(!this.canvasSink)return null;return this.canvasSink.getCanvas(O)}async getSampleAt(O){if(!this.sampleSink)return null;return this.sampleSink.getSample(O)}async extractFrames(O,$,A=1){if(!this.canvasSink)return[];let Q=[],V=[];for(let J=O;J<=$;J+=A)V.push(J);for await(let J of this.canvasSink.canvasesAtTimestamps(V))if(J)Q.push(J);return Q}async screenshot(O,$={}){if(!this.canvas)return null;if(O!==void 0&&this.canvasSink){let A=await this.canvasSink.getCanvas(O);if(A)this.renderFrame(A)}if("toBlob"in this.canvas)return new Promise((A)=>{this.canvas.toBlob((Q)=>A(Q),`image/${$.format??"png"}`,$.quality)});else return this.canvas.convertToBlob({type:`image/${$.format??"png"}`,quality:$.quality})}getCurrentFrame(){return this.currentFrame}getNextFrame(){return this.nextFrame}getRendererType(){return this.rendererType}getCanvas(){return this.canvas}updateCanvasDimensions(){if(!this.canvas||!("getBoundingClientRect"in this.canvas))return;let O=this.canvas;if(this.updateCanvasBackingBuffer(O)&&this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}async switchRenderer(O){if(!this.canvas)throw Error("Cannot switch renderer: No canvas set");let $=this.rendererType;if(O===$)return;if(this.debug)console.warn(`Switching renderer from ${$} to ${O}. This will recreate the canvas element.`);if(this.canvas instanceof HTMLCanvasElement){let A=this.canvas,Q=A.parentElement;if(!Q)throw Error("Cannot switch renderer: Canvas has no parent element");let V=document.createElement("canvas");if(V.width=A.width,V.height=A.height,V.className=A.className,V.id=A.id,V.style.cssText=A.style.cssText,Array.from(A.attributes).forEach((J)=>{if(J.name!=="id"&&J.name!=="class"&&J.name!=="style")V.setAttribute(J.name,J.value)}),this.renderer)this.renderer.dispose(),this.renderer=null;Q.replaceChild(V,A),this.canvas=V;try{await this.initializeRenderer(V,O)}catch(J){if(this.debug)console.error(`Failed to switch to ${O}:`,J);if(!this.renderer){if(this.renderer=new W({canvas:V}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}else{if(this.debug)console.warn("Runtime switching for OffscreenCanvas may not work if context is already set");if(this.renderer)this.renderer.dispose(),this.renderer=null;try{await this.initializeRenderer(this.canvas,O)}catch(A){if(this.debug)console.error(`Failed to switch to ${O}:`,A);if(!this.renderer){if(this.renderer=new W({canvas:this.canvas}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}if(this.currentFrame&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log(`Re-rendering after switch to ${this.rendererType}`);queueMicrotask(()=>{if(this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)})}}setRendererChangeCallback(O){if(this.onRendererChange=O,this.renderer&&this.rendererType){if(this.debug)console.log(`Renderer already initialized as ${this.rendererType}, emitting change event`);O(this.rendererType)}}setRendererFallbackCallback(O){this.onRendererFallback=O}setRotationChangeCallback(O){this.onRotationChange=O}setRotation(O){if(this.rotation===O)return;if(this.rotation=O,this.renderer)this.renderer.setRotation(O);if(this.notifyRotationChange(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}getRotation(){return this.rotation}getDisplaySize(){let O=this.rotation===90||this.rotation===270;return{width:O?this.sourceHeight:this.sourceWidth,height:O?this.sourceWidth:this.sourceHeight}}notifyRotationChange(){if(this.onRotationChange&&this.sourceWidth>0&&this.sourceHeight>0)this.onRotationChange(this.rotation,this.getDisplaySize())}setPluginManager(O){this.pluginManager=O}static getSupportedRenderers(){return F.getSupportedRenderers()}async clearIterators(){if(this.renderingId++,this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}this.currentFrame=null,this.nextFrame=null}async disposeVideoResources(){if(this.disposed=!0,this.renderingId++,this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}this.currentFrame=null,this.nextFrame=null,this.canvasSink=null,this.sampleSink=null,this.videoAspectRatio=null}dispose(){if(this.disposed=!0,this.renderingId++,this.frameIterator)this.frameIterator.return(),this.frameIterator=null;if(this.renderer)this.renderer.dispose(),this.renderer=null;this.cleanupResizeObserver(),this.cleanupOverlayCanvas(),this.currentFrame=null,this.nextFrame=null,this.canvasSink=null,this.sampleSink=null,this.onRendererChange=void 0,this.onRendererFallback=void 0}}var I=2,h="[MediaFox]";function CO(O){I=O}function bO(O,...$){if(I<=0)console.debug(`${h} ${O}`,...$)}function TO(O,...$){if(I<=1)console.info(`${h} ${O}`,...$)}function wO(O,...$){if(I<=2)console.warn(`${h} ${O}`,...$)}function fO(O,...$){if(I<=3)console.error(`${h} ${O}`,...$)}var v={setLevel:CO,debug:bO,info:TO,warn:wO,error:fO};class r{deps;constructor(O){this.deps=O}async load(O,$={}){try{let A=await this.deps.pluginManager.executeBeforeLoad(O);if(A?.cancel)return;if(A?.data!==void 0)O=A.data;await this.deps.playbackController.reset(),this.deps.sourceManager.disposeCurrent();let Q=this.deps.state.getState();if(!$.replacePlaylist)this.deps.state.setState({...Q,state:"loading",currentTime:$.startTime??0,playing:!1,paused:!0,ended:!1,seeking:!1,error:null,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null,buffered:[],canPlay:!1,canPlayThrough:!1});else this.deps.state.reset(),this.deps.state.updateLoadingState();this.deps.emit("loadstart",void 0);let V=$.playlistItemId?this.deps.sourceManager.promoteQueuedSource($.playlistItemId):null;if(!V)V=await this.deps.sourceManager.createSource(O);let J=V.input;if(!J)throw Error("Failed to create input from source");await this.deps.trackManager.initialize(J);let[K,Z,G,j]=await Promise.all([J.computeDuration(),J.getFormat(),J.getMimeType(),J.getMetadataTags()]),U={duration:K,format:Z.name,mimeType:G,metadata:j,hasVideo:this.deps.trackManager.hasVideo(),hasAudio:this.deps.trackManager.hasAudio(),hasSubtitles:this.deps.trackManager.hasSubtitles()};this.deps.state.updateDuration(K),this.deps.state.updateMediaInfo(U),this.deps.state.updateTracks(this.deps.trackManager.getVideoTracks(),this.deps.trackManager.getAudioTracks(),this.deps.trackManager.getSubtitleTracks()),this.deps.playbackController.setDuration(K);let X=V.prefetchedData,z=X?.videoTrack??this.deps.trackManager.getPrimaryVideoTrack(),D=X?.audioTrack??this.deps.trackManager.getPrimaryAudioTrack();if(z&&X?.canvasSink&&X?.firstFrame)UO(z,{canvasSink:X.canvasSink,firstFrame:X.firstFrame});let q="",M=!1,L=!1;if(z||D){let S=await this.deps.trackSwitcher.setupInitialTracks(z,D);q+=S.warningMessage,M=S.videoSupported,L=S.audioSupported}if(!M&&!L){if(!q)q="No audio or video track found.";throw Error(q)}if(q&&(M||L))this.deps.emit("warning",{type:"codec-warning",message:q.trim(),error:void 0});if(this.deps.state.updateReadyState(!0,!0),this.deps.emit("loadedmetadata",U),this.deps.emit("loadeddata",void 0),this.deps.emit("canplay",void 0),this.deps.emit("canplaythrough",void 0),this.updateCurrentPlaylistItemDuration(K),await this.deps.pluginManager.executeAfterLoad(U),$.autoplay)await this.play();if($.startTime!==void 0)await this.seek($.startTime)}catch(A){throw this.handleError(A),A}}async play(){try{if(this.deps.state.getState().state==="idle")throw Error("No media loaded");if((await this.deps.pluginManager.executeBeforePlay())?.cancel)return;await this.deps.playbackController.play(),this.deps.state.updatePlaybackState(!0),this.deps.emit("play",void 0),this.deps.emit("playing",void 0),this.deps.pluginManager.executeAfterPlay()}catch(O){throw this.handleError(O),O}}async pause(){if((await this.deps.pluginManager.executeBeforePause())?.cancel)return;this.deps.playbackController.pause(),this.deps.state.updatePlaybackState(!1),this.deps.emit("pause",void 0),this.deps.pluginManager.executeAfterPause()}async seek(O){try{if(this.deps.state.getState().state==="idle")throw Error("No media loaded");let A=await this.deps.pluginManager.executeBeforeSeek(O);if(A?.cancel)return;if(A?.data!==void 0)O=A.data;this.deps.state.updateSeekingState(!0),this.deps.emit("seeking",{currentTime:O}),await this.deps.playbackController.seek(O),this.deps.state.updateSeekingState(!1),this.deps.state.updateTime(this.deps.playbackController.getCurrentTime()),this.deps.emit("seeked",{currentTime:this.deps.playbackController.getCurrentTime()}),this.deps.pluginManager.executeAfterSeek(this.deps.playbackController.getCurrentTime())}catch($){throw this.deps.state.updateSeekingState(!1),this.handleError($),$}}async stop(){try{if((await this.deps.pluginManager.executeBeforeStop())?.cancel)return;await this.pause(),await this.seek(0),this.deps.pluginManager.executeAfterStop()}catch(O){throw this.handleError(O),O}}handleError(O){if(this.deps.pluginManager.executeOnError(O))return;this.deps.state.updateError(O),this.deps.emit("error",O),v.error("Player error:",O)}updateCurrentPlaylistItemDuration(O){let $=this.deps.state.getState(),A=$.currentPlaylistIndex;if(A!==null&&$.playlist.length>0){let Q=[...$.playlist],V=Q[A];if(V)Q[A]={...V,duration:O},this.deps.state.updatePlaylist(Q,A)}}}class e{store;constructor(O){this.store=O}getState(){return this.store.getState()}subscribe(O){return this.store.subscribe(O)}setState(O){this.store.setState(O)}reset(){this.store.reset()}applyInitial(O,$,A){this.store.setState({volume:O,muted:$,playbackRate:A})}updateLoadingState(){this.store.updateLoadingState()}updateReadyState(O,$){this.store.updateReadyState(O,$)}updatePlaybackState(O){this.store.updatePlaybackState(O)}updateSeekingState(O){this.store.updateSeekingState(O)}updateWaitingState(O){this.store.updateWaitingState(O)}updateEndedState(O){this.store.updateEndedState(O)}updateTime(O){this.store.updateTime(O)}updateDuration(O){this.store.updateDuration(O)}updateVolume(O,$){this.store.updateVolume(O,$)}updatePlaybackRate(O){this.store.updatePlaybackRate(O)}updateMediaInfo(O){this.store.updateMediaInfo(O)}updateTracks(O,$,A){this.store.updateTracks(O,$,A)}updateSelectedTracks(O,$){this.store.updateSelectedTracks(O,$)}updateError(O){this.store.updateError(O)}updateRendererType(O){this.store.updateRendererType(O)}updatePlaylist(O,$=null){this.store.updatePlaylist(O,$)}}class OO{chains=new Map;async run(O,$){let A=this.chains.get(O)??Promise.resolve(),Q,V=new Promise((J)=>{Q=J});this.chains.set(O,A.then(()=>V));try{return await A,await $()}finally{Q?.()}}}class $O{deps;locks=new OO;constructor(O){this.deps=O}async setupInitialTracks(O,$){let A=!1,Q=!1,V="";if(O)try{if(A=await this.locks.run("video",async()=>{if(O.codec!==null&&await O.canDecode())return await this.deps.playbackController.trySetVideoTrack(O);return!1}),!A)V+="Unsupported video codec. "}catch(J){V+="Failed to set up video track. ",v.warn("Video track error:",J)}if($)try{if(Q=await this.locks.run("audio",async()=>{if($.codec!==null&&await $.canDecode())return await this.deps.playbackController.trySetAudioTrack($);return!1}),!Q)V+="Unsupported audio codec. "}catch(J){V+="Failed to set up audio track. ",v.warn("Audio track error:",J)}if(!A&&!Q&&!V)V="No audio or video track found.";return{videoSupported:A,audioSupported:Q,warningMessage:V}}async selectVideoTrack(O,$){if(!O.selectVideoTrack($))throw Error(`Invalid video track ID: ${$}`);let A=O.getSelectedVideoTrack();if(!A){await this.deps.playbackController.setVideoTrack(null);return}if(!await this.locks.run("video",async()=>{if(A.codec!==null&&await A.canDecode())return await this.deps.playbackController.trySetVideoTrack(A);return!1}))this.deps.emit("warning",{type:"video-codec-unsupported",message:"Video codec not supported.",error:void 0}),await this.deps.playbackController.setVideoTrack(null)}async selectAudioTrack(O,$){if(!O.selectAudioTrack($))throw Error(`Invalid audio track ID: ${$}`);let A=O.getSelectedAudioTrack();if(!A){await this.deps.playbackController.setAudioTrack(null);return}if(!await this.locks.run("audio",async()=>{if(A.codec!==null&&await A.canDecode())return await this.deps.playbackController.trySetAudioTrack(A);return!1}))this.deps.emit("warning",{type:"audio-codec-unsupported",message:"Audio codec not supported. Continuing without audio.",error:void 0}),await this.deps.playbackController.setAudioTrack(null)}}import{AudioBufferSink as xO,AudioSampleSink as yO}from"mediabunny";class p{audioContext;gainNode=null;outputNode=null;bufferSink=null;sampleSink=null;bufferIterator=null;queuedNodes=new Set;startContextTime=0;startMediaTime=0;pauseTime=0;playing=!1;volume=1;muted=!1;disposed=!1;playbackId=0;playbackRate=1;pluginManager=null;constructor(O={}){if(O.audioContext)this.audioContext=O.audioContext;else{let $=window,A=$.AudioContext||$.webkitAudioContext;this.audioContext=new A}this.volume=O.volume??1,this.muted=O.muted??!1,this.setupAudioGraph()}setupAudioGraph(){if(this.gainNode=this.audioContext.createGain(),this.pluginManager){let O=this.pluginManager.executeOnAudioNode(this.audioContext,this.gainNode);this.outputNode=O}else this.outputNode=this.gainNode;this.outputNode.connect(this.audioContext.destination),this.updateGain()}setPluginManager(O){this.pluginManager=O,this.rebuildAudioGraph()}rebuildAudioGraph(){if(!this.gainNode)return;if(this.outputNode?.disconnect(),this.pluginManager){let O=this.pluginManager.executeOnAudioNode(this.audioContext,this.gainNode);this.outputNode=O}else this.outputNode=this.gainNode;this.outputNode.connect(this.audioContext.destination)}async setAudioTrack(O){if(this.dispose(),O.codec===null)throw Error("Unsupported audio codec");if(!await O.canDecode())throw Error(`Cannot decode audio track with codec: ${O.codec}`);this.bufferSink=new xO(O),this.sampleSink=new yO(O),this.disposed=!1}async play(O=this.pauseTime){if(this.playing||!this.bufferSink)return;if(this.audioContext.state==="suspended")await this.audioContext.resume();this.playbackId++;let $=this.playbackId;this.playing=!0,this.startContextTime=this.audioContext.currentTime,this.startMediaTime=O,this.pauseTime=O,this.bufferIterator=this.bufferSink.buffers(O),this.scheduleAudioBuffers($)}async scheduleAudioBuffers(O){let $=this.bufferIterator;if(!$||!this.gainNode)return;try{for await(let{buffer:A,timestamp:Q}of $){if(O!==this.playbackId||this.disposed||!this.playing)break;let V=this.audioContext.createBufferSource();V.buffer=A,V.connect(this.gainNode),V.playbackRate.value=this.playbackRate,V.playbackRate.setValueAtTime(this.playbackRate,this.audioContext.currentTime);let J=this.startContextTime+(Q-this.startMediaTime)/this.playbackRate;if(J>=this.audioContext.currentTime)V.start(J);else{let K=Math.max(0,(this.audioContext.currentTime-J)*this.playbackRate);if(K<A.duration)V.start(this.audioContext.currentTime,K);else continue}if(this.queuedNodes.add(V),V.onended=()=>{this.queuedNodes.delete(V)},Q-this.getCurrentTime()>=1)await this.waitForCatchup(Q)}}catch{}}async waitForCatchup(O){return new Promise(($)=>{let A=setInterval(()=>{if(O-this.getCurrentTime()<1||!this.playing)clearInterval(A),$()},100)})}pause(){if(!this.playing)return;let O=this.getCurrentTime();if(this.playing=!1,this.pauseTime=O,this.stopQueuedNodes(),this.bufferIterator)this.bufferIterator.return(),this.bufferIterator=null}stop(){this.pause(),this.pauseTime=0,this.startContextTime=0,this.startMediaTime=0}async seek(O){let $=this.playing;if($)this.pause();if(this.pauseTime=O,$)await this.play(O)}getCurrentTime(){if(this.playing){let O=this.audioContext.currentTime-this.startContextTime;return this.startMediaTime+O*this.playbackRate}return this.pauseTime}setVolume(O){this.volume=Math.max(0,Math.min(1,O)),this.updateGain()}setMuted(O){this.muted=O,this.updateGain()}updateGain(){if(!this.gainNode)return;let O=this.muted?0:this.volume;this.gainNode.gain.value=O*O}getVolume(){return this.volume}isMuted(){return this.muted}isPlaying(){return this.playing}setPlaybackRate(O){let $=Math.max(0.25,Math.min(4,O));if(this.playbackRate===$)return;let A=this.playing,Q=this.getCurrentTime();if(this.playbackRate=$,A)this.pause(),this.pauseTime=Q,this.play(Q)}getAudioContext(){return this.audioContext}async getBufferAt(O){if(!this.bufferSink)return null;return this.bufferSink.getBuffer(O)}async getSampleAt(O){if(!this.sampleSink)return null;return this.sampleSink.getSample(O)}stopQueuedNodes(){for(let O of this.queuedNodes)try{O.stop()}catch{}this.queuedNodes.clear()}async clearIterators(){if(this.playbackId++,this.stop(),this.bufferIterator){try{await this.bufferIterator.return()}catch{}this.bufferIterator=null}}dispose(){if(this.disposed=!0,this.playbackId++,this.stop(),this.bufferIterator)this.bufferIterator.return(),this.bufferIterator=null;this.bufferSink=null,this.sampleSink=null}destroy(){if(this.dispose(),this.gainNode)this.gainNode.disconnect(),this.gainNode=null;if(this.audioContext.state!=="closed")this.audioContext.close()}}var IO=100,vO=250;class g{videoRenderer;audioManager;playing=!1;currentTime=0;duration=0;playbackRate=1;animationFrameId=null;lastFrameTime=0;syncIntervalId=null;renderIntervalId=null;isWaiting=!1;onTimeUpdate;onEnded;onWaiting;onPlaying;constructor(O={}){this.videoRenderer=new k({canvas:O.canvas,rendererType:O.rendererType}),this.audioManager=new p({audioContext:O.audioContext,volume:O.volume,muted:O.muted}),this.playbackRate=O.playbackRate??1}async setVideoTrack(O){if(!O){this.videoRenderer.dispose();return}await this.videoRenderer.setVideoTrack(O);let $=await O.computeDuration();this.duration=Math.max(this.duration,$)}async trySetVideoTrack(O){try{return await this.setVideoTrack(O),!0}catch{return!1}}async setAudioTrack(O){let $=this.playing,A=this.getCurrentTime();if(!O){this.audioManager.dispose();return}let Q=await O.computeDuration(),V=Math.max(0,Math.min(A,Q));if(await this.audioManager.setAudioTrack(O),await this.audioManager.seek(V),$)await this.audioManager.play(V);this.currentTime=V,this.duration=Math.max(this.duration,Q)}async trySetAudioTrack(O){try{return await this.setAudioTrack(O),!0}catch{return!1}}async setCanvas(O){await this.videoRenderer.setCanvas(O)}async play(){if(this.playing)return;if(this.playing=!0,this.lastFrameTime=performance.now(),this.currentTime>=this.duration)this.currentTime=0,await this.videoRenderer.seek(0);await this.audioManager.play(this.currentTime),this.startRenderLoop(),this.startSyncInterval()}pause(){if(!this.playing)return;if(this.playing=!1,this.isWaiting=!1,this.audioManager.pause(),this.stopRenderLoop(),this.stopSyncInterval(),this.audioManager.isPlaying())this.currentTime=this.audioManager.getCurrentTime()}async seek(O){let $=Math.max(0,Math.min(O,this.duration));if(this.currentTime=$,await this.videoRenderer.seek($),await this.audioManager.seek($),this.onTimeUpdate)this.onTimeUpdate(this.currentTime)}startRenderLoop(){if(this.animationFrameId!==null||this.renderIntervalId!==null)return;let O=($=!0)=>{if(!this.playing)return;if(this.audioManager.isPlaying())this.currentTime=this.audioManager.getCurrentTime();else{let Q=performance.now(),V=(Q-this.lastFrameTime)/1000;this.lastFrameTime=Q,this.currentTime+=V*this.playbackRate}if(this.currentTime>=this.duration){this.handleEnded();return}let{isStarving:A}=this.videoRenderer.updateFrame(this.currentTime);if(A&&!this.isWaiting){if(this.isWaiting=!0,this.onWaiting)this.onWaiting()}else if(!A&&this.isWaiting){if(this.isWaiting=!1,this.onPlaying)this.onPlaying()}if($)this.animationFrameId=requestAnimationFrame(()=>O())};if(this.animationFrameId=requestAnimationFrame(()=>O()),this.renderIntervalId===null)this.renderIntervalId=window.setInterval(()=>O(!1),IO)}stopRenderLoop(){if(this.animationFrameId!==null)cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null;if(this.renderIntervalId!==null)clearInterval(this.renderIntervalId),this.renderIntervalId=null}startSyncInterval(){if(this.syncIntervalId!==null)return;this.syncIntervalId=window.setInterval(()=>{if(this.playing&&this.onTimeUpdate)this.onTimeUpdate(this.currentTime)},vO)}stopSyncInterval(){if(this.syncIntervalId!==null)clearInterval(this.syncIntervalId),this.syncIntervalId=null}handleEnded(){if(this.pause(),this.currentTime=this.duration,this.onEnded)this.onEnded()}getCurrentTime(){if(this.playing&&this.audioManager.isPlaying())return this.audioManager.getCurrentTime();return this.currentTime}getDuration(){return this.duration}setDuration(O){this.duration=O}isPlaying(){return this.playing}setVolume(O){this.audioManager.setVolume(O)}getVolume(){return this.audioManager.getVolume()}setMuted(O){this.audioManager.setMuted(O)}isMuted(){return this.audioManager.isMuted()}setPlaybackRate(O){let $=Math.max(0.25,Math.min(4,O));if(this.playbackRate===$)return;this.playbackRate=$,this.audioManager.setPlaybackRate($),this.lastFrameTime=performance.now()}getPlaybackRate(){return this.playbackRate}setTimeUpdateCallback(O){this.onTimeUpdate=O}setEndedCallback(O){this.onEnded=O}setWaitingCallback(O){this.onWaiting=O}setPlayingCallback(O){this.onPlaying=O}isBuffering(){return this.isWaiting}async screenshot(O){return this.videoRenderer.screenshot(this.currentTime,O)}getVideoRenderer(){return this.videoRenderer}getAudioManager(){return this.audioManager}async switchRenderer(O){await this.videoRenderer.switchRenderer(O)}getRendererType(){return this.videoRenderer.getRendererType()}updateCanvasDimensions(){this.videoRenderer.updateCanvasDimensions()}setRendererChangeCallback(O){this.videoRenderer.setRendererChangeCallback(O)}setRendererFallbackCallback(O){this.videoRenderer.setRendererFallbackCallback(O)}setRotationChangeCallback(O){this.videoRenderer.setRotationChangeCallback(O)}setRotation(O){this.videoRenderer.setRotation(O)}getRotation(){return this.videoRenderer.getRotation()}getDisplaySize(){return this.videoRenderer.getDisplaySize()}setPluginManager(O){this.videoRenderer.setPluginManager(O),this.audioManager.setPluginManager(O)}getCanvas(){return this.videoRenderer.getCanvas()}refreshOverlays(){this.videoRenderer.refreshOverlays()}rebuildAudioGraph(){this.audioManager.rebuildAudioGraph()}async reset(){this.pause(),this.stopRenderLoop(),this.stopSyncInterval(),this.currentTime=0,this.duration=0,await Promise.all([this.videoRenderer.clearIterators(),this.audioManager.clearIterators()]),this.playbackRate=1,this.lastFrameTime=0}dispose(){this.pause(),this.videoRenderer.dispose(),this.audioManager.dispose(),this.onTimeUpdate=void 0,this.onEnded=void 0,this.onWaiting=void 0,this.onPlaying=void 0}destroy(){this.dispose(),this.audioManager.destroy()}}function m(){return crypto?.randomUUID?.()??Date.now().toString(36)+Math.random().toString(36).substr(2)}class AO{store;emitter;switchSource;sourceManager;constructor(O,$,A,Q){this.store=O,this.emitter=$,this.switchSource=A,this.sourceManager=Q}async loadPlaylist(O,$={}){let A=O.map((Q)=>{if(Q&&typeof Q==="object"&&"mediaSource"in Q)return{id:m(),mediaSource:Q.mediaSource,title:Q.title,poster:Q.poster,savedPosition:null,duration:null};else return{id:m(),mediaSource:Q,savedPosition:null,duration:null}});if(this.store.updatePlaylist(A,A.length>0?0:null),this.emitter.emit("playlistchange",{playlist:A}),A.length>0&&this.switchSource){let Q=A[0];if($.startTime!==void 0)Q.savedPosition=$.startTime;await this.switchSource(Q,$.autoplay??!1)}}addToPlaylist(O,$){let A=this.createPlaylistItem(O);this.store.addToPlaylist(A,$),this.emitter.emit("playlistadd",{item:A,index:$??this.store.getState().playlist.length-1})}async removeFromPlaylist(O){let $=this.store.getState(),A=$.currentPlaylistIndex,Q=$.playing;this.store.removeFromPlaylist(O),this.emitter.emit("playlistremove",{index:O}),this.sourceManager?.disposeQueued($.playlist[O]?.id||"");let V=this.store.getState(),J=V.currentPlaylistIndex;if(V.playlist.length===0)this.sourceManager?.disposeAll(),this.emitter.emit("playlistchange",{playlist:V.playlist}),this.emitter.emit("playlistend",void 0);if(A===O&&J!==null&&J!==A&&this.switchSource){let K=V.playlist[J];try{await this.switchSource(K,Q)}catch(Z){this.emitter.emit("playlistitemerror",{index:J,error:Z})}}}clearPlaylist(){this.store.clearPlaylist(),this.emitter.emit("playlistchange",{playlist:[]}),this.emitter.emit("playlistend",void 0),this.sourceManager?.disposeAll()}async next(){let O=this.store.getState(),$=O.currentPlaylistIndex??0,A=O.playlist,Q=O.playlistMode,V=null;if(Q==="repeat-one")V=$;else if(Q==="sequential"||Q==="repeat")if($<A.length-1)V=$+1;else if(Q==="repeat")V=0;else{this.emitter.emit("playlistend",void 0);return}else if($<A.length-1)V=$+1;if(V!==null)await this.switchTo(V)}async prev(){let $=this.store.getState().currentPlaylistIndex??0;if($>0)await this.switchTo($-1)}async jumpTo(O){let A=this.store.getState().playlist;if(O>=0&&O<A.length)await this.switchTo(O);else if(O>=A.length)this.emitter.emit("playlistend",void 0)}setMode(O){let $=["sequential","manual","repeat","repeat-one",null];if(!$.includes(O))throw Error(`Invalid playlist mode: ${O}. Valid modes: ${$.filter((A)=>A!==null).join(", ")}, null`);this.store.updatePlaylistMode(O)}async switchTo(O){let $=this.store.getState(),A=$.currentPlaylistIndex,Q=$.playing,V=[...$.playlist];if(A!==null&&A!==O){let Z=V[A];V[A]={...Z,savedPosition:$.currentTime}}this.store.updatePlaylist(V,O);let J=V[O];if(this.emitter.emit("playlistitemchange",{index:O,item:J,previousIndex:A??void 0}),this.switchSource)await this.switchSource(J,Q);if($.playlistMode==="sequential"&&O<V.length-1){let Z=V[O+1];this.sourceManager?.preloadSource(Z.mediaSource,Z.id)}}createPlaylistItem(O){if(O&&typeof O==="object"&&"mediaSource"in O)return{id:m(),mediaSource:O.mediaSource,title:O.title,poster:O.poster,savedPosition:null,duration:null};else return{id:m(),mediaSource:O,savedPosition:null,duration:null}}get playlist(){return this.store.getState().playlist}get currentIndex(){return this.store.getState().currentPlaylistIndex}get currentItem(){let O=this.currentIndex;return O!==null?this.playlist[O]:null}get mode(){return this.store.getState().playlistMode}dispose(){if(this.sourceManager)this.sourceManager=void 0;this.switchSource=void 0}}function XO(O,$,A,Q){let V=$.name;return{player:O,getState(){return O.getState()},subscribe(J){let K=O.subscribe(J),Z=()=>K.unsubscribe();return A.stateUnsubscribes.push(Z),Z},getPluginState(){return A.pluginState},setPluginState(J){A.pluginState=J},on(J,K){O.on(J,K);let Z=A.eventListeners.get(J);if(!Z)Z=new Set,A.eventListeners.set(J,Z);Z.add(K)},off(J,K){O.off(J,K);let Z=A.eventListeners.get(J);if(Z)Z.delete(K)},getCanvas(){return O.getRenderTarget()},getPlugin(J){return Q().get(J)?.plugin},hasPlugin(J){return Q().has(J)},log(...J){console.log(`[MediaFox:${V}]`,...J)},warn(...J){console.warn(`[MediaFox:${V}]`,...J)},error(...J){console.error(`[MediaFox:${V}]`,...J)}}}class QO{player;plugins=new Map;overlays=[];overlaysSorted=!1;registrationCounter=0;constructor(O){this.player=O}async install(O){let{name:$}=O;if(this.plugins.has($))throw Error(`Plugin "${$}" is already installed`);if(O.dependencies){for(let Q of O.dependencies)if(!this.plugins.has(Q))throw Error(`Plugin "${$}" requires plugin "${Q}" to be installed first`)}let A={plugin:O,context:null,eventListeners:new Map,stateUnsubscribes:[],pluginState:void 0};A.context=XO(this.player,O,A,()=>this.plugins),this.plugins.set($,A);try{await O.install(A.context)}catch(Q){throw this.plugins.delete($),Q}if(O.hooks?.render?.onOverlay)this.overlays.push({pluginName:$,zIndex:O.hooks.render.onOverlay.zIndex??0,registrationOrder:this.registrationCounter++,render:O.hooks.render.onOverlay}),this.overlaysSorted=!1,this.player.refreshOverlays()}async uninstall(O){let $=this.plugins.get(O);if(!$)throw Error(`Plugin "${O}" is not installed`);try{await $.plugin.uninstall?.()}catch(Q){console.error(`Error uninstalling plugin "${O}":`,Q)}for(let[Q,V]of $.eventListeners)for(let J of V)this.player.off(Q,J);for(let Q of $.stateUnsubscribes)Q();let A=this.overlays.some((Q)=>Q.pluginName===O);if(this.overlays=this.overlays.filter((Q)=>Q.pluginName!==O),this.plugins.delete(O),A)this.player.refreshOverlays()}has(O){return this.plugins.has(O)}get size(){return this.plugins.size}async executeBeforeLoad(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.beforeLoad;if(!A)continue;try{let Q=await A.call($.plugin,O);if(Q?.cancel)return Q;if(Q?.data!==void 0)O=Q.data}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in beforeLoad hook:`,Q)}}return{data:O}}async executeAfterLoad(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.afterLoad;if(!A)continue;try{await A.call($.plugin,O)}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in afterLoad hook:`,Q)}}}async executeBeforePlay(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforePlay;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforePlay hook:`,A)}}return}executeAfterPlay(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterPlay;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterPlay hook:`,A)}}}async executeBeforePause(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforePause;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforePause hook:`,A)}}return}executeAfterPause(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterPause;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterPause hook:`,A)}}}async executeBeforeSeek(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.beforeSeek;if(!A)continue;try{let Q=await A.call($.plugin,O);if(Q?.cancel)return Q;if(Q?.data!==void 0)O=Q.data}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in beforeSeek hook:`,Q)}}return{data:O}}executeAfterSeek(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.afterSeek;if(!A)continue;try{A.call($.plugin,O)}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in afterSeek hook:`,Q)}}}async executeBeforeStop(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforeStop;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforeStop hook:`,A)}}return}executeAfterStop(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterStop;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterStop hook:`,A)}}}executeOnError(O){let $=!1;for(let[,A]of this.plugins){let Q=A.plugin.hooks?.lifecycle?.onError;if(!Q)continue;try{if(Q.call(A.plugin,O)?.handled)$=!0}catch(V){console.error(`[MediaFox:${A.plugin.name}] Error in onError hook:`,V)}}return $}executeOnEnded(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.onEnded;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in onEnded hook:`,A)}}}executeBeforeRender(O,$){for(let[,A]of this.plugins){let Q=A.plugin.hooks?.render?.beforeRender;if(!Q)continue;try{let V=Q.call(A.plugin,O,$);if(V?.skip)return V}catch(V){console.error(`[MediaFox:${A.plugin.name}] Error in beforeRender hook:`,V)}}return}executeTransformFrame(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.render?.transformFrame;if(!A)continue;try{let Q=A.call($.plugin,O);if(Q)O=Q}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in transformFrame hook:`,Q)}}return O}executeAfterRender(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.render?.afterRender;if(!A)continue;try{A.call($.plugin,O)}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in afterRender hook:`,Q)}}}executeOverlays(O,$,A){if(this.overlays.length===0)return;if(!this.overlaysSorted)this.overlays.sort((Q,V)=>{if(Q.zIndex!==V.zIndex)return Q.zIndex-V.zIndex;return Q.registrationOrder-V.registrationOrder}),this.overlaysSorted=!0;for(let Q of this.overlays)try{Q.render?.render(O,$,A)}catch(V){console.error(`[MediaFox:${Q.pluginName}] Error in onOverlay hook:`,V)}}executeBeforeStateUpdate(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.state?.beforeStateUpdate;if(!A)continue;try{let Q=A.call($.plugin,O);if(Q===null)return null;if(Q!==void 0)O=Q}catch(Q){console.error(`[MediaFox:${$.plugin.name}] Error in beforeStateUpdate hook:`,Q)}}return O}executeOnStateChange(O,$){for(let[,A]of this.plugins){let Q=A.plugin.hooks?.state?.onStateChange;if(!Q)continue;try{Q.call(A.plugin,O,$)}catch(V){console.error(`[MediaFox:${A.plugin.name}] Error in onStateChange hook:`,V)}}}executeBeforeEvent(O,$){for(let[,A]of this.plugins){let Q=A.plugin.hooks?.event?.beforeEvent;if(!Q)continue;try{let V=Q.call(A.plugin,O,$);if(V?.cancel)return V;if(V?.data!==void 0)$=V.data}catch(V){console.error(`[MediaFox:${A.plugin.name}] Error in beforeEvent hook:`,V)}}return{data:$}}executeAfterEvent(O,$){for(let[,A]of this.plugins){let Q=A.plugin.hooks?.event?.afterEvent;if(!Q)continue;try{Q.call(A.plugin,O,$)}catch(V){console.error(`[MediaFox:${A.plugin.name}] Error in afterEvent hook:`,V)}}}executeOnAudioNode(O,$){let A=$;for(let[,Q]of this.plugins){let V=Q.plugin.hooks?.audio?.onAudioNode;if(!V)continue;try{let J=V.call(Q.plugin,O,$);if(J)A=J}catch(J){console.error(`[MediaFox:${Q.plugin.name}] Error in onAudioNode hook:`,J)}}return A}async dispose(){let O=Array.from(this.plugins.keys()).reverse();for(let $ of O)try{await this.uninstall($)}catch(A){console.error(`Error disposing plugin "${$}":`,A)}}}import{ALL_FORMATS as kO,BlobSource as hO,BufferSource as pO,CanvasSink as gO,FilePathSource as mO,Input as uO,ReadableStreamSource as lO,UrlSource as cO}from"mediabunny";class u{currentSource=null;queuedSources=new Map;options;constructor(O={}){this.options={maxCacheSize:O.maxCacheSize??16777216,crossOrigin:O.crossOrigin,requestInit:O.requestInit}}async createSource(O,$){if(this.currentSource&&!$)this.disposeCurrent();let A,Q;if(O instanceof File||O instanceof Blob)A=new hO(O,{maxCacheSize:this.options.maxCacheSize}),Q="blob";else if(O instanceof ArrayBuffer||O instanceof Uint8Array)A=new pO(O),Q="buffer";else if(typeof O==="string"||O instanceof URL){let K=O instanceof URL?O.href:O;if(typeof window>"u"&&!K.startsWith("http"))A=new mO(K,{maxCacheSize:this.options.maxCacheSize}),Q="file";else A=new cO(K,{maxCacheSize:this.options.maxCacheSize,requestInit:this.options.requestInit}),Q="url"}else if(typeof ReadableStream<"u"&&O instanceof ReadableStream)A=new lO(O,{maxCacheSize:this.options.maxCacheSize}),Q="stream";else throw TypeError("Unsupported media source type");let V=new uO({source:A,formats:kO}),J={source:A,input:V,type:Q,originalSource:O};if($)this.queuedSources.set($,J);else this.currentSource=J;return J}getCurrentSource(){return this.currentSource}getQueuedSource(O){return this.queuedSources.get(O)||null}async preloadSource(O,$){if(this.queuedSources.has($))return;let A=await this.createSource(O,$);if(A.input)try{let Q=await this.prefetchTrackData(A.input);A.prefetchedData=Q}catch{}}async prefetchTrackData(O){let $=await O.getVideoTracks(),A=await O.getAudioTracks(),Q=$.length>0?$[0]:null,V=A.length>0?A[0]:null,J=null,K=null,Z=0;if(Q){if(Q.codec!==null&&await Q.canDecode()){J=new gO(Q,{poolSize:2});let G=J.canvases(0);K=(await G.next()).value??null,await G.return(),Z=await Q.computeDuration()}}if(!Z&&V)Z=await V.computeDuration();return{videoTrack:Q,audioTrack:V,canvasSink:J,firstFrame:K,duration:Z}}promoteQueuedSource(O){let $=this.queuedSources.get(O);if(!$)return null;if(this.queuedSources.delete(O),this.currentSource)this.currentSource.input?.dispose();return this.currentSource=$,$}getOriginalSource(){return this.currentSource?.originalSource??null}disposeCurrent(){if(this.currentSource)this.currentSource.input?.dispose(),this.currentSource=null}disposeQueued(O){let $=this.queuedSources.get(O);if($)$.input?.dispose(),this.queuedSources.delete(O)}disposeAll(){this.disposeCurrent(),this.queuedSources.forEach((O,$)=>{this.disposeQueued($)}),this.queuedSources.clear()}dispose(){this.disposeAll()}static isStreamingSource(O){return O instanceof ReadableStream||typeof O==="string"&&O.startsWith("http")}static isLocalSource(O){return O instanceof File||O instanceof Blob||O instanceof ArrayBuffer||O instanceof Uint8Array||typeof O==="string"&&!O.startsWith("http")}static getSourceType(O){if(O instanceof File)return"file";if(O instanceof Blob)return"blob";if(O instanceof ArrayBuffer||O instanceof Uint8Array)return"buffer";if(O instanceof ReadableStream)return"stream";if(typeof O==="string"||O instanceof URL)return(O instanceof URL?O.href:O).startsWith("http")?"url":"file";return"unknown"}static async fromFetch(O,$){let A=await fetch(O,$);if(!A.ok)throw Error(`Failed to fetch: ${A.status} ${A.statusText}`);return A.blob()}static fromStreamingFetch(O,$){return new ReadableStream({async start(A){let Q=await fetch(O,$);if(!Q.ok){A.error(Error(`Failed to fetch: ${Q.status} ${Q.statusText}`));return}let V=Q.body?.getReader();if(!V){A.error(Error("Response body is not readable"));return}try{while(!0){let{done:J,value:K}=await V.read();if(J)break;A.enqueue(K)}A.close()}catch(J){A.error(J)}}})}}function l(O,$){if(Object.is(O,$))return!0;if(typeof O!==typeof $)return!1;if(O===null||$===null)return O===$;if(Array.isArray(O)&&Array.isArray($)){if(O.length!==$.length)return!1;for(let A=0;A<O.length;A++)if(!l(O[A],$[A]))return!1;return!0}if(LO(O)&&LO($)){let A=Object.keys(O),Q=Object.keys($);if(A.length!==Q.length)return!1;for(let V of A){if(!Object.hasOwn($,V))return!1;if(!l(O[V],$[V]))return!1}return!0}return!1}function LO(O){return typeof O==="object"&&O!==null&&O.constructor===Object}class c{state;previousState;listeners=new Set;updateScheduled=!1;pendingUpdates={};pendingKeys=[];pluginManager=null;listenerCache=[];constructor(){this.state=this.getInitialState(),this.previousState={...this.state}}setPluginManager(O){this.pluginManager=O}getInitialState(){let $=F.getSupportedRenderers()[0]||"canvas2d";return{state:"idle",currentTime:0,duration:0,buffered:[],volume:1,muted:!1,playbackRate:1,playing:!1,paused:!0,ended:!1,seeking:!1,waiting:!1,error:null,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null,canPlay:!1,canPlayThrough:!1,isLive:!1,rendererType:$,playlist:[],currentPlaylistIndex:null,playlistMode:null,rotation:0,displaySize:{width:0,height:0}}}getState(){return this.state}setState(O){if(this.pluginManager){let A=this.pluginManager.executeBeforeStateUpdate(O);if(A===null)return;O=A}let $=Object.keys(O);for(let A=0;A<$.length;A++){let Q=$[A];if(this.pendingUpdates[Q]===void 0)this.pendingKeys.push(Q);this.setPendingValue(Q,O[Q])}if(!this.updateScheduled)this.updateScheduled=!0,queueMicrotask(()=>this.flushUpdates())}setPendingValue(O,$){this.pendingUpdates[O]=$}flushUpdates(){let O=this.pendingKeys;if(O.length===0){this.updateScheduled=!1;return}let $=!1;for(let A=0;A<O.length;A++){let Q=O[A];if(!l(this.pendingUpdates[Q],this.state[Q])){$=!0;break}}for(let A=0;A<O.length;A++){let Q=O[A];this.copyStateKey(Q)}if(this.pendingUpdates={},this.pendingKeys.length=0,this.updateScheduled=!1,$){if(this.notifyListeners(),this.pluginManager)this.pluginManager.executeOnStateChange(this.state,this.previousState)}}copyStateKey(O){if(this.previousState[O]=this.state[O],O in this.pendingUpdates)this.state[O]=this.pendingUpdates[O]}subscribe(O){return this.listeners.add(O),O(this.getState()),()=>{this.listeners.delete(O)}}reset(){this.state=this.getInitialState(),this.pendingUpdates={},this.pendingKeys.length=0,this.updateScheduled=!1,this.notifyListeners()}notifyListeners(){let O=this.state,$=this.listenerCache;$.length=0;for(let A of this.listeners)$.push(A);for(let A=0;A<$.length;A++)try{$[A](O)}catch(Q){console.error("Error in state listener:",Q)}}updatePlaybackState(O){let $=O?"playing":"paused";this.setState({state:$,playing:O,paused:!O,ended:!1})}updateTime(O){this.setState({currentTime:O})}updateDuration(O){this.setState({duration:O})}updateBuffered(O){this.setState({buffered:O})}updateVolume(O,$){this.setState({volume:O,muted:$})}updatePlaybackRate(O){this.setState({playbackRate:O})}updateMediaInfo(O){this.setState({mediaInfo:O})}updateTracks(O,$,A){let Q={};if(O)Q.videoTracks=O;if($)Q.audioTracks=$;if(A)Q.subtitleTracks=A;this.setState(Q)}updateSelectedTracks(O,$){switch(O){case"video":this.setState({selectedVideoTrack:$});break;case"audio":this.setState({selectedAudioTrack:$});break;case"subtitle":this.setState({selectedSubtitleTrack:$});break}}updateError(O){this.setState({error:O,state:O?"error":this.state.state})}updateSeekingState(O){this.setState({seeking:O})}updateWaitingState(O){this.setState({waiting:O})}updateReadyState(O,$){this.setState({canPlay:O,canPlayThrough:$,state:O?"ready":this.state.state})}updateEndedState(O){this.setState({ended:O,playing:!1,paused:!0,state:O?"ended":this.state.state})}updateLoadingState(){this.setState({state:"loading",playing:!1,paused:!0,ended:!1,error:null})}updateRendererType(O){this.setState({rendererType:O})}updateRotation(O,$){this.setState({rotation:O,displaySize:$})}updatePlaylist(O,$=null){this.setState({playlist:O,currentPlaylistIndex:$})}updateCurrentPlaylistIndex(O){this.setState({currentPlaylistIndex:O})}updatePlaylistMode(O){this.setState({playlistMode:O})}addToPlaylist(O,$){let A=this.state.playlist,Q,V=this.state.currentPlaylistIndex;if($!==void 0&&$>=0&&$<=A.length){if(Q=[...A.slice(0,$),O,...A.slice($)],V!==null&&V>=$)V+=1}else Q=[...A,O];this.setState({playlist:Q,currentPlaylistIndex:V})}removeFromPlaylist(O){let $=this.state.playlist;if(O<0||O>=$.length)return;let A=$.filter((V,J)=>J!==O),Q=this.state.currentPlaylistIndex;if(Q===O)Q=A.length>0?0:null;else if(Q!==null&&Q>O)Q-=1;if(A.length===0)this.setState({playlist:A,currentPlaylistIndex:null,state:"idle",currentTime:0,duration:0,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null});else this.setState({playlist:A,currentPlaylistIndex:Q})}clearPlaylist(){this.setState({playlist:[],currentPlaylistIndex:null,state:"idle",currentTime:0,duration:0,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null})}}class d{input=null;videoTracks=new Map;audioTracks=new Map;videoTrackInfos=[];audioTrackInfos=[];subtitleTrackInfos=[];subtitleProviders=new Map;subtitleTrackResolvers=new Map;selectedVideoTrack=null;selectedAudioTrack=null;selectedSubtitleTrack=null;onTrackChange;async initialize(O){this.videoTracks.clear(),this.audioTracks.clear(),this.videoTrackInfos=[],this.audioTrackInfos=[],this.selectedVideoTrack=null,this.selectedAudioTrack=null,this.input=O,await this.loadTracks()}async loadTracks(){if(!this.input)return;let O=await this.input.getVideoTracks();this.videoTrackInfos=await Promise.all(O.map(async(A)=>{let Q=`video-${A.id}`;this.videoTracks.set(Q,A);let V=0,J=0;try{let Z=await A.computePacketStats(100);V=Z.averagePacketRate,J=Z.averageBitrate}catch{}return{id:Q,codec:A.codec,language:A.languageCode,name:A.name,width:A.codedWidth,height:A.codedHeight,frameRate:V,bitrate:J,rotation:A.rotation,selected:!1,decodable:await A.canDecode()}}));let $=await this.input.getAudioTracks();if(this.audioTrackInfos=await Promise.all($.map(async(A)=>{let Q=`audio-${A.id}`;this.audioTracks.set(Q,A);let V=0;try{V=(await A.computePacketStats(100)).averageBitrate}catch{}return{id:Q,codec:A.codec,language:A.languageCode,name:A.name,channels:A.numberOfChannels,sampleRate:A.sampleRate,bitrate:V,selected:!1,decodable:await A.canDecode()}})),this.videoTrackInfos.length>0){let A=this.videoTrackInfos.find((Q)=>Q.decodable);if(A)this.selectVideoTrack(A.id)}if(this.audioTrackInfos.length>0){let A=this.audioTrackInfos.find((Q)=>Q.decodable);if(A)this.selectAudioTrack(A.id)}}getVideoTracks(){return[...this.videoTrackInfos]}getAudioTracks(){return[...this.audioTrackInfos]}getSubtitleTracks(){return[...this.subtitleTrackInfos]}getSelectedVideoTrack(){if(!this.selectedVideoTrack)return null;return this.videoTracks.get(this.selectedVideoTrack)??null}getSelectedAudioTrack(){if(!this.selectedAudioTrack)return null;return this.audioTracks.get(this.selectedAudioTrack)??null}getSelectedVideoTrackInfo(){if(!this.selectedVideoTrack)return null;return this.videoTrackInfos.find((O)=>O.id===this.selectedVideoTrack)??null}getSelectedAudioTrackInfo(){if(!this.selectedAudioTrack)return null;return this.audioTrackInfos.find((O)=>O.id===this.selectedAudioTrack)??null}getSelectedSubtitleTrackInfo(){if(!this.selectedSubtitleTrack)return null;return this.subtitleTrackInfos.find((O)=>O.id===this.selectedSubtitleTrack)??null}selectVideoTrack(O){if(O===this.selectedVideoTrack)return!0;if(O&&!this.videoTracks.has(O))return!1;let $=this.selectedVideoTrack;if(this.videoTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedVideoTrack=O,this.onTrackChange)this.onTrackChange({type:"video",previousTrackId:$,newTrackId:O});return!0}selectAudioTrack(O){if(O===this.selectedAudioTrack)return!0;if(O&&!this.audioTracks.has(O))return!1;let $=this.selectedAudioTrack;if(this.audioTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedAudioTrack=O,this.onTrackChange)this.onTrackChange({type:"audio",previousTrackId:$,newTrackId:O});return!0}selectSubtitleTrack(O){if(O===this.selectedSubtitleTrack)return!0;if(O&&!this.subtitleTrackResolvers.has(O))return!1;let $=this.selectedSubtitleTrack;if(this.subtitleTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedSubtitleTrack=O,this.onTrackChange)this.onTrackChange({type:"subtitle",previousTrackId:$,newTrackId:O});return!0}registerSubtitleTracks(O,$){this.subtitleProviders.set(O,$),this.rebuildSubtitleTracks()}unregisterSubtitleTracks(O){if(!this.subtitleProviders.delete(O))return;this.rebuildSubtitleTracks()}async getSubtitleTrackResource(O){if(!O)return null;let $=this.subtitleTrackResolvers.get(O);if(!$)return null;return $()}rebuildSubtitleTracks(){let O=this.selectedSubtitleTrack;this.subtitleTrackInfos=[],this.subtitleTrackResolvers.clear();for(let A of this.subtitleProviders.values())for(let Q of A){let V={...Q.info,selected:!1};this.subtitleTrackInfos.push(V),this.subtitleTrackResolvers.set(V.id,Q.resolver)}let $=O;if(!$||!this.subtitleTrackResolvers.has($))$=this.subtitleTrackInfos[0]?.id??null;if(this.selectedSubtitleTrack=$,this.subtitleTrackInfos.forEach((A)=>{A.selected=A.id===this.selectedSubtitleTrack}),O!==this.selectedSubtitleTrack&&this.onTrackChange)this.onTrackChange({type:"subtitle",previousTrackId:O,newTrackId:this.selectedSubtitleTrack})}setTrackChangeListener(O){this.onTrackChange=O}getState(){return{videoTracks:this.getVideoTracks(),audioTracks:this.getAudioTracks(),subtitleTracks:this.getSubtitleTracks(),selectedVideoTrack:this.selectedVideoTrack,selectedAudioTrack:this.selectedAudioTrack,selectedSubtitleTrack:this.selectedSubtitleTrack}}getPrimaryVideoTrack(){if(this.videoTracks.size===0)return null;return this.selectedVideoTrack?this.videoTracks.get(this.selectedVideoTrack)??null:this.videoTracks.values().next().value??null}getPrimaryAudioTrack(){if(this.audioTracks.size===0)return null;return this.selectedAudioTrack?this.audioTracks.get(this.selectedAudioTrack)??null:this.audioTracks.values().next().value??null}hasVideo(){return this.videoTrackInfos.length>0}hasAudio(){return this.audioTrackInfos.length>0}hasSubtitles(){return this.subtitleTrackInfos.length>0}dispose(){this.videoTracks.clear(),this.audioTracks.clear(),this.videoTrackInfos=[],this.audioTrackInfos=[],this.subtitleTrackInfos=[],this.subtitleProviders.clear(),this.subtitleTrackResolvers.clear(),this.selectedVideoTrack=null,this.selectedAudioTrack=null,this.selectedSubtitleTrack=null,this.input=null,this.onTrackChange=void 0}async replaceAudioTrackByInputId(O,$){let A=null;for(let[V,J]of this.audioTracks.entries())if(J.id===O){A=V;break}if(!A)return;this.audioTracks.set(A,$);let Q=this.audioTrackInfos.findIndex((V)=>V.id===A);if(Q!==-1){let V=0;try{V=(await $.computePacketStats(100)).averageBitrate}catch{}this.audioTrackInfos[Q]={...this.audioTrackInfos[Q],codec:$.codec,channels:$.numberOfChannels,sampleRate:$.sampleRate,bitrate:V,decodable:await $.canDecode()}}}async replaceVideoTrackByInputId(O,$){let A=null;for(let[V,J]of this.videoTracks.entries())if(J.id===O){A=V;break}if(!A)return;this.videoTracks.set(A,$);let Q=this.videoTrackInfos.findIndex((V)=>V.id===A);if(Q!==-1){let V=0,J=0;try{let K=await $.computePacketStats(100);V=K.averagePacketRate,J=K.averageBitrate}catch{}this.videoTrackInfos[Q]={...this.videoTrackInfos[Q],codec:$.codec,width:$.codedWidth,height:$.codedHeight,rotation:$.rotation,frameRate:V,bitrate:J,decodable:await $.canDecode()}}}}class o{emitter;store;state;sourceManager;playbackController;trackManager;playlistManager;pluginManager;options;disposed=!1;getCurrentInput=()=>this.sourceManager.getCurrentSource()?.input??null;trackSwitcher;core;constructor(O={}){this.options={volume:1,muted:!1,playbackRate:1,autoplay:!1,preload:"metadata",...O},this.emitter=new f({maxListeners:100}),this.store=new c,this.state=new e(this.store),this.sourceManager=new u({maxCacheSize:O.maxCacheSize,crossOrigin:O.crossOrigin}),this.playbackController=new g({canvas:O.renderTarget,audioContext:O.audioContext,volume:this.options.volume,muted:this.options.muted,playbackRate:this.options.playbackRate,rendererType:this.options.renderer}),this.trackManager=new d,this.playlistManager=new AO(this.store,this.emitter,async($,A)=>{await this.core.load($.mediaSource,{startTime:$.savedPosition??0,autoplay:A,playlistItemId:$.id})},this.sourceManager),this.trackSwitcher=new $O({sourceManager:this.sourceManager,trackManager:this.trackManager,playbackController:this.playbackController,emit:this.emit.bind(this),store:this.store,getCurrentInput:this.getCurrentInput}),this.pluginManager=new QO(this),this.core=new r({state:this.state,sourceManager:this.sourceManager,trackManager:this.trackManager,playbackController:this.playbackController,trackSwitcher:this.trackSwitcher,emit:this.emit.bind(this),pluginManager:this.pluginManager}),this.playbackController.setPluginManager(this.pluginManager),this.store.setPluginManager(this.pluginManager),this.setupInternalListeners(),this.state.applyInitial(this.options.volume??1,this.options.muted??!1,this.options.playbackRate??1),this.state.updateRendererType(this.options.renderer||"webgpu")}setupInternalListeners(){this.playbackController.setTimeUpdateCallback((O)=>{this.state.updateTime(O),this.emit("timeupdate",{currentTime:O})}),this.playbackController.setEndedCallback(()=>{this.state.updateEndedState(!0),this.emit("ended",void 0);let O=this.getState();if(O.playlist.length>0&&O.currentPlaylistIndex!==null){let{playlistMode:$,currentPlaylistIndex:A}=O;if($==="repeat-one"){let Q=A;queueMicrotask(async()=>{try{await this.seek(0),await this.play()}catch(V){this.emitter.emit("playlistitemerror",{index:Q,error:V})}})}else if($==="repeat"){let Q=A<O.playlist.length-1?A+1:0;queueMicrotask(async()=>{try{await this.playlistManager.next()}catch(V){this.emitter.emit("playlistitemerror",{index:Q,error:V})}})}else if($==="sequential"&&A<O.playlist.length-1){let Q=A+1;queueMicrotask(async()=>{try{await this.playlistManager.next()}catch(V){this.emitter.emit("playlistitemerror",{index:Q,error:V})}})}}}),this.trackManager.setTrackChangeListener((O)=>{this.state.updateSelectedTracks(O.type,O.newTrackId),this.emit("trackchange",{type:O.type,trackId:O.newTrackId})}),this.playbackController.setWaitingCallback(()=>{this.state.updateWaitingState(!0),this.emit("waiting",void 0)}),this.playbackController.setPlayingCallback(()=>{if(this.getState().waiting)this.state.updateWaitingState(!1),this.emit("playing",void 0)}),this.playbackController.setRendererChangeCallback((O)=>{this.state.updateRendererType(O),this.emit("rendererchange",O)}),this.playbackController.setRendererFallbackCallback((O,$)=>{this.emit("rendererfallback",{from:O,to:$})}),this.playbackController.setRotationChangeCallback((O,$)=>{this.store.updateRotation(O,$),this.emit("rotationchange",{rotation:O,displaySize:$})}),this.state.subscribe((O)=>{this.emit("statechange",O)})}async load(O,$={}){this.checkDisposed();let A=this.getState();if(A.playlist.length===0||$.replacePlaylist){await this.playlistManager.loadPlaylist([{mediaSource:O}],{autoplay:$.autoplay??this.options.autoplay,startTime:$.startTime});return}else if(A.currentPlaylistIndex!==null&&A.playlist.length>0){let Q=A.currentPlaylistIndex,J={...A.playlist[Q],mediaSource:O,savedPosition:0,duration:null},K=[...A.playlist];K[Q]=J,this.store.updatePlaylist(K,Q),this.emitter.emit("playlistchange",{playlist:K}),await this.core.load(O,{startTime:$.startTime??0,autoplay:$.autoplay??this.options.autoplay});return}await this.core.load(O,{autoplay:$.autoplay??this.options.autoplay,startTime:$.startTime})}async play(){return this.checkDisposed(),this.core.play()}pause(){this.checkDisposed(),this.core.pause()}async seek(O,$={}){return this.checkDisposed(),this.core.seek(O)}async stop(){return this.checkDisposed(),this.core.stop()}get currentTime(){return this.playbackController.getCurrentTime()}set currentTime(O){this.seek(O)}get duration(){return this.state.getState().duration}get volume(){return this.playbackController.getVolume()}set volume(O){this.checkDisposed();let $=Math.max(0,Math.min(1,O));this.playbackController.setVolume($),this.state.updateVolume($,this.muted),this.emit("volumechange",{volume:$,muted:this.muted})}get muted(){return this.playbackController.isMuted()}set muted(O){this.checkDisposed(),this.playbackController.setMuted(O),this.state.updateVolume(this.volume,O),this.emit("volumechange",{volume:this.volume,muted:O})}get playbackRate(){return this.playbackController.getPlaybackRate()}set playbackRate(O){this.checkDisposed();let $=Math.max(0.25,Math.min(4,O));this.playbackController.setPlaybackRate($),this.state.updatePlaybackRate($),this.emit("ratechange",{playbackRate:$})}get paused(){return!this.playbackController.isPlaying()}get ended(){return this.state.getState().ended}get seeking(){return this.state.getState().seeking}get waiting(){return this.state.getState().waiting}get rotation(){return this.playbackController.getRotation()}set rotation(O){this.checkDisposed(),this.playbackController.setRotation(O)}get displaySize(){return this.playbackController.getDisplaySize()}getVideoTracks(){return this.trackManager.getVideoTracks()}getAudioTracks(){return this.trackManager.getAudioTracks()}getSubtitleTracks(){return this.trackManager.getSubtitleTracks()}async selectVideoTrack(O){this.checkDisposed(),await this.trackSwitcher.selectVideoTrack(this.trackManager,O)}async selectAudioTrack(O){this.checkDisposed(),await this.trackSwitcher.selectAudioTrack(this.trackManager,O)}selectSubtitleTrack(O){if(this.checkDisposed(),!this.trackManager.selectSubtitleTrack(O))throw Error(`Invalid subtitle track ID: ${O}`)}registerSubtitleTracks(O,$){this.trackManager.registerSubtitleTracks(O,$),this.state.updateTracks(void 0,void 0,this.trackManager.getSubtitleTracks());let A=this.state.getState().mediaInfo;if(A)this.state.updateMediaInfo({...A,hasSubtitles:this.trackManager.hasSubtitles()})}unregisterSubtitleTracks(O){this.trackManager.unregisterSubtitleTracks(O),this.state.updateTracks(void 0,void 0,this.trackManager.getSubtitleTracks());let $=this.state.getState().mediaInfo;if($)this.state.updateMediaInfo({...$,hasSubtitles:this.trackManager.hasSubtitles()})}async getSubtitleTrackResource(O){return this.trackManager.getSubtitleTrackResource(O)}async screenshot(O={}){return this.checkDisposed(),this.playbackController.screenshot(O)}async setRenderTarget(O){this.checkDisposed(),await this.playbackController.setCanvas(O)}getRenderTarget(){return this.playbackController.getCanvas()}refreshOverlays(){this.playbackController.refreshOverlays()}async loadPlaylist(O,$){this.checkDisposed(),await this.playlistManager.loadPlaylist(O,$)}addToPlaylist(O,$){this.checkDisposed(),this.playlistManager.addToPlaylist(O,$)}async removeFromPlaylist(O){this.checkDisposed(),await this.playlistManager.removeFromPlaylist(O)}clearPlaylist(){this.checkDisposed(),this.playlistManager.clearPlaylist()}async next(){this.checkDisposed(),await this.playlistManager.next()}async prev(){this.checkDisposed(),await this.playlistManager.prev()}async jumpTo(O){this.checkDisposed(),await this.playlistManager.jumpTo(O)}get playlist(){return this.playlistManager.playlist}get playlistIndex(){return this.playlistManager.currentIndex}get nowPlaying(){return this.playlistManager.currentItem}get playlistMode(){return this.playlistManager.mode}set playlistMode(O){this.checkDisposed(),this.playlistManager.setMode(O)}getRendererType(){return this.playbackController.getRendererType()}async switchRenderer(O){this.checkDisposed(),await this.playbackController.switchRenderer(O)}updateCanvasDimensions(){this.checkDisposed(),this.playbackController.updateCanvasDimensions()}static getSupportedRenderers(){return F.getSupportedRenderers()}getState(){return this.state.getState()}subscribe(O){return{unsubscribe:this.state.subscribe(O)}}on(O,$){return this.emitter.on(O,$)}once(O,$){return this.emitter.once(O,$)}off(O,$){this.emitter.off(O,$)}async use(O){if(this.checkDisposed(),await this.pluginManager.install(O),O.hooks?.audio)this.playbackController.rebuildAudioGraph()}async unuse(O){this.checkDisposed(),await this.pluginManager.uninstall(O),this.playbackController.rebuildAudioGraph()}emit(O,$){let A=this.pluginManager.executeBeforeEvent(O,$);if(A?.cancel)return;let Q=A?.data??$;this.emitter.emit(O,Q),this.pluginManager.executeAfterEvent(O,Q)}checkDisposed(){if(this.disposed)throw Error("Player has been disposed")}dispose(){if(this.disposed)return;this.disposed=!0,this.pluginManager.dispose(),this.playbackController.dispose(),this.trackManager.dispose(),this.playlistManager?.dispose(),this.sourceManager.dispose(),this.state.reset(),this.emitter.removeAllListeners()}destroy(){this.dispose(),this.playbackController.destroy()}}var dO={fromUrl(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromFile(O,$={}){return{mediaSource:O,title:$.title||O.name,poster:$.poster}},fromBlob(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromBuffer(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromUint8Array(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromStream(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}}};var YO;((j)=>{j.MEDIA_NOT_SUPPORTED="MEDIA_NOT_SUPPORTED";j.MEDIA_LOAD_FAILED="MEDIA_LOAD_FAILED";j.DECODE_ERROR="DECODE_ERROR";j.NETWORK_ERROR="NETWORK_ERROR";j.PERMISSION_DENIED="PERMISSION_DENIED";j.PLAYBACK_ERROR="PLAYBACK_ERROR";j.TRACK_NOT_FOUND="TRACK_NOT_FOUND";j.INVALID_STATE="INVALID_STATE";j.UNKNOWN_ERROR="UNKNOWN_ERROR"})(YO||={});class E extends Error{code;details;constructor(O,$,A){super($);this.name="MediaFoxError",this.code=O,this.details=A}static mediaNotSupported(O="Media format not supported",$){return new E("MEDIA_NOT_SUPPORTED",O,$)}static mediaLoadFailed(O="Failed to load media",$){return new E("MEDIA_LOAD_FAILED",O,$)}static decodeError(O="Failed to decode media",$){return new E("DECODE_ERROR",O,$)}static networkError(O="Network error occurred",$){return new E("NETWORK_ERROR",O,$)}static permissionDenied(O="Permission denied",$){return new E("PERMISSION_DENIED",O,$)}static playbackError(O="Playback error occurred",$){return new E("PLAYBACK_ERROR",O,$)}static trackNotFound(O="Track not found",$){return new E("TRACK_NOT_FOUND",O,$)}static invalidState(O="Invalid player state",$){return new E("INVALID_STATE",O,$)}static unknownError(O="Unknown error occurred",$){return new E("UNKNOWN_ERROR",O,$)}}function oO(O,$){if(O instanceof E)return O;if(O instanceof Error)return new E("UNKNOWN_ERROR",`${$}: ${O.message}`,{originalError:O});return new E("UNKNOWN_ERROR",`${$}: ${String(O)}`,{originalError:O})}function nO(O,$=!1){let A=Math.abs(O),Q=Math.floor(A/3600),V=Math.floor(A%3600/60),J=Math.floor(A%60),K=Math.floor(A%1*1000),Z="";if(O<0)Z="-";if(Q>0)Z+=`${Q}:${V.toString().padStart(2,"0")}:${J.toString().padStart(2,"0")}`;else Z+=`${V}:${J.toString().padStart(2,"0")}`;if($)Z+=`.${K.toString().padStart(3,"0")}`;return Z}function iO(O){let $=O.trim().split(":").map(Number);if($.some(Number.isNaN))throw Error("Invalid time string");let A=0;if($.length===3)A=$[0]*3600+$[1]*60+$[2];else if($.length===2)A=$[0]*60+$[1];else if($.length===1)A=$[0];else throw Error("Invalid time format");return A}function sO(O,$){return Math.floor(O*$)}function tO(O,$){return O/$}function aO(O,$,A){return Math.max($,Math.min(A,O))}function rO(O,$){return O.start<$.end&&$.start<O.end}function eO(O){if(O.length===0)return[];let $=[...O].sort((Q,V)=>Q.start-V.start),A=[$[0]];for(let Q=1;Q<$.length;Q++){let V=A[A.length-1],J=$[Q];if(J.start<=V.end)V.end=Math.max(V.end,J.end);else A.push(J)}return A}function O$(O){return O.reduce(($,A)=>$+(A.end-A.start),0)}function $$(O,$){for(let A of O)if($>=A.start&&$<A.end)return A;return null}var BA="0.1.0",wA=o;export{oO as wrapError,O$ as totalBufferedDuration,sO as timeToFrame,rO as timeRangesOverlap,iO as parseTime,eO as mergeTimeRanges,tO as frameToTime,nO as formatTime,$$ as findBufferedRange,wA as default,aO as clamp,k as VideoRenderer,BA as VERSION,d as TrackManager,c as Store,y as SourcePool,u as SourceManager,dO as Source,F as RendererFactory,g as PlaybackController,E as MediaFoxError,o as MediaFox,f as EventEmitter,YO as ErrorCode,i as Compositor,p as AudioManager};
|
|
40
|
+
`;constructor(O){this.canvas=O.canvas,this.powerPreference=O.powerPreference||"high-performance",this.rotation=O.rotation??0,this.initialize().catch(($)=>{console.error("WebGPU initialization failed:",$)})}async initialize(){try{let O=navigator;if(!O.gpu)return console.log("WebGPU not available in navigator"),!1;let $=await O.gpu.requestAdapter({powerPreference:this.powerPreference});if(!$)return console.log("WebGPU adapter not available"),!1;if(this.device=await $.requestDevice(),!this.device)return console.log("WebGPU device not available"),!1;if("getContext"in this.canvas)this.context=this.canvas.getContext("webgpu");if(!this.context)return console.log("WebGPU context not available on canvas"),!1;let A=O.gpu.getPreferredCanvasFormat();return this.context.configure({device:this.device,format:A,usage:GPUTextureUsage.RENDER_ATTACHMENT,alphaMode:"opaque"}),await this.createRenderPipeline(),this.createVertexBuffer(),this.isInitialized=!0,console.log("WebGPU renderer initialized successfully"),!0}catch(O){return console.error("WebGPU initialization error:",O),!1}}async createRenderPipeline(){if(!this.device)return;let O=navigator;if(!O.gpu)return;let $=this.device.createShaderModule({code:this.vertexShaderSource}),A=this.device.createShaderModule({code:this.fragmentShaderSource});this.pipeline=this.device.createRenderPipeline({layout:"auto",vertex:{module:$,entryPoint:"vs_main",buffers:[{arrayStride:16,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"}]}]},fragment:{module:A,entryPoint:"fs_main",targets:[{format:O.gpu.getPreferredCanvasFormat()}]},primitive:{topology:"triangle-strip"}})}createVertexBuffer(){if(!this.device)return;this.vertexBuffer=this.device.createBuffer({size:64,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}createTexture(O,$){if(!this.device)return;if(this.texture)this.texture.destroy();if(this.texture=this.device.createTexture({size:{width:O,height:$},format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),!this.sampler)this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"});this.createBindGroup()}createBindGroup(){if(!this.device||!this.texture||!this.sampler||!this.pipeline)return;this.bindGroup=this.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:this.sampler},{binding:1,resource:this.texture.createView()}]})}isReady(){return this.isInitialized&&this.device!==null&&this.context!==null&&this.pipeline!==null}render(O){if(!this.isReady()||!this.device||!this.context||!this.pipeline)return!1;try{let{width:$,height:A}=O;if($===0||A===0)return console.warn(`WebGPU: Source canvas has zero dimensions (${$}x${A})`),!1;let j=this.canvas.width,Q=this.canvas.height;if(j===0||Q===0)return console.warn(`WebGPU: Output canvas has zero dimensions (${j}x${Q})`),!1;if($!==this.textureWidth||A!==this.textureHeight)this.createTexture($,A),this.textureWidth=$,this.textureHeight=A;if(!this.texture)return!1;try{this.device.queue.copyExternalImageToTexture({source:O},{texture:this.texture},{width:$,height:A})}catch{let VO=O.getContext("2d");if(!VO)return!1;let zO=VO.getImageData(0,0,$,A),BO=new Uint8Array(zO.data.buffer);this.device.queue.writeTexture({texture:this.texture,origin:{x:0,y:0,z:0}},BO,{bytesPerRow:$*4,rowsPerImage:A},{width:$,height:A,depthOrArrayLayers:1})}let V=this.device.createCommandEncoder(),J=this.context.getCurrentTexture().createView(),K=V.beginRenderPass({colorAttachments:[{view:J,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]});if(K.setPipeline(this.pipeline),this.bindGroup)K.setBindGroup(0,this.bindGroup);let Z=this.rotation===90||this.rotation===270,U=Z?this.textureHeight:this.textureWidth,G=Z?this.textureWidth:this.textureHeight,L=Math.min(j/U,Q/G),P=Math.round(U*L),M=Math.round(G*L),X=Math.round((j-P)/2),E=Math.round((Q-M)/2),Y=X/j*2-1,q=(X+P)/j*2-1,H=1-E/Q*2,b=1-(E+M)/Q*2,w=(Y+q)/2,T=(H+b)/2,f=(q-Y)/2,C=(H-b)/2,R=this.rotation*Math.PI/180,B=Math.cos(R),N=Math.sin(R),z=Z?C:f,F=Z?f:C,D=this.quadArray;if(D[0]=-z*B- -F*N+w,D[1]=-z*N+-F*B+T,D[2]=0,D[3]=1,D[4]=z*B- -F*N+w,D[5]=z*N+-F*B+T,D[6]=1,D[7]=1,D[8]=-z*B-F*N+w,D[9]=-z*N+F*B+T,D[10]=0,D[11]=0,D[12]=z*B-F*N+w,D[13]=z*N+F*B+T,D[14]=1,D[15]=0,this.vertexBuffer)this.device.queue.writeBuffer(this.vertexBuffer,0,D),K.setVertexBuffer(0,this.vertexBuffer);return K.draw(4,1,0,0),K.end(),this.device.queue.submit([V.finish()]),!0}catch{return!1}}clear(){if(!this.isReady()||!this.device||!this.context)return;try{let O=this.device.createCommandEncoder(),$=this.context.getCurrentTexture().createView();O.beginRenderPass({colorAttachments:[{view:$,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]}).end(),this.device.queue.submit([O.finish()])}catch{}}setRotation(O){this.rotation=O}getRotation(){return this.rotation}dispose(){try{if(this.texture)this.texture.destroy(),this.texture=null;if(this.vertexBuffer)this.vertexBuffer.destroy(),this.vertexBuffer=null;this.device=null,this.context=null,this.pipeline=null,this.sampler=null,this.bindGroup=null,this.isInitialized=!1}catch{}}}class W{canvas;powerPreference;constructor(O){this.canvas=O.canvas,this.powerPreference=O.powerPreference||"high-performance"}async createRenderer(O){try{switch(O){case"webgpu":return await this.createWebGPURenderer();case"webgl":return this.createWebGLRenderer();case"canvas2d":return this.createCanvas2DRenderer();default:return null}}catch{return null}}async createRendererWithFallback(O){let $=[O];if(O!=="webgl")$.push("webgl");if(O!=="canvas2d")$.push("canvas2d");for(let j of $){let Q=await this.createRenderer(j);if(Q?.isReady())return{renderer:Q,actualType:j};if(Q)Q.dispose()}return{renderer:this.createCanvas2DRenderer(),actualType:"canvas2d"}}async createWebGPURenderer(){if(!navigator.gpu)return null;if(!("getContext"in this.canvas))return console.log("WebGPU requires HTMLCanvasElement, not OffscreenCanvas"),null;let $=new r({canvas:this.canvas,powerPreference:this.powerPreference}),A=1000,j=performance.now();if(await(async()=>{while(!$.isReady()){if(performance.now()-j>A)return console.log("WebGPU renderer initialization timed out"),!1;if("requestIdleCallback"in window)await new Promise((J)=>requestIdleCallback(()=>J(void 0)));else await new Promise((J)=>requestAnimationFrame(()=>J(void 0)))}return!0})())return console.log("WebGPU renderer initialized successfully"),$;return $.isReady()?$:null}createWebGLRenderer(){try{let O=new t({canvas:this.canvas,powerPreference:this.powerPreference,preserveDrawingBuffer:!1,antialias:!1,alpha:!1});return O.isReady()?O:null}catch{return null}}createCanvas2DRenderer(){return new S({canvas:this.canvas})}static getSupportedRenderers(){let O=[];if(navigator.gpu)O.push("webgpu");try{let A=document.createElement("canvas");if(A.getContext("webgl")||A.getContext("experimental-webgl"))O.push("webgl")}catch{}return O.push("canvas2d"),O}static getRendererDisplayName(O){switch(O){case"canvas2d":return"Canvas 2D";case"webgl":return"WebGL";case"webgpu":return"WebGPU";default:return"Unknown"}}static isRendererSupported(O){if(O==="canvas2d")return!0;return W.getSupportedRenderers().includes(O)}}var a=new WeakMap;function LO(O,$){a.set(O,$)}function HO(O){let $=a.get(O);if($)a.delete(O);return $}class v{canvas=null;canvasSink=null;sampleSink=null;options;frameIterator=null;currentFrame=null;nextFrame=null;disposed=!1;renderingId=0;renderer=null;rendererType="canvas2d";onRendererChange;onRendererFallback;onRotationChange;initPromise=null;resizeObserver=null;lastObservedWidth=0;lastObservedHeight=0;videoAspectRatio=null;debug=!1;pluginManager=null;overlayCanvas=null;overlayCtx=null;lastOverlayTime=0;rotation=0;sourceWidth=0;sourceHeight=0;updateFrameResult={frameUpdated:!1,isStarving:!1};constructor(O={}){if(this.options={poolSize:O.poolSize??2,rendererType:O.rendererType??"webgpu",...O},this.rendererType=this.options.rendererType??"webgpu",this.debug=O.debug??!1,this.initPromise=null,O.canvas){if(this.canvas=O.canvas,this.options.width!==void 0)O.canvas.width=this.options.width;if(this.options.height!==void 0)O.canvas.height=this.options.height;this.initPromise=this.initializeRenderer(O.canvas,this.rendererType).catch(($)=>{if(this.debug)console.error("Failed to initialize renderer:",$)}),this.setupResizeObserver(O.canvas)}}setupResizeObserver(O){if(!("getBoundingClientRect"in O)||typeof ResizeObserver>"u")return;if(this.options.width!==void 0||this.options.height!==void 0)return;this.cleanupResizeObserver();let $=O;this.resizeObserver=new ResizeObserver((A)=>{if(this.disposed||!this.resizeObserver)return;for(let j of A){let{width:Q,height:V}=this.getCanvasDimensionsFromEntry(j,$);if(Q!==this.lastObservedWidth||V!==this.lastObservedHeight){if(this.lastObservedWidth=Q,this.lastObservedHeight=V,$.width!==Q||$.height!==V){if($.width=Q,$.height=V,this.updateCanvasAspectRatio(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}}}});try{this.resizeObserver.observe($,{box:"device-pixel-content-box"})}catch{try{this.resizeObserver.observe($,{box:"content-box"})}catch{this.resizeObserver.observe($)}}requestAnimationFrame(()=>{if(this.disposed||!this.resizeObserver)return;let{width:A,height:j}=this.getCanvasDimensionsFromCanvas($);if(this.lastObservedWidth=A,this.lastObservedHeight=j,$.width!==A||$.height!==j){if($.width=A,$.height=j,this.updateCanvasAspectRatio(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}})}getCanvasDimensionsFromEntry(O,$){let A=0,j=0,Q=window.devicePixelRatio||1;if(O.devicePixelContentBoxSize?.length)A=O.devicePixelContentBoxSize[0].inlineSize,j=O.devicePixelContentBoxSize[0].blockSize;else if(O.contentBoxSize?.length)A=Math.round(O.contentBoxSize[0].inlineSize*Q),j=Math.round(O.contentBoxSize[0].blockSize*Q);else if(O.contentRect)A=Math.round(O.contentRect.width*Q),j=Math.round(O.contentRect.height*Q);if(A===0||j===0)return this.getCanvasDimensionsFromCanvas($);return{width:Math.max(1,A),height:Math.max(1,j)}}getCanvasDimensionsFromCanvas(O){let $=0,A=0,j=window.devicePixelRatio||1,Q=O.getBoundingClientRect();if($=Math.round(Q.width*j),A=Math.round(Q.height*j),$===0||A===0)$=Math.round(O.clientWidth*j)||$,A=Math.round(O.clientHeight*j)||A;if($===0||A===0)console.warn("Canvas has zero dimensions after all fallbacks, using 1x1");return{width:Math.max(1,$),height:Math.max(1,A)}}cleanupResizeObserver(){if(this.resizeObserver)this.resizeObserver.disconnect(),this.resizeObserver=null,this.lastObservedWidth=0,this.lastObservedHeight=0}retryUntilCanvasReady(O,$,A=60){let j=0,Q=()=>{if(j++,O.canvas.width>0&&O.canvas.height>0)$();else if(j<A)requestAnimationFrame(Q);else{if(this.debug)console.warn("Canvas dimensions timeout, forcing action");$()}};requestAnimationFrame(Q)}updateCanvasAspectRatio(){if(!this.canvas||!this.videoAspectRatio||!("style"in this.canvas))return;this.canvas.style.aspectRatio=this.videoAspectRatio}updateCanvasBackingBuffer(O){let{width:$,height:A}=this.getCanvasDimensionsFromCanvas(O);if(O.width!==$||O.height!==A)return O.width=$,O.height=A,!0;return!1}async initializeRenderer(O,$){if(this.debug)console.log(`Initializing renderer: ${$}`);let j=await new W({canvas:O}).createRendererWithFallback($);if(this.debug)console.log(`Renderer factory result: ${j.actualType}`);if(!j.renderer.isReady()){if(this.debug)console.warn(`VideoRenderer: Renderer (${j.actualType}) not ready`);throw j.renderer.dispose(),Error(`Failed to initialize renderer: ${j.actualType}`)}if(this.renderer=j.renderer,this.rendererType=j.actualType,this.debug)console.log(`Initialized renderer: ${this.rendererType}`);if(j.actualType!==$){if(this.onRendererFallback)this.onRendererFallback($,j.actualType)}if(this.onRendererChange){if(this.debug)console.log(`Emitting renderer change: ${this.rendererType}`);this.onRendererChange(this.rendererType)}if(this.currentFrame&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log(`Rendering initial frame with ${this.rendererType}`);if(this.currentFrame.canvas.width===0||this.currentFrame.canvas.height===0){if(this.debug)console.log("Initial frame has zero dimensions, scheduling render when ready...");this.retryUntilCanvasReady(this.currentFrame,()=>{if(this.currentFrame&&this.debug)console.log(`Canvas ready (${this.currentFrame.canvas.width}x${this.currentFrame.canvas.height}), rendering initial frame`);if(this.currentFrame)this.renderFrame(this.currentFrame)})}else this.renderFrame(this.currentFrame)}}async setCanvas(O){if(this.cleanupOverlayCanvas(),this.canvas=O,this.renderer)this.renderer.dispose(),this.renderer=null;if(this.options.width!==void 0)O.width=this.options.width;if(this.options.height!==void 0)O.height=this.options.height;this.setupResizeObserver(O);try{await this.initializeRenderer(O,this.rendererType)}catch($){if(this.debug)console.error("Failed to initialize renderer:",$);if(!this.renderer){if(this.renderer=new S({canvas:O}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}async setVideoTrack(O){if(await this.disposeVideoResources(),O.codec===null)throw Error("Unsupported video codec");if(!await O.canDecode())throw Error(`Cannot decode video track with codec: ${O.codec}`);let A=HO(O);if(this.sourceWidth=O.displayWidth,this.sourceHeight=O.displayHeight,!this.videoAspectRatio&&O.displayWidth&&O.displayHeight){let j=(K,Z)=>Z===0?K:j(Z,K%Z),Q=j(O.displayWidth,O.displayHeight),V=O.displayWidth/Q,J=O.displayHeight/Q;this.videoAspectRatio=`${V}/${J}`,this.updateCanvasAspectRatio()}if(this.notifyRotationChange(),this.initPromise)try{await this.initPromise}catch(j){if(this.debug)console.error("Renderer initialization failed:",j)}if(!this.renderer){if(this.debug)console.warn("Renderer not ready, creating Canvas2D fallback");if(this.canvas){if(this.renderer=new S({canvas:this.canvas}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}if(this.canvas){if(this.options.width!==void 0||this.options.height!==void 0){let j=this.options.width??O.displayWidth,Q=this.options.height??O.displayHeight;if(this.canvas.width!==j||this.canvas.height!==Q)this.canvas.width=j,this.canvas.height=Q,this.updateCanvasAspectRatio()}else if(!this.resizeObserver){if(this.canvas.width===0||this.canvas.height===0)this.canvas.width=O.displayWidth,this.canvas.height=O.displayHeight,this.updateCanvasAspectRatio()}}if(A?.canvasSink)this.canvasSink=A.canvasSink;else this.canvasSink=new FO(O,{rotation:this.options.rotation,poolSize:this.options.poolSize});if(this.sampleSink=new SO(O),this.disposed=!1,A?.firstFrame){if(this.currentFrame=A.firstFrame,this.currentFrame.canvas.width>0&&this.currentFrame.canvas.height>0)this.renderFrame(this.currentFrame);else this.retryUntilCanvasReady(this.currentFrame,()=>{if(this.currentFrame)this.renderFrame(this.currentFrame)},30);this.frameIterator=this.canvasSink.canvases(0),this.frameIterator.next().then(()=>{this.fetchNextFrame()})}else try{await this.seek(0)}catch(j){if(this.debug)console.error("Initial seek failed:",j)}requestAnimationFrame(()=>{if(this.resizeObserver&&this.canvas&&"getBoundingClientRect"in this.canvas)this.updateCanvasBackingBuffer(this.canvas);if(this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)})}async seek(O){if(!this.canvasSink)return;this.renderingId++;let $=this.renderingId;if(this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}let A=this.canvasSink.canvases(O);this.frameIterator=A;try{let j=await A.next(),Q=await A.next();if($!==this.renderingId)return;let V=j.value??null,J=Q.value??null;if(V)if(this.currentFrame=V,V.canvas.width>0&&V.canvas.height>0)this.renderFrame(V);else this.retryUntilCanvasReady(V,()=>this.renderFrame(V),30);if(this.nextFrame=J,!this.nextFrame)this.fetchNextFrame()}catch{}}updateFrame(O){let $=this.updateFrameResult;if(this.disposed)return $.frameUpdated=!1,$.isStarving=!1,$;if(!this.nextFrame){if(this.frameIterator)this.fetchNextFrame();return $.frameUpdated=!1,$.isStarving=!0,$}if(this.nextFrame.timestamp<=O){if(this.currentFrame=this.nextFrame,this.nextFrame=null,this.renderFrame(this.currentFrame),this.frameIterator)this.fetchNextFrame();return $.frameUpdated=!0,$.isStarving=!1,$}return $.frameUpdated=!1,$.isStarving=!1,$}async fetchNextFrame(){let O=this.frameIterator;if(!O||this.disposed)return;let $=this.renderingId;try{let j=(await O.next()).value??null;if(!j||$!==this.renderingId||this.disposed)return;this.nextFrame=j}catch{}}renderFrame(O){if(this.currentFrame=O,!this.renderer||!this.canvas){if(this.initPromise)this.initPromise.then(()=>{if(this.currentFrame===O&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log("Rendering frame after renderer initialization");this.renderFrameWithPlugins(O)}});return}if(!this.renderer.isReady()){if(this.debug)console.warn(`VideoRenderer: Renderer (${this.rendererType}) not ready, skipping frame`);return}this.renderFrameWithPlugins(O)}renderFrameWithPlugins(O){if(!this.renderer||!this.canvas)return;let $=O.timestamp;if(this.pluginManager){if(this.pluginManager.executeBeforeRender(O,$)?.skip)return}let A=O;if(this.pluginManager)A=this.pluginManager.executeTransformFrame(O);if(!this.renderer.render(A.canvas)){if(this.debug)console.warn(`Failed to render frame with ${this.rendererType} (canvas: ${A.canvas.width}x${A.canvas.height})`);if(A.canvas.width===0||A.canvas.height===0)this.retryUntilCanvasReady(A,()=>{if(this.currentFrame===O&&this.renderer&&this.renderer.isReady()){if(!this.renderer.render(A.canvas)&&this.debug)console.warn("Retry render also failed")}},1);return}if(this.executeOverlays($),this.pluginManager)this.pluginManager.executeAfterRender(this.canvas)}executeOverlays(O){if(!this.pluginManager||!this.canvas)return;this.lastOverlayTime=O;let $={width:this.canvas.width,height:this.canvas.height};if(this.rendererType==="canvas2d"){let A=this.canvas.getContext("2d");if(!A)return;this.pluginManager.executeOverlays(A,O,$)}else{if(this.ensureOverlayCanvas(),!this.overlayCanvas||!this.overlayCtx)return;this.overlayCtx.clearRect(0,0,this.overlayCanvas.width,this.overlayCanvas.height),this.pluginManager.executeOverlays(this.overlayCtx,O,$)}}refreshOverlays(){if(!this.canvas)return;if(this.rendererType==="canvas2d"){if(this.currentFrame&&this.renderer?.isReady())this.renderer.render(this.currentFrame.canvas),this.executeOverlays(this.lastOverlayTime)}else if(this.overlayCanvas&&this.overlayCtx){if(this.overlayCtx.clearRect(0,0,this.overlayCanvas.width,this.overlayCanvas.height),this.pluginManager){let O={width:this.canvas.width,height:this.canvas.height};this.pluginManager.executeOverlays(this.overlayCtx,this.lastOverlayTime,O)}}}ensureOverlayCanvas(){if(!this.canvas||!(this.canvas instanceof HTMLCanvasElement))return;if(!this.overlayCanvas){this.overlayCanvas=document.createElement("canvas"),this.overlayCanvas.style.position="absolute",this.overlayCanvas.style.top="0",this.overlayCanvas.style.left="0",this.overlayCanvas.style.width="100%",this.overlayCanvas.style.height="100%",this.overlayCanvas.style.pointerEvents="none",this.overlayCanvas.style.zIndex="1",this.overlayCtx=this.overlayCanvas.getContext("2d");let O=this.canvas.parentElement;if(O){if(getComputedStyle(O).position==="static")O.style.position="relative";O.insertBefore(this.overlayCanvas,this.canvas.nextSibling)}}if(this.overlayCanvas.width!==this.canvas.width||this.overlayCanvas.height!==this.canvas.height)this.overlayCanvas.width=this.canvas.width,this.overlayCanvas.height=this.canvas.height}cleanupOverlayCanvas(){if(this.overlayCanvas)this.overlayCanvas.remove(),this.overlayCanvas=null,this.overlayCtx=null}async getFrameAt(O){if(!this.canvasSink)return null;return this.canvasSink.getCanvas(O)}async getSampleAt(O){if(!this.sampleSink)return null;return this.sampleSink.getSample(O)}async extractFrames(O,$,A=1){if(!this.canvasSink)return[];let j=[],Q=[];for(let V=O;V<=$;V+=A)Q.push(V);for await(let V of this.canvasSink.canvasesAtTimestamps(Q))if(V)j.push(V);return j}async screenshot(O,$={}){if(!this.canvas)return null;if(O!==void 0&&this.canvasSink){let A=await this.canvasSink.getCanvas(O);if(A)this.renderFrame(A)}if("toBlob"in this.canvas)return new Promise((A)=>{this.canvas.toBlob((j)=>A(j),`image/${$.format??"png"}`,$.quality)});else return this.canvas.convertToBlob({type:`image/${$.format??"png"}`,quality:$.quality})}getCurrentFrame(){return this.currentFrame}getNextFrame(){return this.nextFrame}getRendererType(){return this.rendererType}getCanvas(){return this.canvas}updateCanvasDimensions(){if(!this.canvas||!("getBoundingClientRect"in this.canvas))return;let O=this.canvas;if(this.updateCanvasBackingBuffer(O)&&this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}async switchRenderer(O){if(!this.canvas)throw Error("Cannot switch renderer: No canvas set");let $=this.rendererType;if(O===$)return;if(this.debug)console.warn(`Switching renderer from ${$} to ${O}. This will recreate the canvas element.`);if(this.canvas instanceof HTMLCanvasElement){let A=this.canvas,j=A.parentElement;if(!j)throw Error("Cannot switch renderer: Canvas has no parent element");let Q=document.createElement("canvas");if(Q.width=A.width,Q.height=A.height,Q.className=A.className,Q.id=A.id,Q.style.cssText=A.style.cssText,Array.from(A.attributes).forEach((V)=>{if(V.name!=="id"&&V.name!=="class"&&V.name!=="style")Q.setAttribute(V.name,V.value)}),this.renderer)this.renderer.dispose(),this.renderer=null;j.replaceChild(Q,A),this.canvas=Q;try{await this.initializeRenderer(Q,O)}catch(V){if(this.debug)console.error(`Failed to switch to ${O}:`,V);if(!this.renderer){if(this.renderer=new S({canvas:Q}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}else{if(this.debug)console.warn("Runtime switching for OffscreenCanvas may not work if context is already set");if(this.renderer)this.renderer.dispose(),this.renderer=null;try{await this.initializeRenderer(this.canvas,O)}catch(A){if(this.debug)console.error(`Failed to switch to ${O}:`,A);if(!this.renderer){if(this.renderer=new S({canvas:this.canvas}),this.rendererType="canvas2d",this.onRendererChange)this.onRendererChange("canvas2d")}}}if(this.currentFrame&&this.renderer&&this.renderer.isReady()){if(this.debug)console.log(`Re-rendering after switch to ${this.rendererType}`);queueMicrotask(()=>{if(this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)})}}setRendererChangeCallback(O){if(this.onRendererChange=O,this.renderer&&this.rendererType){if(this.debug)console.log(`Renderer already initialized as ${this.rendererType}, emitting change event`);O(this.rendererType)}}setRendererFallbackCallback(O){this.onRendererFallback=O}setRotationChangeCallback(O){this.onRotationChange=O}setRotation(O){if(this.rotation===O)return;if(this.rotation=O,this.renderer)this.renderer.setRotation(O);if(this.notifyRotationChange(),this.currentFrame&&this.renderer&&this.renderer.isReady())this.renderFrame(this.currentFrame)}getRotation(){return this.rotation}getDisplaySize(){let O=this.rotation===90||this.rotation===270;return{width:O?this.sourceHeight:this.sourceWidth,height:O?this.sourceWidth:this.sourceHeight}}notifyRotationChange(){if(this.onRotationChange&&this.sourceWidth>0&&this.sourceHeight>0)this.onRotationChange(this.rotation,this.getDisplaySize())}setPluginManager(O){this.pluginManager=O}static getSupportedRenderers(){return W.getSupportedRenderers()}async clearIterators(){if(this.renderingId++,this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}this.currentFrame=null,this.nextFrame=null}async disposeVideoResources(){if(this.disposed=!0,this.renderingId++,this.frameIterator){try{await this.frameIterator.return()}catch{}this.frameIterator=null}this.currentFrame=null,this.nextFrame=null,this.canvasSink=null,this.sampleSink=null,this.videoAspectRatio=null}dispose(){if(this.disposed=!0,this.renderingId++,this.frameIterator)this.frameIterator.return(),this.frameIterator=null;if(this.renderer)this.renderer.dispose(),this.renderer=null;this.cleanupResizeObserver(),this.cleanupOverlayCanvas(),this.currentFrame=null,this.nextFrame=null,this.canvasSink=null,this.sampleSink=null,this.onRendererChange=void 0,this.onRendererFallback=void 0}}var I=2,h="[MediaFox]";function bO(O){I=O}function wO(O,...$){if(I<=0)console.debug(`${h} ${O}`,...$)}function TO(O,...$){if(I<=1)console.info(`${h} ${O}`,...$)}function yO(O,...$){if(I<=2)console.warn(`${h} ${O}`,...$)}function fO(O,...$){if(I<=3)console.error(`${h} ${O}`,...$)}var k={setLevel:bO,debug:wO,info:TO,warn:yO,error:fO};class e{deps;constructor(O){this.deps=O}async load(O,$={}){try{let A=await this.deps.pluginManager.executeBeforeLoad(O);if(A?.cancel)return;if(A?.data!==void 0)O=A.data;await this.deps.playbackController.reset(),this.deps.sourceManager.disposeCurrent();let j=this.deps.state.getState();if(!$.replacePlaylist)this.deps.state.setState({...j,state:"loading",currentTime:$.startTime??0,playing:!1,paused:!0,ended:!1,seeking:!1,error:null,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null,buffered:[],canPlay:!1,canPlayThrough:!1});else this.deps.state.reset(),this.deps.state.updateLoadingState();this.deps.emit("loadstart",void 0);let Q=$.playlistItemId?this.deps.sourceManager.promoteQueuedSource($.playlistItemId):null;if(!Q)Q=await this.deps.sourceManager.createSource(O);let V=Q.input;if(!V)throw Error("Failed to create input from source");await this.deps.trackManager.initialize(V);let[J,K,Z,U]=await Promise.all([V.computeDuration(),V.getFormat(),V.getMimeType(),V.getMetadataTags()]),G={duration:J,format:K.name,mimeType:Z,metadata:U,hasVideo:this.deps.trackManager.hasVideo(),hasAudio:this.deps.trackManager.hasAudio(),hasSubtitles:this.deps.trackManager.hasSubtitles()};this.deps.state.updateDuration(J),this.deps.state.updateMediaInfo(G),this.deps.state.updateTracks(this.deps.trackManager.getVideoTracks(),this.deps.trackManager.getAudioTracks(),this.deps.trackManager.getSubtitleTracks()),this.deps.playbackController.setDuration(J);let L=Q.prefetchedData,P=L?.videoTrack??this.deps.trackManager.getPrimaryVideoTrack(),M=L?.audioTrack??this.deps.trackManager.getPrimaryAudioTrack();if(P&&L?.canvasSink&&L?.firstFrame)LO(P,{canvasSink:L.canvasSink,firstFrame:L.firstFrame});let X="",E=!1,Y=!1;if(P||M){let q=await this.deps.trackSwitcher.setupInitialTracks(P,M);X+=q.warningMessage,E=q.videoSupported,Y=q.audioSupported}if(!E&&!Y){if(!X)X="No audio or video track found.";throw Error(X)}if(X&&(E||Y))this.deps.emit("warning",{type:"codec-warning",message:X.trim(),error:void 0});if(this.deps.state.updateReadyState(!0,!0),this.deps.emit("loadedmetadata",G),this.deps.emit("loadeddata",void 0),this.deps.emit("canplay",void 0),this.deps.emit("canplaythrough",void 0),this.updateCurrentPlaylistItemDuration(J),await this.deps.pluginManager.executeAfterLoad(G),$.autoplay)await this.play();if($.startTime!==void 0)await this.seek($.startTime)}catch(A){throw this.handleError(A),A}}async play(){try{if(this.deps.state.getState().state==="idle")throw Error("No media loaded");if((await this.deps.pluginManager.executeBeforePlay())?.cancel)return;await this.deps.playbackController.play(),this.deps.state.updatePlaybackState(!0),this.deps.emit("play",void 0),this.deps.emit("playing",void 0),this.deps.pluginManager.executeAfterPlay()}catch(O){throw this.handleError(O),O}}async pause(){if((await this.deps.pluginManager.executeBeforePause())?.cancel)return;this.deps.playbackController.pause(),this.deps.state.updatePlaybackState(!1),this.deps.emit("pause",void 0),this.deps.pluginManager.executeAfterPause()}async seek(O){try{if(this.deps.state.getState().state==="idle")throw Error("No media loaded");let A=await this.deps.pluginManager.executeBeforeSeek(O);if(A?.cancel)return;if(A?.data!==void 0)O=A.data;this.deps.state.updateSeekingState(!0),this.deps.emit("seeking",{currentTime:O}),await this.deps.playbackController.seek(O),this.deps.state.updateSeekingState(!1),this.deps.state.updateTime(this.deps.playbackController.getCurrentTime()),this.deps.emit("seeked",{currentTime:this.deps.playbackController.getCurrentTime()}),this.deps.pluginManager.executeAfterSeek(this.deps.playbackController.getCurrentTime())}catch($){throw this.deps.state.updateSeekingState(!1),this.handleError($),$}}async stop(){try{if((await this.deps.pluginManager.executeBeforeStop())?.cancel)return;await this.pause(),await this.seek(0),this.deps.pluginManager.executeAfterStop()}catch(O){throw this.handleError(O),O}}handleError(O){if(this.deps.pluginManager.executeOnError(O))return;this.deps.state.updateError(O),this.deps.emit("error",O),k.error("Player error:",O)}updateCurrentPlaylistItemDuration(O){let $=this.deps.state.getState(),A=$.currentPlaylistIndex;if(A!==null&&$.playlist.length>0){let j=[...$.playlist],Q=j[A];if(Q)j[A]={...Q,duration:O},this.deps.state.updatePlaylist(j,A)}}}class OO{store;constructor(O){this.store=O}getState(){return this.store.getState()}subscribe(O){return this.store.subscribe(O)}setState(O){this.store.setState(O)}reset(){this.store.reset()}applyInitial(O,$,A){this.store.setState({volume:O,muted:$,playbackRate:A})}updateLoadingState(){this.store.updateLoadingState()}updateReadyState(O,$){this.store.updateReadyState(O,$)}updatePlaybackState(O){this.store.updatePlaybackState(O)}updateSeekingState(O){this.store.updateSeekingState(O)}updateWaitingState(O){this.store.updateWaitingState(O)}updateEndedState(O){this.store.updateEndedState(O)}updateTime(O){this.store.updateTime(O)}updateDuration(O){this.store.updateDuration(O)}updateVolume(O,$){this.store.updateVolume(O,$)}updatePlaybackRate(O){this.store.updatePlaybackRate(O)}updateMediaInfo(O){this.store.updateMediaInfo(O)}updateTracks(O,$,A){this.store.updateTracks(O,$,A)}updateSelectedTracks(O,$){this.store.updateSelectedTracks(O,$)}updateError(O){this.store.updateError(O)}updateRendererType(O){this.store.updateRendererType(O)}updatePlaylist(O,$=null){this.store.updatePlaylist(O,$)}}class $O{chains=new Map;async run(O,$){let A=this.chains.get(O)??Promise.resolve(),j,Q=new Promise((V)=>{j=V});this.chains.set(O,A.then(()=>Q));try{return await A,await $()}finally{j?.()}}}class AO{deps;locks=new $O;constructor(O){this.deps=O}async setupInitialTracks(O,$){let A=!1,j=!1,Q="";if(O)try{if(A=await this.locks.run("video",async()=>{if(O.codec!==null&&await O.canDecode())return await this.deps.playbackController.trySetVideoTrack(O);return!1}),!A)Q+="Unsupported video codec. "}catch(V){Q+="Failed to set up video track. ",k.warn("Video track error:",V)}if($)try{if(j=await this.locks.run("audio",async()=>{if($.codec!==null&&await $.canDecode())return await this.deps.playbackController.trySetAudioTrack($);return!1}),!j)Q+="Unsupported audio codec. "}catch(V){Q+="Failed to set up audio track. ",k.warn("Audio track error:",V)}if(!A&&!j&&!Q)Q="No audio or video track found.";return{videoSupported:A,audioSupported:j,warningMessage:Q}}async selectVideoTrack(O,$){if(!O.selectVideoTrack($))throw Error(`Invalid video track ID: ${$}`);let A=O.getSelectedVideoTrack();if(!A){await this.deps.playbackController.setVideoTrack(null);return}if(!await this.locks.run("video",async()=>{if(A.codec!==null&&await A.canDecode())return await this.deps.playbackController.trySetVideoTrack(A);return!1}))this.deps.emit("warning",{type:"video-codec-unsupported",message:"Video codec not supported.",error:void 0}),await this.deps.playbackController.setVideoTrack(null)}async selectAudioTrack(O,$){if(!O.selectAudioTrack($))throw Error(`Invalid audio track ID: ${$}`);let A=O.getSelectedAudioTrack();if(!A){await this.deps.playbackController.setAudioTrack(null);return}if(!await this.locks.run("audio",async()=>{if(A.codec!==null&&await A.canDecode())return await this.deps.playbackController.trySetAudioTrack(A);return!1}))this.deps.emit("warning",{type:"audio-codec-unsupported",message:"Audio codec not supported. Continuing without audio.",error:void 0}),await this.deps.playbackController.setAudioTrack(null)}}import{AudioBufferSink as xO,AudioSampleSink as IO}from"mediabunny";class p{audioContext;gainNode=null;outputNode=null;bufferSink=null;sampleSink=null;bufferIterator=null;queuedNodes=new Set;startContextTime=0;startMediaTime=0;pauseTime=0;playing=!1;volume=1;muted=!1;disposed=!1;playbackId=0;playbackRate=1;pluginManager=null;constructor(O={}){if(O.audioContext)this.audioContext=O.audioContext;else{let $=window,A=$.AudioContext||$.webkitAudioContext;this.audioContext=new A}this.volume=O.volume??1,this.muted=O.muted??!1,this.setupAudioGraph()}setupAudioGraph(){if(this.gainNode=this.audioContext.createGain(),this.pluginManager){let O=this.pluginManager.executeOnAudioNode(this.audioContext,this.gainNode);this.outputNode=O}else this.outputNode=this.gainNode;this.outputNode.connect(this.audioContext.destination),this.updateGain()}setPluginManager(O){this.pluginManager=O,this.rebuildAudioGraph()}rebuildAudioGraph(){if(!this.gainNode)return;if(this.outputNode?.disconnect(),this.pluginManager){let O=this.pluginManager.executeOnAudioNode(this.audioContext,this.gainNode);this.outputNode=O}else this.outputNode=this.gainNode;this.outputNode.connect(this.audioContext.destination)}async setAudioTrack(O){if(this.dispose(),O.codec===null)throw Error("Unsupported audio codec");if(!await O.canDecode())throw Error(`Cannot decode audio track with codec: ${O.codec}`);this.bufferSink=new xO(O),this.sampleSink=new IO(O),this.disposed=!1}async play(O=this.pauseTime){if(this.playing||!this.bufferSink)return;if(this.audioContext.state==="suspended")await this.audioContext.resume();this.playbackId++;let $=this.playbackId;this.playing=!0,this.startContextTime=this.audioContext.currentTime,this.startMediaTime=O,this.pauseTime=O,this.bufferIterator=this.bufferSink.buffers(O),this.scheduleAudioBuffers($)}async scheduleAudioBuffers(O){let $=this.bufferIterator;if(!$||!this.gainNode)return;try{for await(let{buffer:A,timestamp:j}of $){if(O!==this.playbackId||this.disposed||!this.playing)break;let Q=this.audioContext.createBufferSource();Q.buffer=A,Q.connect(this.gainNode),Q.playbackRate.value=this.playbackRate,Q.playbackRate.setValueAtTime(this.playbackRate,this.audioContext.currentTime);let V=this.startContextTime+(j-this.startMediaTime)/this.playbackRate;if(V>=this.audioContext.currentTime)Q.start(V);else{let J=Math.max(0,(this.audioContext.currentTime-V)*this.playbackRate);if(J<A.duration)Q.start(this.audioContext.currentTime,J);else continue}if(this.queuedNodes.add(Q),Q.onended=()=>{this.queuedNodes.delete(Q)},j-this.getCurrentTime()>=1)await this.waitForCatchup(j)}}catch{}}async waitForCatchup(O){return new Promise(($)=>{let A=setInterval(()=>{if(O-this.getCurrentTime()<1||!this.playing)clearInterval(A),$()},100)})}pause(){if(!this.playing)return;let O=this.getCurrentTime();if(this.playing=!1,this.pauseTime=O,this.stopQueuedNodes(),this.bufferIterator)this.bufferIterator.return(),this.bufferIterator=null}stop(){this.pause(),this.pauseTime=0,this.startContextTime=0,this.startMediaTime=0}async seek(O){let $=this.playing;if($)this.pause();if(this.pauseTime=O,$)await this.play(O)}getCurrentTime(){if(this.playing){let O=this.audioContext.currentTime-this.startContextTime;return this.startMediaTime+O*this.playbackRate}return this.pauseTime}setVolume(O){this.volume=Math.max(0,Math.min(1,O)),this.updateGain()}setMuted(O){this.muted=O,this.updateGain()}updateGain(){if(!this.gainNode)return;let O=this.muted?0:this.volume;this.gainNode.gain.value=O*O}getVolume(){return this.volume}isMuted(){return this.muted}isPlaying(){return this.playing}setPlaybackRate(O){let $=Math.max(0.25,Math.min(4,O));if(this.playbackRate===$)return;let A=this.playing,j=this.getCurrentTime();if(this.playbackRate=$,A)this.pause(),this.pauseTime=j,this.play(j)}getAudioContext(){return this.audioContext}async getBufferAt(O){if(!this.bufferSink)return null;return this.bufferSink.getBuffer(O)}async getSampleAt(O){if(!this.sampleSink)return null;return this.sampleSink.getSample(O)}stopQueuedNodes(){for(let O of this.queuedNodes)try{O.stop()}catch{}this.queuedNodes.clear()}async clearIterators(){if(this.playbackId++,this.stop(),this.bufferIterator){try{await this.bufferIterator.return()}catch{}this.bufferIterator=null}}dispose(){if(this.disposed=!0,this.playbackId++,this.stop(),this.bufferIterator)this.bufferIterator.return(),this.bufferIterator=null;this.bufferSink=null,this.sampleSink=null}destroy(){if(this.dispose(),this.gainNode)this.gainNode.disconnect(),this.gainNode=null;if(this.audioContext.state!=="closed")this.audioContext.close()}}var kO=100,vO=250;class g{videoRenderer;audioManager;playing=!1;currentTime=0;duration=0;playbackRate=1;animationFrameId=null;lastFrameTime=0;syncIntervalId=null;renderIntervalId=null;isWaiting=!1;onTimeUpdate;onEnded;onWaiting;onPlaying;constructor(O={}){this.videoRenderer=new v({canvas:O.canvas,rendererType:O.rendererType}),this.audioManager=new p({audioContext:O.audioContext,volume:O.volume,muted:O.muted}),this.playbackRate=O.playbackRate??1}async setVideoTrack(O){if(!O){this.videoRenderer.dispose();return}await this.videoRenderer.setVideoTrack(O);let $=await O.computeDuration();this.duration=Math.max(this.duration,$)}async trySetVideoTrack(O){try{return await this.setVideoTrack(O),!0}catch{return!1}}async setAudioTrack(O){let $=this.playing,A=this.getCurrentTime();if(!O){this.audioManager.dispose();return}let j=await O.computeDuration(),Q=Math.max(0,Math.min(A,j));if(await this.audioManager.setAudioTrack(O),await this.audioManager.seek(Q),$)await this.audioManager.play(Q);this.currentTime=Q,this.duration=Math.max(this.duration,j)}async trySetAudioTrack(O){try{return await this.setAudioTrack(O),!0}catch{return!1}}async setCanvas(O){await this.videoRenderer.setCanvas(O)}async play(){if(this.playing)return;if(this.playing=!0,this.lastFrameTime=performance.now(),this.currentTime>=this.duration)this.currentTime=0,await this.videoRenderer.seek(0);await this.audioManager.play(this.currentTime),this.startRenderLoop(),this.startSyncInterval()}pause(){if(!this.playing)return;if(this.playing=!1,this.isWaiting=!1,this.audioManager.pause(),this.stopRenderLoop(),this.stopSyncInterval(),this.audioManager.isPlaying())this.currentTime=this.audioManager.getCurrentTime()}async seek(O){let $=Math.max(0,Math.min(O,this.duration));if(this.currentTime=$,await this.videoRenderer.seek($),await this.audioManager.seek($),this.onTimeUpdate)this.onTimeUpdate(this.currentTime)}startRenderLoop(){if(this.animationFrameId!==null||this.renderIntervalId!==null)return;let O=($=!0)=>{if(!this.playing)return;if(this.audioManager.isPlaying())this.currentTime=this.audioManager.getCurrentTime();else{let j=performance.now(),Q=(j-this.lastFrameTime)/1000;this.lastFrameTime=j,this.currentTime+=Q*this.playbackRate}if(this.currentTime>=this.duration){this.handleEnded();return}let{isStarving:A}=this.videoRenderer.updateFrame(this.currentTime);if(A&&!this.isWaiting){if(this.isWaiting=!0,this.onWaiting)this.onWaiting()}else if(!A&&this.isWaiting){if(this.isWaiting=!1,this.onPlaying)this.onPlaying()}if($)this.animationFrameId=requestAnimationFrame(()=>O())};if(this.animationFrameId=requestAnimationFrame(()=>O()),this.renderIntervalId===null)this.renderIntervalId=window.setInterval(()=>O(!1),kO)}stopRenderLoop(){if(this.animationFrameId!==null)cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null;if(this.renderIntervalId!==null)clearInterval(this.renderIntervalId),this.renderIntervalId=null}startSyncInterval(){if(this.syncIntervalId!==null)return;this.syncIntervalId=window.setInterval(()=>{if(this.playing&&this.onTimeUpdate)this.onTimeUpdate(this.currentTime)},vO)}stopSyncInterval(){if(this.syncIntervalId!==null)clearInterval(this.syncIntervalId),this.syncIntervalId=null}handleEnded(){if(this.pause(),this.currentTime=this.duration,this.onEnded)this.onEnded()}getCurrentTime(){if(this.playing&&this.audioManager.isPlaying())return this.audioManager.getCurrentTime();return this.currentTime}getDuration(){return this.duration}setDuration(O){this.duration=O}isPlaying(){return this.playing}setVolume(O){this.audioManager.setVolume(O)}getVolume(){return this.audioManager.getVolume()}setMuted(O){this.audioManager.setMuted(O)}isMuted(){return this.audioManager.isMuted()}setPlaybackRate(O){let $=Math.max(0.25,Math.min(4,O));if(this.playbackRate===$)return;this.playbackRate=$,this.audioManager.setPlaybackRate($),this.lastFrameTime=performance.now()}getPlaybackRate(){return this.playbackRate}setTimeUpdateCallback(O){this.onTimeUpdate=O}setEndedCallback(O){this.onEnded=O}setWaitingCallback(O){this.onWaiting=O}setPlayingCallback(O){this.onPlaying=O}isBuffering(){return this.isWaiting}async screenshot(O){return this.videoRenderer.screenshot(this.currentTime,O)}getVideoRenderer(){return this.videoRenderer}getAudioManager(){return this.audioManager}async switchRenderer(O){await this.videoRenderer.switchRenderer(O)}getRendererType(){return this.videoRenderer.getRendererType()}updateCanvasDimensions(){this.videoRenderer.updateCanvasDimensions()}setRendererChangeCallback(O){this.videoRenderer.setRendererChangeCallback(O)}setRendererFallbackCallback(O){this.videoRenderer.setRendererFallbackCallback(O)}setRotationChangeCallback(O){this.videoRenderer.setRotationChangeCallback(O)}setRotation(O){this.videoRenderer.setRotation(O)}getRotation(){return this.videoRenderer.getRotation()}getDisplaySize(){return this.videoRenderer.getDisplaySize()}setPluginManager(O){this.videoRenderer.setPluginManager(O),this.audioManager.setPluginManager(O)}getCanvas(){return this.videoRenderer.getCanvas()}refreshOverlays(){this.videoRenderer.refreshOverlays()}rebuildAudioGraph(){this.audioManager.rebuildAudioGraph()}async reset(){this.pause(),this.stopRenderLoop(),this.stopSyncInterval(),this.currentTime=0,this.duration=0,await Promise.all([this.videoRenderer.clearIterators(),this.audioManager.clearIterators()]),this.playbackRate=1,this.lastFrameTime=0}dispose(){this.pause(),this.videoRenderer.dispose(),this.audioManager.dispose(),this.onTimeUpdate=void 0,this.onEnded=void 0,this.onWaiting=void 0,this.onPlaying=void 0}destroy(){this.dispose(),this.audioManager.destroy()}}function m(){return crypto?.randomUUID?.()??Date.now().toString(36)+Math.random().toString(36).substr(2)}class jO{store;emitter;switchSource;sourceManager;constructor(O,$,A,j){this.store=O,this.emitter=$,this.switchSource=A,this.sourceManager=j}async loadPlaylist(O,$={}){let A=O.map((j)=>{if(j&&typeof j==="object"&&"mediaSource"in j)return{id:m(),mediaSource:j.mediaSource,title:j.title,poster:j.poster,savedPosition:null,duration:null};else return{id:m(),mediaSource:j,savedPosition:null,duration:null}});if(this.store.updatePlaylist(A,A.length>0?0:null),this.emitter.emit("playlistchange",{playlist:A}),A.length>0&&this.switchSource){let j=A[0];if($.startTime!==void 0)j.savedPosition=$.startTime;await this.switchSource(j,$.autoplay??!1)}}addToPlaylist(O,$){let A=this.createPlaylistItem(O);this.store.addToPlaylist(A,$),this.emitter.emit("playlistadd",{item:A,index:$??this.store.getState().playlist.length-1})}async removeFromPlaylist(O){let $=this.store.getState(),A=$.currentPlaylistIndex,j=$.playing;this.store.removeFromPlaylist(O),this.emitter.emit("playlistremove",{index:O}),this.sourceManager?.disposeQueued($.playlist[O]?.id||"");let Q=this.store.getState(),V=Q.currentPlaylistIndex;if(Q.playlist.length===0)this.sourceManager?.disposeAll(),this.emitter.emit("playlistchange",{playlist:Q.playlist}),this.emitter.emit("playlistend",void 0);if(A===O&&V!==null&&V!==A&&this.switchSource){let J=Q.playlist[V];try{await this.switchSource(J,j)}catch(K){this.emitter.emit("playlistitemerror",{index:V,error:K})}}}clearPlaylist(){this.store.clearPlaylist(),this.emitter.emit("playlistchange",{playlist:[]}),this.emitter.emit("playlistend",void 0),this.sourceManager?.disposeAll()}async next(){let O=this.store.getState(),$=O.currentPlaylistIndex??0,A=O.playlist,j=O.playlistMode,Q=null;if(j==="repeat-one")Q=$;else if(j==="sequential"||j==="repeat")if($<A.length-1)Q=$+1;else if(j==="repeat")Q=0;else{this.emitter.emit("playlistend",void 0);return}else if($<A.length-1)Q=$+1;if(Q!==null)await this.switchTo(Q)}async prev(){let $=this.store.getState().currentPlaylistIndex??0;if($>0)await this.switchTo($-1)}async jumpTo(O){let A=this.store.getState().playlist;if(O>=0&&O<A.length)await this.switchTo(O);else if(O>=A.length)this.emitter.emit("playlistend",void 0)}setMode(O){let $=["sequential","manual","repeat","repeat-one",null];if(!$.includes(O))throw Error(`Invalid playlist mode: ${O}. Valid modes: ${$.filter((A)=>A!==null).join(", ")}, null`);this.store.updatePlaylistMode(O)}async switchTo(O){let $=this.store.getState(),A=$.currentPlaylistIndex,j=$.playing,Q=[...$.playlist];if(A!==null&&A!==O){let K=Q[A];Q[A]={...K,savedPosition:$.currentTime}}this.store.updatePlaylist(Q,O);let V=Q[O];if(this.emitter.emit("playlistitemchange",{index:O,item:V,previousIndex:A??void 0}),this.switchSource)await this.switchSource(V,j);if($.playlistMode==="sequential"&&O<Q.length-1){let K=Q[O+1];this.sourceManager?.preloadSource(K.mediaSource,K.id)}}createPlaylistItem(O){if(O&&typeof O==="object"&&"mediaSource"in O)return{id:m(),mediaSource:O.mediaSource,title:O.title,poster:O.poster,savedPosition:null,duration:null};else return{id:m(),mediaSource:O,savedPosition:null,duration:null}}get playlist(){return this.store.getState().playlist}get currentIndex(){return this.store.getState().currentPlaylistIndex}get currentItem(){let O=this.currentIndex;return O!==null?this.playlist[O]:null}get mode(){return this.store.getState().playlistMode}dispose(){if(this.sourceManager)this.sourceManager=void 0;this.switchSource=void 0}}function PO(O,$,A,j){let Q=$.name;return{player:O,getState(){return O.getState()},subscribe(V){let J=O.subscribe(V),K=()=>J.unsubscribe();return A.stateUnsubscribes.push(K),K},getPluginState(){return A.pluginState},setPluginState(V){A.pluginState=V},on(V,J){O.on(V,J);let K=A.eventListeners.get(V);if(!K)K=new Set,A.eventListeners.set(V,K);K.add(J)},off(V,J){O.off(V,J);let K=A.eventListeners.get(V);if(K)K.delete(J)},getCanvas(){return O.getRenderTarget()},getPlugin(V){return j().get(V)?.plugin},hasPlugin(V){return j().has(V)},log(...V){console.log(`[MediaFox:${Q}]`,...V)},warn(...V){console.warn(`[MediaFox:${Q}]`,...V)},error(...V){console.error(`[MediaFox:${Q}]`,...V)}}}class QO{player;plugins=new Map;overlays=[];overlaysSorted=!1;registrationCounter=0;constructor(O){this.player=O}async install(O){let{name:$}=O;if(this.plugins.has($))throw Error(`Plugin "${$}" is already installed`);if(O.dependencies){for(let j of O.dependencies)if(!this.plugins.has(j))throw Error(`Plugin "${$}" requires plugin "${j}" to be installed first`)}let A={plugin:O,context:null,eventListeners:new Map,stateUnsubscribes:[],pluginState:void 0};A.context=PO(this.player,O,A,()=>this.plugins),this.plugins.set($,A);try{await O.install(A.context)}catch(j){throw this.plugins.delete($),j}if(O.hooks?.render?.onOverlay)this.overlays.push({pluginName:$,zIndex:O.hooks.render.onOverlay.zIndex??0,registrationOrder:this.registrationCounter++,render:O.hooks.render.onOverlay}),this.overlaysSorted=!1,this.player.refreshOverlays()}async uninstall(O){let $=this.plugins.get(O);if(!$)throw Error(`Plugin "${O}" is not installed`);try{await $.plugin.uninstall?.()}catch(j){console.error(`Error uninstalling plugin "${O}":`,j)}for(let[j,Q]of $.eventListeners)for(let V of Q)this.player.off(j,V);for(let j of $.stateUnsubscribes)j();let A=this.overlays.some((j)=>j.pluginName===O);if(this.overlays=this.overlays.filter((j)=>j.pluginName!==O),this.plugins.delete(O),A)this.player.refreshOverlays()}has(O){return this.plugins.has(O)}get size(){return this.plugins.size}async executeBeforeLoad(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.beforeLoad;if(!A)continue;try{let j=await A.call($.plugin,O);if(j?.cancel)return j;if(j?.data!==void 0)O=j.data}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in beforeLoad hook:`,j)}}return{data:O}}async executeAfterLoad(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.afterLoad;if(!A)continue;try{await A.call($.plugin,O)}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in afterLoad hook:`,j)}}}async executeBeforePlay(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforePlay;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforePlay hook:`,A)}}return}executeAfterPlay(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterPlay;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterPlay hook:`,A)}}}async executeBeforePause(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforePause;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforePause hook:`,A)}}return}executeAfterPause(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterPause;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterPause hook:`,A)}}}async executeBeforeSeek(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.beforeSeek;if(!A)continue;try{let j=await A.call($.plugin,O);if(j?.cancel)return j;if(j?.data!==void 0)O=j.data}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in beforeSeek hook:`,j)}}return{data:O}}executeAfterSeek(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.lifecycle?.afterSeek;if(!A)continue;try{A.call($.plugin,O)}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in afterSeek hook:`,j)}}}async executeBeforeStop(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.beforeStop;if(!$)continue;try{let A=await $.call(O.plugin);if(A?.cancel)return A}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in beforeStop hook:`,A)}}return}executeAfterStop(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.afterStop;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in afterStop hook:`,A)}}}executeOnError(O){let $=!1;for(let[,A]of this.plugins){let j=A.plugin.hooks?.lifecycle?.onError;if(!j)continue;try{if(j.call(A.plugin,O)?.handled)$=!0}catch(Q){console.error(`[MediaFox:${A.plugin.name}] Error in onError hook:`,Q)}}return $}executeOnEnded(){for(let[,O]of this.plugins){let $=O.plugin.hooks?.lifecycle?.onEnded;if(!$)continue;try{$.call(O.plugin)}catch(A){console.error(`[MediaFox:${O.plugin.name}] Error in onEnded hook:`,A)}}}executeBeforeRender(O,$){for(let[,A]of this.plugins){let j=A.plugin.hooks?.render?.beforeRender;if(!j)continue;try{let Q=j.call(A.plugin,O,$);if(Q?.skip)return Q}catch(Q){console.error(`[MediaFox:${A.plugin.name}] Error in beforeRender hook:`,Q)}}return}executeTransformFrame(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.render?.transformFrame;if(!A)continue;try{let j=A.call($.plugin,O);if(j)O=j}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in transformFrame hook:`,j)}}return O}executeAfterRender(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.render?.afterRender;if(!A)continue;try{A.call($.plugin,O)}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in afterRender hook:`,j)}}}executeOverlays(O,$,A){if(this.overlays.length===0)return;if(!this.overlaysSorted)this.overlays.sort((j,Q)=>{if(j.zIndex!==Q.zIndex)return j.zIndex-Q.zIndex;return j.registrationOrder-Q.registrationOrder}),this.overlaysSorted=!0;for(let j of this.overlays)try{j.render?.render(O,$,A)}catch(Q){console.error(`[MediaFox:${j.pluginName}] Error in onOverlay hook:`,Q)}}executeBeforeStateUpdate(O){for(let[,$]of this.plugins){let A=$.plugin.hooks?.state?.beforeStateUpdate;if(!A)continue;try{let j=A.call($.plugin,O);if(j===null)return null;if(j!==void 0)O=j}catch(j){console.error(`[MediaFox:${$.plugin.name}] Error in beforeStateUpdate hook:`,j)}}return O}executeOnStateChange(O,$){for(let[,A]of this.plugins){let j=A.plugin.hooks?.state?.onStateChange;if(!j)continue;try{j.call(A.plugin,O,$)}catch(Q){console.error(`[MediaFox:${A.plugin.name}] Error in onStateChange hook:`,Q)}}}executeBeforeEvent(O,$){for(let[,A]of this.plugins){let j=A.plugin.hooks?.event?.beforeEvent;if(!j)continue;try{let Q=j.call(A.plugin,O,$);if(Q?.cancel)return Q;if(Q?.data!==void 0)$=Q.data}catch(Q){console.error(`[MediaFox:${A.plugin.name}] Error in beforeEvent hook:`,Q)}}return{data:$}}executeAfterEvent(O,$){for(let[,A]of this.plugins){let j=A.plugin.hooks?.event?.afterEvent;if(!j)continue;try{j.call(A.plugin,O,$)}catch(Q){console.error(`[MediaFox:${A.plugin.name}] Error in afterEvent hook:`,Q)}}}executeOnAudioNode(O,$){let A=$;for(let[,j]of this.plugins){let Q=j.plugin.hooks?.audio?.onAudioNode;if(!Q)continue;try{let V=Q.call(j.plugin,O,$);if(V)A=V}catch(V){console.error(`[MediaFox:${j.plugin.name}] Error in onAudioNode hook:`,V)}}return A}async dispose(){let O=Array.from(this.plugins.keys()).reverse();for(let $ of O)try{await this.uninstall($)}catch(A){console.error(`Error disposing plugin "${$}":`,A)}}}import{ALL_FORMATS as hO,BlobSource as pO,BufferSource as gO,CanvasSink as mO,FilePathSource as uO,Input as lO,ReadableStreamSource as cO,UrlSource as oO}from"mediabunny";class u{currentSource=null;queuedSources=new Map;options;constructor(O={}){this.options={maxCacheSize:O.maxCacheSize??16777216,crossOrigin:O.crossOrigin,requestInit:O.requestInit}}async createSource(O,$){if(this.currentSource&&!$)this.disposeCurrent();let A,j;if(O instanceof File||O instanceof Blob)A=new pO(O,{maxCacheSize:this.options.maxCacheSize}),j="blob";else if(O instanceof ArrayBuffer||O instanceof Uint8Array)A=new gO(O),j="buffer";else if(typeof O==="string"||O instanceof URL){let J=O instanceof URL?O.href:O;if(typeof window>"u"&&!J.startsWith("http"))A=new uO(J,{maxCacheSize:this.options.maxCacheSize}),j="file";else A=new oO(J,{maxCacheSize:this.options.maxCacheSize,requestInit:this.options.requestInit}),j="url"}else if(typeof ReadableStream<"u"&&O instanceof ReadableStream)A=new cO(O,{maxCacheSize:this.options.maxCacheSize}),j="stream";else throw TypeError("Unsupported media source type");let Q=new lO({source:A,formats:hO}),V={source:A,input:Q,type:j,originalSource:O};if($)this.queuedSources.set($,V);else this.currentSource=V;return V}getCurrentSource(){return this.currentSource}getQueuedSource(O){return this.queuedSources.get(O)||null}async preloadSource(O,$){if(this.queuedSources.has($))return;let A=await this.createSource(O,$);if(A.input)try{let j=await this.prefetchTrackData(A.input);A.prefetchedData=j}catch{}}async prefetchTrackData(O){let $=await O.getVideoTracks(),A=await O.getAudioTracks(),j=$.length>0?$[0]:null,Q=A.length>0?A[0]:null,V=null,J=null,K=0;if(j){if(j.codec!==null&&await j.canDecode()){V=new mO(j,{poolSize:2});let Z=V.canvases(0);J=(await Z.next()).value??null,await Z.return(),K=await j.computeDuration()}}if(!K&&Q)K=await Q.computeDuration();return{videoTrack:j,audioTrack:Q,canvasSink:V,firstFrame:J,duration:K}}promoteQueuedSource(O){let $=this.queuedSources.get(O);if(!$)return null;if(this.queuedSources.delete(O),this.currentSource)this.currentSource.input?.dispose();return this.currentSource=$,$}getOriginalSource(){return this.currentSource?.originalSource??null}disposeCurrent(){if(this.currentSource)this.currentSource.input?.dispose(),this.currentSource=null}disposeQueued(O){let $=this.queuedSources.get(O);if($)$.input?.dispose(),this.queuedSources.delete(O)}disposeAll(){this.disposeCurrent(),this.queuedSources.forEach((O,$)=>{this.disposeQueued($)}),this.queuedSources.clear()}dispose(){this.disposeAll()}static isStreamingSource(O){return O instanceof ReadableStream||typeof O==="string"&&O.startsWith("http")}static isLocalSource(O){return O instanceof File||O instanceof Blob||O instanceof ArrayBuffer||O instanceof Uint8Array||typeof O==="string"&&!O.startsWith("http")}static getSourceType(O){if(O instanceof File)return"file";if(O instanceof Blob)return"blob";if(O instanceof ArrayBuffer||O instanceof Uint8Array)return"buffer";if(O instanceof ReadableStream)return"stream";if(typeof O==="string"||O instanceof URL)return(O instanceof URL?O.href:O).startsWith("http")?"url":"file";return"unknown"}static async fromFetch(O,$){let A=await fetch(O,$);if(!A.ok)throw Error(`Failed to fetch: ${A.status} ${A.statusText}`);return A.blob()}static fromStreamingFetch(O,$){return new ReadableStream({async start(A){let j=await fetch(O,$);if(!j.ok){A.error(Error(`Failed to fetch: ${j.status} ${j.statusText}`));return}let Q=j.body?.getReader();if(!Q){A.error(Error("Response body is not readable"));return}try{while(!0){let{done:V,value:J}=await Q.read();if(V)break;A.enqueue(J)}A.close()}catch(V){A.error(V)}}})}}function l(O,$){if(Object.is(O,$))return!0;if(typeof O!==typeof $)return!1;if(O===null||$===null)return O===$;if(Array.isArray(O)&&Array.isArray($)){if(O.length!==$.length)return!1;for(let A=0;A<O.length;A++)if(!l(O[A],$[A]))return!1;return!0}if(XO(O)&&XO($)){let A=Object.keys(O),j=Object.keys($);if(A.length!==j.length)return!1;for(let Q of A){if(!Object.hasOwn($,Q))return!1;if(!l(O[Q],$[Q]))return!1}return!0}return!1}function XO(O){return typeof O==="object"&&O!==null&&O.constructor===Object}class c{state;previousState;listeners=new Set;updateScheduled=!1;pendingUpdates={};pendingKeys=[];pluginManager=null;listenerCache=[];constructor(){this.state=this.getInitialState(),this.previousState={...this.state}}setPluginManager(O){this.pluginManager=O}getInitialState(){let $=W.getSupportedRenderers()[0]||"canvas2d";return{state:"idle",currentTime:0,duration:0,buffered:[],volume:1,muted:!1,playbackRate:1,playing:!1,paused:!0,ended:!1,seeking:!1,waiting:!1,error:null,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null,canPlay:!1,canPlayThrough:!1,isLive:!1,rendererType:$,playlist:[],currentPlaylistIndex:null,playlistMode:null,rotation:0,displaySize:{width:0,height:0}}}getState(){return this.state}setState(O){if(this.pluginManager){let A=this.pluginManager.executeBeforeStateUpdate(O);if(A===null)return;O=A}let $=Object.keys(O);for(let A=0;A<$.length;A++){let j=$[A];if(this.pendingUpdates[j]===void 0)this.pendingKeys.push(j);this.setPendingValue(j,O[j])}if(!this.updateScheduled)this.updateScheduled=!0,queueMicrotask(()=>this.flushUpdates())}setPendingValue(O,$){this.pendingUpdates[O]=$}flushUpdates(){let O=this.pendingKeys;if(O.length===0){this.updateScheduled=!1;return}let $=!1;for(let A=0;A<O.length;A++){let j=O[A];if(!l(this.pendingUpdates[j],this.state[j])){$=!0;break}}for(let A=0;A<O.length;A++){let j=O[A];this.copyStateKey(j)}if(this.pendingUpdates={},this.pendingKeys.length=0,this.updateScheduled=!1,$){if(this.notifyListeners(),this.pluginManager)this.pluginManager.executeOnStateChange(this.state,this.previousState)}}copyStateKey(O){if(this.previousState[O]=this.state[O],O in this.pendingUpdates)this.state[O]=this.pendingUpdates[O]}subscribe(O){return this.listeners.add(O),O(this.getState()),()=>{this.listeners.delete(O)}}reset(){this.state=this.getInitialState(),this.pendingUpdates={},this.pendingKeys.length=0,this.updateScheduled=!1,this.notifyListeners()}notifyListeners(){let O=this.state,$=this.listenerCache;$.length=0;for(let A of this.listeners)$.push(A);for(let A=0;A<$.length;A++)try{$[A](O)}catch(j){console.error("Error in state listener:",j)}}updatePlaybackState(O){let $=O?"playing":"paused";this.setState({state:$,playing:O,paused:!O,ended:!1})}updateTime(O){this.setState({currentTime:O})}updateDuration(O){this.setState({duration:O})}updateBuffered(O){this.setState({buffered:O})}updateVolume(O,$){this.setState({volume:O,muted:$})}updatePlaybackRate(O){this.setState({playbackRate:O})}updateMediaInfo(O){this.setState({mediaInfo:O})}updateTracks(O,$,A){let j={};if(O)j.videoTracks=O;if($)j.audioTracks=$;if(A)j.subtitleTracks=A;this.setState(j)}updateSelectedTracks(O,$){switch(O){case"video":this.setState({selectedVideoTrack:$});break;case"audio":this.setState({selectedAudioTrack:$});break;case"subtitle":this.setState({selectedSubtitleTrack:$});break}}updateError(O){this.setState({error:O,state:O?"error":this.state.state})}updateSeekingState(O){this.setState({seeking:O})}updateWaitingState(O){this.setState({waiting:O})}updateReadyState(O,$){this.setState({canPlay:O,canPlayThrough:$,state:O?"ready":this.state.state})}updateEndedState(O){this.setState({ended:O,playing:!1,paused:!0,state:O?"ended":this.state.state})}updateLoadingState(){this.setState({state:"loading",playing:!1,paused:!0,ended:!1,error:null})}updateRendererType(O){this.setState({rendererType:O})}updateRotation(O,$){this.setState({rotation:O,displaySize:$})}updatePlaylist(O,$=null){this.setState({playlist:O,currentPlaylistIndex:$})}updateCurrentPlaylistIndex(O){this.setState({currentPlaylistIndex:O})}updatePlaylistMode(O){this.setState({playlistMode:O})}addToPlaylist(O,$){let A=this.state.playlist,j,Q=this.state.currentPlaylistIndex;if($!==void 0&&$>=0&&$<=A.length){if(j=[...A.slice(0,$),O,...A.slice($)],Q!==null&&Q>=$)Q+=1}else j=[...A,O];this.setState({playlist:j,currentPlaylistIndex:Q})}removeFromPlaylist(O){let $=this.state.playlist;if(O<0||O>=$.length)return;let A=$.filter((Q,V)=>V!==O),j=this.state.currentPlaylistIndex;if(j===O)j=A.length>0?0:null;else if(j!==null&&j>O)j-=1;if(A.length===0)this.setState({playlist:A,currentPlaylistIndex:null,state:"idle",currentTime:0,duration:0,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null});else this.setState({playlist:A,currentPlaylistIndex:j})}clearPlaylist(){this.setState({playlist:[],currentPlaylistIndex:null,state:"idle",currentTime:0,duration:0,mediaInfo:null,videoTracks:[],audioTracks:[],subtitleTracks:[],selectedVideoTrack:null,selectedAudioTrack:null,selectedSubtitleTrack:null})}}class o{input=null;videoTracks=new Map;audioTracks=new Map;videoTrackInfos=[];audioTrackInfos=[];subtitleTrackInfos=[];subtitleProviders=new Map;subtitleTrackResolvers=new Map;selectedVideoTrack=null;selectedAudioTrack=null;selectedSubtitleTrack=null;onTrackChange;async initialize(O){this.videoTracks.clear(),this.audioTracks.clear(),this.videoTrackInfos=[],this.audioTrackInfos=[],this.selectedVideoTrack=null,this.selectedAudioTrack=null,this.input=O,await this.loadTracks()}async loadTracks(){if(!this.input)return;let O=await this.input.getVideoTracks();this.videoTrackInfos=await Promise.all(O.map(async(A)=>{let j=`video-${A.id}`;this.videoTracks.set(j,A);let Q=0,V=0;try{let K=await A.computePacketStats(100);Q=K.averagePacketRate,V=K.averageBitrate}catch{}return{id:j,codec:A.codec,language:A.languageCode,name:A.name,width:A.codedWidth,height:A.codedHeight,frameRate:Q,bitrate:V,rotation:A.rotation,selected:!1,decodable:await A.canDecode()}}));let $=await this.input.getAudioTracks();if(this.audioTrackInfos=await Promise.all($.map(async(A)=>{let j=`audio-${A.id}`;this.audioTracks.set(j,A);let Q=0;try{Q=(await A.computePacketStats(100)).averageBitrate}catch{}return{id:j,codec:A.codec,language:A.languageCode,name:A.name,channels:A.numberOfChannels,sampleRate:A.sampleRate,bitrate:Q,selected:!1,decodable:await A.canDecode()}})),this.videoTrackInfos.length>0){let A=this.videoTrackInfos.find((j)=>j.decodable);if(A)this.selectVideoTrack(A.id)}if(this.audioTrackInfos.length>0){let A=this.audioTrackInfos.find((j)=>j.decodable);if(A)this.selectAudioTrack(A.id)}}getVideoTracks(){return[...this.videoTrackInfos]}getAudioTracks(){return[...this.audioTrackInfos]}getSubtitleTracks(){return[...this.subtitleTrackInfos]}getSelectedVideoTrack(){if(!this.selectedVideoTrack)return null;return this.videoTracks.get(this.selectedVideoTrack)??null}getSelectedAudioTrack(){if(!this.selectedAudioTrack)return null;return this.audioTracks.get(this.selectedAudioTrack)??null}getSelectedVideoTrackInfo(){if(!this.selectedVideoTrack)return null;return this.videoTrackInfos.find((O)=>O.id===this.selectedVideoTrack)??null}getSelectedAudioTrackInfo(){if(!this.selectedAudioTrack)return null;return this.audioTrackInfos.find((O)=>O.id===this.selectedAudioTrack)??null}getSelectedSubtitleTrackInfo(){if(!this.selectedSubtitleTrack)return null;return this.subtitleTrackInfos.find((O)=>O.id===this.selectedSubtitleTrack)??null}selectVideoTrack(O){if(O===this.selectedVideoTrack)return!0;if(O&&!this.videoTracks.has(O))return!1;let $=this.selectedVideoTrack;if(this.videoTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedVideoTrack=O,this.onTrackChange)this.onTrackChange({type:"video",previousTrackId:$,newTrackId:O});return!0}selectAudioTrack(O){if(O===this.selectedAudioTrack)return!0;if(O&&!this.audioTracks.has(O))return!1;let $=this.selectedAudioTrack;if(this.audioTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedAudioTrack=O,this.onTrackChange)this.onTrackChange({type:"audio",previousTrackId:$,newTrackId:O});return!0}selectSubtitleTrack(O){if(O===this.selectedSubtitleTrack)return!0;if(O&&!this.subtitleTrackResolvers.has(O))return!1;let $=this.selectedSubtitleTrack;if(this.subtitleTrackInfos.forEach((A)=>{A.selected=A.id===O}),this.selectedSubtitleTrack=O,this.onTrackChange)this.onTrackChange({type:"subtitle",previousTrackId:$,newTrackId:O});return!0}registerSubtitleTracks(O,$){this.subtitleProviders.set(O,$),this.rebuildSubtitleTracks()}unregisterSubtitleTracks(O){if(!this.subtitleProviders.delete(O))return;this.rebuildSubtitleTracks()}async getSubtitleTrackResource(O){if(!O)return null;let $=this.subtitleTrackResolvers.get(O);if(!$)return null;return $()}rebuildSubtitleTracks(){let O=this.selectedSubtitleTrack;this.subtitleTrackInfos=[],this.subtitleTrackResolvers.clear();for(let A of this.subtitleProviders.values())for(let j of A){let Q={...j.info,selected:!1};this.subtitleTrackInfos.push(Q),this.subtitleTrackResolvers.set(Q.id,j.resolver)}let $=O;if(!$||!this.subtitleTrackResolvers.has($))$=this.subtitleTrackInfos[0]?.id??null;if(this.selectedSubtitleTrack=$,this.subtitleTrackInfos.forEach((A)=>{A.selected=A.id===this.selectedSubtitleTrack}),O!==this.selectedSubtitleTrack&&this.onTrackChange)this.onTrackChange({type:"subtitle",previousTrackId:O,newTrackId:this.selectedSubtitleTrack})}setTrackChangeListener(O){this.onTrackChange=O}getState(){return{videoTracks:this.getVideoTracks(),audioTracks:this.getAudioTracks(),subtitleTracks:this.getSubtitleTracks(),selectedVideoTrack:this.selectedVideoTrack,selectedAudioTrack:this.selectedAudioTrack,selectedSubtitleTrack:this.selectedSubtitleTrack}}getPrimaryVideoTrack(){if(this.videoTracks.size===0)return null;return this.selectedVideoTrack?this.videoTracks.get(this.selectedVideoTrack)??null:this.videoTracks.values().next().value??null}getPrimaryAudioTrack(){if(this.audioTracks.size===0)return null;return this.selectedAudioTrack?this.audioTracks.get(this.selectedAudioTrack)??null:this.audioTracks.values().next().value??null}hasVideo(){return this.videoTrackInfos.length>0}hasAudio(){return this.audioTrackInfos.length>0}hasSubtitles(){return this.subtitleTrackInfos.length>0}dispose(){this.videoTracks.clear(),this.audioTracks.clear(),this.videoTrackInfos=[],this.audioTrackInfos=[],this.subtitleTrackInfos=[],this.subtitleProviders.clear(),this.subtitleTrackResolvers.clear(),this.selectedVideoTrack=null,this.selectedAudioTrack=null,this.selectedSubtitleTrack=null,this.input=null,this.onTrackChange=void 0}async replaceAudioTrackByInputId(O,$){let A=null;for(let[Q,V]of this.audioTracks.entries())if(V.id===O){A=Q;break}if(!A)return;this.audioTracks.set(A,$);let j=this.audioTrackInfos.findIndex((Q)=>Q.id===A);if(j!==-1){let Q=0;try{Q=(await $.computePacketStats(100)).averageBitrate}catch{}this.audioTrackInfos[j]={...this.audioTrackInfos[j],codec:$.codec,channels:$.numberOfChannels,sampleRate:$.sampleRate,bitrate:Q,decodable:await $.canDecode()}}}async replaceVideoTrackByInputId(O,$){let A=null;for(let[Q,V]of this.videoTracks.entries())if(V.id===O){A=Q;break}if(!A)return;this.videoTracks.set(A,$);let j=this.videoTrackInfos.findIndex((Q)=>Q.id===A);if(j!==-1){let Q=0,V=0;try{let J=await $.computePacketStats(100);Q=J.averagePacketRate,V=J.averageBitrate}catch{}this.videoTrackInfos[j]={...this.videoTrackInfos[j],codec:$.codec,width:$.codedWidth,height:$.codedHeight,rotation:$.rotation,frameRate:Q,bitrate:V,decodable:await $.canDecode()}}}}class d{emitter;store;state;sourceManager;playbackController;trackManager;playlistManager;pluginManager;options;disposed=!1;getCurrentInput=()=>this.sourceManager.getCurrentSource()?.input??null;trackSwitcher;core;constructor(O={}){this.options={volume:1,muted:!1,playbackRate:1,autoplay:!1,preload:"metadata",...O},this.emitter=new y({maxListeners:100}),this.store=new c,this.state=new OO(this.store),this.sourceManager=new u({maxCacheSize:O.maxCacheSize,crossOrigin:O.crossOrigin}),this.playbackController=new g({canvas:O.renderTarget,audioContext:O.audioContext,volume:this.options.volume,muted:this.options.muted,playbackRate:this.options.playbackRate,rendererType:this.options.renderer}),this.trackManager=new o,this.playlistManager=new jO(this.store,this.emitter,async($,A)=>{await this.core.load($.mediaSource,{startTime:$.savedPosition??0,autoplay:A,playlistItemId:$.id})},this.sourceManager),this.trackSwitcher=new AO({sourceManager:this.sourceManager,trackManager:this.trackManager,playbackController:this.playbackController,emit:this.emit.bind(this),store:this.store,getCurrentInput:this.getCurrentInput}),this.pluginManager=new QO(this),this.core=new e({state:this.state,sourceManager:this.sourceManager,trackManager:this.trackManager,playbackController:this.playbackController,trackSwitcher:this.trackSwitcher,emit:this.emit.bind(this),pluginManager:this.pluginManager}),this.playbackController.setPluginManager(this.pluginManager),this.store.setPluginManager(this.pluginManager),this.setupInternalListeners(),this.state.applyInitial(this.options.volume??1,this.options.muted??!1,this.options.playbackRate??1),this.state.updateRendererType(this.options.renderer||"webgpu")}setupInternalListeners(){this.playbackController.setTimeUpdateCallback((O)=>{this.state.updateTime(O),this.emit("timeupdate",{currentTime:O})}),this.playbackController.setEndedCallback(()=>{this.state.updateEndedState(!0),this.emit("ended",void 0);let O=this.getState();if(O.playlist.length>0&&O.currentPlaylistIndex!==null){let{playlistMode:$,currentPlaylistIndex:A}=O;if($==="repeat-one"){let j=A;queueMicrotask(async()=>{try{await this.seek(0),await this.play()}catch(Q){this.emitter.emit("playlistitemerror",{index:j,error:Q})}})}else if($==="repeat"){let j=A<O.playlist.length-1?A+1:0;queueMicrotask(async()=>{try{await this.playlistManager.next()}catch(Q){this.emitter.emit("playlistitemerror",{index:j,error:Q})}})}else if($==="sequential"&&A<O.playlist.length-1){let j=A+1;queueMicrotask(async()=>{try{await this.playlistManager.next()}catch(Q){this.emitter.emit("playlistitemerror",{index:j,error:Q})}})}}}),this.trackManager.setTrackChangeListener((O)=>{this.state.updateSelectedTracks(O.type,O.newTrackId),this.emit("trackchange",{type:O.type,trackId:O.newTrackId})}),this.playbackController.setWaitingCallback(()=>{this.state.updateWaitingState(!0),this.emit("waiting",void 0)}),this.playbackController.setPlayingCallback(()=>{if(this.getState().waiting)this.state.updateWaitingState(!1),this.emit("playing",void 0)}),this.playbackController.setRendererChangeCallback((O)=>{this.state.updateRendererType(O),this.emit("rendererchange",O)}),this.playbackController.setRendererFallbackCallback((O,$)=>{this.emit("rendererfallback",{from:O,to:$})}),this.playbackController.setRotationChangeCallback((O,$)=>{this.store.updateRotation(O,$),this.emit("rotationchange",{rotation:O,displaySize:$})}),this.state.subscribe((O)=>{this.emit("statechange",O)})}async load(O,$={}){this.checkDisposed();let A=this.getState();if(A.playlist.length===0||$.replacePlaylist){await this.playlistManager.loadPlaylist([{mediaSource:O}],{autoplay:$.autoplay??this.options.autoplay,startTime:$.startTime});return}else if(A.currentPlaylistIndex!==null&&A.playlist.length>0){let j=A.currentPlaylistIndex,V={...A.playlist[j],mediaSource:O,savedPosition:0,duration:null},J=[...A.playlist];J[j]=V,this.store.updatePlaylist(J,j),this.emitter.emit("playlistchange",{playlist:J}),await this.core.load(O,{startTime:$.startTime??0,autoplay:$.autoplay??this.options.autoplay});return}await this.core.load(O,{autoplay:$.autoplay??this.options.autoplay,startTime:$.startTime})}async play(){return this.checkDisposed(),this.core.play()}pause(){this.checkDisposed(),this.core.pause()}async seek(O,$={}){return this.checkDisposed(),this.core.seek(O)}async stop(){return this.checkDisposed(),this.core.stop()}get currentTime(){return this.playbackController.getCurrentTime()}set currentTime(O){this.seek(O)}get duration(){return this.state.getState().duration}get volume(){return this.playbackController.getVolume()}set volume(O){this.checkDisposed();let $=Math.max(0,Math.min(1,O));this.playbackController.setVolume($),this.state.updateVolume($,this.muted),this.emit("volumechange",{volume:$,muted:this.muted})}get muted(){return this.playbackController.isMuted()}set muted(O){this.checkDisposed(),this.playbackController.setMuted(O),this.state.updateVolume(this.volume,O),this.emit("volumechange",{volume:this.volume,muted:O})}get playbackRate(){return this.playbackController.getPlaybackRate()}set playbackRate(O){this.checkDisposed();let $=Math.max(0.25,Math.min(4,O));this.playbackController.setPlaybackRate($),this.state.updatePlaybackRate($),this.emit("ratechange",{playbackRate:$})}get paused(){return!this.playbackController.isPlaying()}get ended(){return this.state.getState().ended}get seeking(){return this.state.getState().seeking}get waiting(){return this.state.getState().waiting}get rotation(){return this.playbackController.getRotation()}set rotation(O){this.checkDisposed(),this.playbackController.setRotation(O)}get displaySize(){return this.playbackController.getDisplaySize()}getVideoTracks(){return this.trackManager.getVideoTracks()}getAudioTracks(){return this.trackManager.getAudioTracks()}getSubtitleTracks(){return this.trackManager.getSubtitleTracks()}async selectVideoTrack(O){this.checkDisposed(),await this.trackSwitcher.selectVideoTrack(this.trackManager,O)}async selectAudioTrack(O){this.checkDisposed(),await this.trackSwitcher.selectAudioTrack(this.trackManager,O)}selectSubtitleTrack(O){if(this.checkDisposed(),!this.trackManager.selectSubtitleTrack(O))throw Error(`Invalid subtitle track ID: ${O}`)}registerSubtitleTracks(O,$){this.trackManager.registerSubtitleTracks(O,$),this.state.updateTracks(void 0,void 0,this.trackManager.getSubtitleTracks());let A=this.state.getState().mediaInfo;if(A)this.state.updateMediaInfo({...A,hasSubtitles:this.trackManager.hasSubtitles()})}unregisterSubtitleTracks(O){this.trackManager.unregisterSubtitleTracks(O),this.state.updateTracks(void 0,void 0,this.trackManager.getSubtitleTracks());let $=this.state.getState().mediaInfo;if($)this.state.updateMediaInfo({...$,hasSubtitles:this.trackManager.hasSubtitles()})}async getSubtitleTrackResource(O){return this.trackManager.getSubtitleTrackResource(O)}async screenshot(O={}){return this.checkDisposed(),this.playbackController.screenshot(O)}async setRenderTarget(O){this.checkDisposed(),await this.playbackController.setCanvas(O)}getRenderTarget(){return this.playbackController.getCanvas()}refreshOverlays(){this.playbackController.refreshOverlays()}async loadPlaylist(O,$){this.checkDisposed(),await this.playlistManager.loadPlaylist(O,$)}addToPlaylist(O,$){this.checkDisposed(),this.playlistManager.addToPlaylist(O,$)}async removeFromPlaylist(O){this.checkDisposed(),await this.playlistManager.removeFromPlaylist(O)}clearPlaylist(){this.checkDisposed(),this.playlistManager.clearPlaylist()}async next(){this.checkDisposed(),await this.playlistManager.next()}async prev(){this.checkDisposed(),await this.playlistManager.prev()}async jumpTo(O){this.checkDisposed(),await this.playlistManager.jumpTo(O)}get playlist(){return this.playlistManager.playlist}get playlistIndex(){return this.playlistManager.currentIndex}get nowPlaying(){return this.playlistManager.currentItem}get playlistMode(){return this.playlistManager.mode}set playlistMode(O){this.checkDisposed(),this.playlistManager.setMode(O)}getRendererType(){return this.playbackController.getRendererType()}async switchRenderer(O){this.checkDisposed(),await this.playbackController.switchRenderer(O)}updateCanvasDimensions(){this.checkDisposed(),this.playbackController.updateCanvasDimensions()}static getSupportedRenderers(){return W.getSupportedRenderers()}getState(){return this.state.getState()}subscribe(O){return{unsubscribe:this.state.subscribe(O)}}on(O,$){return this.emitter.on(O,$)}once(O,$){return this.emitter.once(O,$)}off(O,$){this.emitter.off(O,$)}async use(O){if(this.checkDisposed(),await this.pluginManager.install(O),O.hooks?.audio)this.playbackController.rebuildAudioGraph()}async unuse(O){this.checkDisposed(),await this.pluginManager.uninstall(O),this.playbackController.rebuildAudioGraph()}emit(O,$){let A=this.pluginManager.executeBeforeEvent(O,$);if(A?.cancel)return;let j=A?.data??$;this.emitter.emit(O,j),this.pluginManager.executeAfterEvent(O,j)}checkDisposed(){if(this.disposed)throw Error("Player has been disposed")}dispose(){if(this.disposed)return;this.disposed=!0,this.pluginManager.dispose(),this.playbackController.dispose(),this.trackManager.dispose(),this.playlistManager?.dispose(),this.sourceManager.dispose(),this.state.reset(),this.emitter.removeAllListeners()}destroy(){this.dispose(),this.playbackController.destroy()}}var dO={fromUrl(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromFile(O,$={}){return{mediaSource:O,title:$.title||O.name,poster:$.poster}},fromBlob(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromBuffer(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromUint8Array(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}},fromStream(O,$={}){return{mediaSource:O,title:$.title,poster:$.poster}}};var YO;((U)=>{U.MEDIA_NOT_SUPPORTED="MEDIA_NOT_SUPPORTED";U.MEDIA_LOAD_FAILED="MEDIA_LOAD_FAILED";U.DECODE_ERROR="DECODE_ERROR";U.NETWORK_ERROR="NETWORK_ERROR";U.PERMISSION_DENIED="PERMISSION_DENIED";U.PLAYBACK_ERROR="PLAYBACK_ERROR";U.TRACK_NOT_FOUND="TRACK_NOT_FOUND";U.INVALID_STATE="INVALID_STATE";U.UNKNOWN_ERROR="UNKNOWN_ERROR"})(YO||={});class _ extends Error{code;details;constructor(O,$,A){super($);this.name="MediaFoxError",this.code=O,this.details=A}static mediaNotSupported(O="Media format not supported",$){return new _("MEDIA_NOT_SUPPORTED",O,$)}static mediaLoadFailed(O="Failed to load media",$){return new _("MEDIA_LOAD_FAILED",O,$)}static decodeError(O="Failed to decode media",$){return new _("DECODE_ERROR",O,$)}static networkError(O="Network error occurred",$){return new _("NETWORK_ERROR",O,$)}static permissionDenied(O="Permission denied",$){return new _("PERMISSION_DENIED",O,$)}static playbackError(O="Playback error occurred",$){return new _("PLAYBACK_ERROR",O,$)}static trackNotFound(O="Track not found",$){return new _("TRACK_NOT_FOUND",O,$)}static invalidState(O="Invalid player state",$){return new _("INVALID_STATE",O,$)}static unknownError(O="Unknown error occurred",$){return new _("UNKNOWN_ERROR",O,$)}}function nO(O,$){if(O instanceof _)return O;if(O instanceof Error)return new _("UNKNOWN_ERROR",`${$}: ${O.message}`,{originalError:O});return new _("UNKNOWN_ERROR",`${$}: ${String(O)}`,{originalError:O})}function sO(O,$=!1){let A=Math.abs(O),j=Math.floor(A/3600),Q=Math.floor(A%3600/60),V=Math.floor(A%60),J=Math.floor(A%1*1000),K="";if(O<0)K="-";if(j>0)K+=`${j}:${Q.toString().padStart(2,"0")}:${V.toString().padStart(2,"0")}`;else K+=`${Q}:${V.toString().padStart(2,"0")}`;if($)K+=`.${J.toString().padStart(3,"0")}`;return K}function iO(O){let $=O.trim().split(":").map(Number);if($.some(Number.isNaN))throw Error("Invalid time string");let A=0;if($.length===3)A=$[0]*3600+$[1]*60+$[2];else if($.length===2)A=$[0]*60+$[1];else if($.length===1)A=$[0];else throw Error("Invalid time format");return A}function tO(O,$){return Math.floor(O*$)}function rO(O,$){return O/$}function aO(O,$,A){return Math.max($,Math.min(A,O))}function eO(O,$){return O.start<$.end&&$.start<O.end}function O$(O){if(O.length===0)return[];let $=[...O].sort((j,Q)=>j.start-Q.start),A=[$[0]];for(let j=1;j<$.length;j++){let Q=A[A.length-1],V=$[j];if(V.start<=Q.end)Q.end=Math.max(Q.end,V.end);else A.push(V)}return A}function $$(O){return O.reduce(($,A)=>$+(A.end-A.start),0)}function A$(O,$){for(let A of O)if($>=A.start&&$<A.end)return A;return null}var DA="0.1.0",xA=d;export{nO as wrapError,$$ as totalBufferedDuration,tO as timeToFrame,eO as timeRangesOverlap,iO as parseTime,O$ as mergeTimeRanges,rO as frameToTime,sO as formatTime,A$ as findBufferedRange,xA as default,aO as clamp,v as VideoRenderer,DA as VERSION,o as TrackManager,c as Store,x as SourcePool,u as SourceManager,dO as Source,W as RendererFactory,g as PlaybackController,_ as MediaFoxError,d as MediaFox,y as EventEmitter,YO as ErrorCode,i as Compositor,p as AudioManager};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mediafox/core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"description": "Framework-agnostic media player library powered by MediaBunny",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"dev": "bun run --watch src/index.ts",
|
|
20
20
|
"build": "bun run build:js && bun run build:types",
|
|
21
|
-
"build:js": "bun build src/index.ts --outdir=dist --target=browser --format=esm --minify --external mediabunny",
|
|
21
|
+
"build:js": "bun build src/index.ts --outdir=dist --target=browser --format=esm --minify --external mediabunny && bun build src/compositor/compositor-worker.ts --outdir=dist --target=browser --format=esm --minify --external mediabunny",
|
|
22
22
|
"build:types": "tsc --emitDeclarationOnly",
|
|
23
23
|
"test": "bun test",
|
|
24
24
|
"lint": "biome lint ./src",
|