@meframe/core 0.3.7 → 0.3.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"BaseEncoder.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/BaseEncoder.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,yBAAyB,CAAC;CACrC;AAED,8BAAsB,WAAW,CAC/B,QAAQ,SAAS,YAAY,GAAG,YAAY,EAC5C,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,MAAM,SAAS,UAAU,GAAG,SAAS,EACrC,MAAM,SAAS,iBAAiB,GAAG,iBAAiB,EACpD,SAAS,SAAS,yBAAyB,GAAG,yBAAyB;IAEvE,SAAS,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,UAAU,EAAE,gCAAgC,CAAC,YAAY,CAAC,GAAG,IAAI,CAAQ;gBAEvE,MAAM,EAAE,OAAO;IAI3B,SAAS,IAAI,OAAO;IAIpB,SAAS,KAAK,aAAa,IAAI,OAAO,CAErC;IAED,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO;IAW/D,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAiBlD,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO;IAIjD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IAchE,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAYhD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IACtF,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,QAAQ;IAC7D,SAAS,CAAC,QAAQ,CAAC,cAAc,IAAI,MAAM;IAG3C,SAAS,CAAC,OAAO,IAAI,IAAI;IAKzB,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAClD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IAEzD;;;OAGG;IACH,YAAY,IAAI,eAAe,CAAC,MAAM,EAAE,YAAY,CAAC;IAkDrD,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CACrC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC5C,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CACtC"}
1
+ {"version":3,"file":"BaseEncoder.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/BaseEncoder.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,yBAAyB,CAAC;CACrC;AAED,8BAAsB,WAAW,CAC/B,QAAQ,SAAS,YAAY,GAAG,YAAY,EAC5C,OAAO,SAAS,kBAAkB,GAAG,kBAAkB,EACvD,MAAM,SAAS,UAAU,GAAG,SAAS,EACrC,MAAM,SAAS,iBAAiB,GAAG,iBAAiB,EACpD,SAAS,SAAS,yBAAyB,GAAG,yBAAyB;IAEvE,SAAS,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,UAAU,EAAE,gCAAgC,CAAC,YAAY,CAAC,GAAG,IAAI,CAAQ;gBAEvE,MAAM,EAAE,OAAO;IAI3B,SAAS,IAAI,OAAO;IAIpB,SAAS,KAAK,aAAa,IAAI,OAAO,CAErC;IAED,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO;IAW/D,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAiBlD,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO;IAIjD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IAehE,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAiBhD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IACtF,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,QAAQ;IAC7D,SAAS,CAAC,QAAQ,CAAC,cAAc,IAAI,MAAM;IAG3C,SAAS,CAAC,OAAO,IAAI,IAAI;IAKzB,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAClD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IAEzD;;;OAGG;IACH,YAAY,IAAI,eAAe,CAAC,MAAM,EAAE,YAAY,CAAC;IAgErD,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CACrC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC5C,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CACtC"}
@@ -39,11 +39,14 @@ class BaseEncoder {
39
39
  return JSON.stringify(a) === JSON.stringify(b);
40
40
  }
41
41
  async initialize() {
42
+ console.info("Encoder is initializing...");
42
43
  if (this.encoder?.state === "configured") {
44
+ console.warn("Encoder is already initialized, skipping initialization");
43
45
  return;
44
46
  }
45
47
  const isSupported = await this.isConfigSupported(this.config);
46
48
  if (!isSupported.supported) {
49
+ console.warn("Codec not supported:", JSON.stringify(this.config));
47
50
  throw new Error(`Codec not supported: ${JSON.stringify(this.config)}`);
48
51
  }
49
52
  this.encoder = this.createEncoder({
@@ -51,8 +54,10 @@ class BaseEncoder {
51
54
  error: this.handleError.bind(this)
52
55
  });
53
56
  this.encoder.configure(this.config);
57
+ console.info("Encoder is initialized");
54
58
  }
55
59
  async reconfigure(config) {
60
+ console.info("Encoder is reconfiguring...");
56
61
  if (!config || Object.keys(config).length === 0) {
57
62
  return;
58
63
  }
@@ -74,6 +79,7 @@ class BaseEncoder {
74
79
  }
75
80
  this.config = nextConfig;
76
81
  this.encoder.configure(this.config);
82
+ console.info("Encoder is reconfigured");
77
83
  }
78
84
  async flush() {
79
85
  if (!this.encoder) {
@@ -82,13 +88,17 @@ class BaseEncoder {
82
88
  await this.encoder.flush();
83
89
  }
84
90
  async reset() {
91
+ console.info("Encoder is resetting...");
85
92
  if (!this.encoder) {
93
+ console.warn("Encoder is not initialized, skipping reset");
86
94
  return;
87
95
  }
88
96
  this.encoder.reset();
89
97
  this.onReset();
98
+ console.info("Encoder is resetted");
90
99
  }
91
100
  async close() {
101
+ console.info("Encoder is closing...");
92
102
  if (!this.encoder) {
93
103
  return;
94
104
  }
@@ -97,6 +107,7 @@ class BaseEncoder {
97
107
  }
98
108
  this.encoder.close();
99
109
  this.encoder = void 0;
110
+ console.info("Encoder is closed");
100
111
  }
101
112
  get isReady() {
102
113
  return this.encoder?.state === "configured";
@@ -109,6 +120,7 @@ class BaseEncoder {
109
120
  try {
110
121
  this.controller.enqueue({ chunk, metadata });
111
122
  } catch (error) {
123
+ console.error("Encoder output error:", error);
112
124
  if (!(error instanceof TypeError && error.message.includes("closed"))) {
113
125
  throw error;
114
126
  }
@@ -116,6 +128,10 @@ class BaseEncoder {
116
128
  }
117
129
  }
118
130
  handleError(error) {
131
+ if (error.message.includes("reclaimed")) {
132
+ console.warn("Encoder reclaimed by browser due to inactivity, skipping error handling");
133
+ return;
134
+ }
119
135
  console.error(`[${this.getEncoderType()}Encoder] Encode error:`, {
120
136
  name: error.name,
121
137
  message: error.message,
@@ -137,12 +153,14 @@ class BaseEncoder {
137
153
  {
138
154
  start: async (controller) => {
139
155
  this.controller = controller;
156
+ },
157
+ transform: async (input) => {
140
158
  if (!this.isReady) {
159
+ console.warn("Encoder is not ready, initializing...");
141
160
  await this.initialize();
142
161
  }
143
- },
144
- transform: async (input) => {
145
162
  if (!this.encoder || this.encoder.state !== "configured") {
163
+ console.error("Encoder not configured, throwing error");
146
164
  throw new Error("Encoder not configured");
147
165
  }
148
166
  if (this.encoder.encodeQueueSize >= this.encodeQueueThreshold) {
@@ -158,7 +176,20 @@ class BaseEncoder {
158
176
  });
159
177
  }
160
178
  const frame = input.frame || input;
161
- this.encode(frame);
179
+ try {
180
+ this.encode(frame);
181
+ } catch (err) {
182
+ const msg = err instanceof Error ? err.message : String(err);
183
+ console.error("Encoder error:", msg);
184
+ if (err instanceof DOMException && msg.includes("reclaimed")) {
185
+ console.warn("Codec reclaimed due to inactivity, reset encoder...");
186
+ this.encoder = void 0;
187
+ await this.initialize();
188
+ this.encode(frame);
189
+ } else {
190
+ throw err;
191
+ }
192
+ }
162
193
  },
163
194
  flush: async () => {
164
195
  await this.flush();
@@ -1 +1 @@
1
- {"version":3,"file":"BaseEncoder.js","sources":["../../../src/stages/encode/BaseEncoder.ts"],"sourcesContent":["// Base encoder implementation\n\n/**\n * Base encoder class for both video and audio encoding\n * Handles common WebCodecs encoder operations\n */\n\nexport interface EncoderChunk {\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n}\n\nexport abstract class BaseEncoder<\n TEncoder extends VideoEncoder | AudioEncoder,\n TConfig extends VideoEncoderConfig | AudioEncoderConfig,\n TInput extends VideoFrame | AudioData,\n TChunk extends EncodedVideoChunk | EncodedAudioChunk,\n TMetadata extends EncodedVideoChunkMetadata | EncodedAudioChunkMetadata,\n> {\n protected encoder?: TEncoder;\n protected config: TConfig;\n protected controller: TransformStreamDefaultController<EncoderChunk> | null = null;\n\n constructor(config: TConfig) {\n this.config = config;\n }\n\n getConfig(): TConfig {\n return { ...this.config };\n }\n\n protected get currentConfig(): TConfig {\n return this.config;\n }\n\n protected shouldReconfigure(partial: Partial<TConfig>): boolean {\n const next = { ...this.config, ...partial } as TConfig;\n const keys = Object.keys(partial ?? {}) as Array<keyof TConfig>;\n for (const key of keys) {\n if (partial[key] !== undefined && next[key] !== this.config[key]) {\n return true;\n }\n }\n return false;\n }\n\n protected hasConfigChanged(next: TConfig): boolean {\n const currentEntries = Object.entries(this.config) as Array<[keyof TConfig, any]>;\n for (const [key, value] of currentEntries) {\n if (next[key] !== value) {\n return true;\n }\n }\n\n for (const key of Object.keys(next) as Array<keyof TConfig>) {\n if (this.config[key] !== next[key]) {\n return true;\n }\n }\n\n return false;\n }\n\n protected configsEqual(a: TConfig, b: TConfig): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n }\n\n async initialize(): Promise<void> {\n if (this.encoder?.state === 'configured') {\n return;\n }\n\n const isSupported = await this.isConfigSupported(this.config);\n\n if (!isSupported.supported) {\n throw new Error(`Codec not supported: ${JSON.stringify(this.config)}`);\n }\n\n this.encoder = this.createEncoder({\n output: this.handleOutput.bind(this),\n error: this.handleError.bind(this),\n });\n\n (this.encoder as any).configure(this.config);\n }\n\n async reconfigure(config: Partial<TConfig>): Promise<void> {\n if (!config || Object.keys(config).length === 0) {\n return;\n }\n\n const nextConfig = { ...this.config, ...config } as TConfig;\n\n if (this.configsEqual(this.config, nextConfig)) {\n return;\n }\n\n if (!this.encoder) {\n this.config = nextConfig;\n await this.initialize();\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n const isSupported = await this.isConfigSupported(nextConfig);\n if (!isSupported.supported) {\n throw new Error(`New configuration not supported: ${nextConfig.codec}`);\n }\n\n this.config = nextConfig;\n (this.encoder as any).configure(this.config);\n }\n\n async flush(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n await this.encoder.flush();\n }\n\n async reset(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n this.encoder.reset();\n this.onReset();\n }\n\n async close(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n this.encoder.close();\n this.encoder = undefined;\n }\n\n get isReady(): boolean {\n return this.encoder?.state === 'configured';\n }\n\n get queueSize(): number {\n return this.encoder?.encodeQueueSize ?? 0;\n }\n\n protected handleOutput(chunk: TChunk, metadata: TMetadata): void {\n // Only enqueue if controller exists and stream is not closed\n if (this.controller) {\n try {\n this.controller.enqueue({ chunk, metadata });\n } catch (error) {\n // Stream may be closed during flush, ignore enqueue errors\n if (!(error instanceof TypeError && error.message.includes('closed'))) {\n throw error;\n }\n }\n }\n }\n\n protected handleError(error: DOMException): void {\n console.error(`[${this.getEncoderType()}Encoder] Encode error:`, {\n name: error.name,\n message: error.message,\n encoderState: this.encoder?.state,\n queueSize: this.queueSize,\n platform: typeof navigator !== 'undefined' ? navigator.platform : 'unknown',\n });\n this.controller?.error(error);\n }\n\n // Abstract methods to be implemented by subclasses\n protected abstract isConfigSupported(config: TConfig): Promise<{ supported: boolean }>;\n protected abstract createEncoder(init: EncoderInit): TEncoder;\n protected abstract getEncoderType(): string;\n\n // Hook for subclasses to handle reset\n protected onReset(): void {\n // Override in subclasses if needed\n }\n\n // Abstract properties for backpressure configuration\n protected abstract readonly highWaterMark: number;\n protected abstract readonly encodeQueueThreshold: number;\n\n /**\n * Create transform stream for encoding\n * Implements common stream logic with backpressure handling\n */\n createStream(): TransformStream<TInput, EncoderChunk> {\n return new TransformStream<TInput, EncoderChunk>(\n {\n start: async (controller) => {\n this.controller = controller;\n\n // Initialize encoder if not already initialized\n if (!this.isReady) {\n await this.initialize();\n }\n },\n\n transform: async (input) => {\n if (!this.encoder || this.encoder.state !== 'configured') {\n throw new Error('Encoder not configured');\n }\n\n // Check encoder queue pressure\n if (this.encoder.encodeQueueSize >= this.encodeQueueThreshold) {\n // Wait for queue to drain\n await new Promise<void>((resolve) => {\n const check = () => {\n if (!this.encoder || this.encoder.encodeQueueSize < this.encodeQueueThreshold - 1) {\n resolve();\n } else {\n setTimeout(check, 10);\n }\n };\n check();\n });\n }\n\n // Encode the input\n const frame = (input as any).frame || input;\n this.encode(frame);\n },\n\n flush: async () => {\n await this.flush();\n },\n },\n // Queuing strategy with backpressure configuration\n {\n highWaterMark: this.highWaterMark,\n size: () => 1, // Count-based\n }\n );\n }\n\n // Abstract method for encoding\n abstract encode(input: TInput): void;\n}\n\ninterface EncoderInit {\n output: (chunk: any, metadata: any) => void;\n error: (error: DOMException) => void;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseEncoder.js","sources":["../../../src/stages/encode/BaseEncoder.ts"],"sourcesContent":["// Base encoder implementation\n\n/**\n * Base encoder class for both video and audio encoding\n * Handles common WebCodecs encoder operations\n */\n\nexport interface EncoderChunk {\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n}\n\nexport abstract class BaseEncoder<\n TEncoder extends VideoEncoder | AudioEncoder,\n TConfig extends VideoEncoderConfig | AudioEncoderConfig,\n TInput extends VideoFrame | AudioData,\n TChunk extends EncodedVideoChunk | EncodedAudioChunk,\n TMetadata extends EncodedVideoChunkMetadata | EncodedAudioChunkMetadata,\n> {\n protected encoder?: TEncoder;\n protected config: TConfig;\n protected controller: TransformStreamDefaultController<EncoderChunk> | null = null;\n\n constructor(config: TConfig) {\n this.config = config;\n }\n\n getConfig(): TConfig {\n return { ...this.config };\n }\n\n protected get currentConfig(): TConfig {\n return this.config;\n }\n\n protected shouldReconfigure(partial: Partial<TConfig>): boolean {\n const next = { ...this.config, ...partial } as TConfig;\n const keys = Object.keys(partial ?? {}) as Array<keyof TConfig>;\n for (const key of keys) {\n if (partial[key] !== undefined && next[key] !== this.config[key]) {\n return true;\n }\n }\n return false;\n }\n\n protected hasConfigChanged(next: TConfig): boolean {\n const currentEntries = Object.entries(this.config) as Array<[keyof TConfig, any]>;\n for (const [key, value] of currentEntries) {\n if (next[key] !== value) {\n return true;\n }\n }\n\n for (const key of Object.keys(next) as Array<keyof TConfig>) {\n if (this.config[key] !== next[key]) {\n return true;\n }\n }\n\n return false;\n }\n\n protected configsEqual(a: TConfig, b: TConfig): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n }\n\n async initialize(): Promise<void> {\n console.info('Encoder is initializing...');\n if (this.encoder?.state === 'configured') {\n console.warn('Encoder is already initialized, skipping initialization');\n return;\n }\n\n const isSupported = await this.isConfigSupported(this.config);\n\n if (!isSupported.supported) {\n console.warn('Codec not supported:', JSON.stringify(this.config));\n throw new Error(`Codec not supported: ${JSON.stringify(this.config)}`);\n }\n\n this.encoder = this.createEncoder({\n output: this.handleOutput.bind(this),\n error: this.handleError.bind(this),\n });\n\n (this.encoder as any).configure(this.config);\n console.info('Encoder is initialized');\n }\n\n async reconfigure(config: Partial<TConfig>): Promise<void> {\n console.info('Encoder is reconfiguring...');\n if (!config || Object.keys(config).length === 0) {\n return;\n }\n\n const nextConfig = { ...this.config, ...config } as TConfig;\n\n if (this.configsEqual(this.config, nextConfig)) {\n return;\n }\n\n if (!this.encoder) {\n this.config = nextConfig;\n await this.initialize();\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n const isSupported = await this.isConfigSupported(nextConfig);\n if (!isSupported.supported) {\n throw new Error(`New configuration not supported: ${nextConfig.codec}`);\n }\n\n this.config = nextConfig;\n (this.encoder as any).configure(this.config);\n console.info('Encoder is reconfigured');\n }\n\n async flush(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n await this.encoder.flush();\n }\n\n async reset(): Promise<void> {\n console.info('Encoder is resetting...');\n if (!this.encoder) {\n console.warn('Encoder is not initialized, skipping reset');\n return;\n }\n\n this.encoder.reset();\n this.onReset();\n console.info('Encoder is resetted');\n }\n\n async close(): Promise<void> {\n console.info('Encoder is closing...');\n if (!this.encoder) {\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n this.encoder.close();\n this.encoder = undefined;\n console.info('Encoder is closed');\n }\n\n get isReady(): boolean {\n return this.encoder?.state === 'configured';\n }\n\n get queueSize(): number {\n return this.encoder?.encodeQueueSize ?? 0;\n }\n\n protected handleOutput(chunk: TChunk, metadata: TMetadata): void {\n // Only enqueue if controller exists and stream is not closed\n if (this.controller) {\n try {\n this.controller.enqueue({ chunk, metadata });\n } catch (error) {\n console.error('Encoder output error:', error);\n // Stream may be closed during flush, ignore enqueue errors\n if (!(error instanceof TypeError && error.message.includes('closed'))) {\n throw error;\n }\n }\n }\n }\n\n protected handleError(error: DOMException): void {\n // Codec reclaimed by browser due to inactivity, let transform re-initialize on next frame\n if (error.message.includes('reclaimed')) {\n console.warn('Encoder reclaimed by browser due to inactivity, skipping error handling');\n return;\n }\n console.error(`[${this.getEncoderType()}Encoder] Encode error:`, {\n name: error.name,\n message: error.message,\n encoderState: this.encoder?.state,\n queueSize: this.queueSize,\n platform: typeof navigator !== 'undefined' ? navigator.platform : 'unknown',\n });\n this.controller?.error(error);\n }\n\n // Abstract methods to be implemented by subclasses\n protected abstract isConfigSupported(config: TConfig): Promise<{ supported: boolean }>;\n protected abstract createEncoder(init: EncoderInit): TEncoder;\n protected abstract getEncoderType(): string;\n\n // Hook for subclasses to handle reset\n protected onReset(): void {\n // Override in subclasses if needed\n }\n\n // Abstract properties for backpressure configuration\n protected abstract readonly highWaterMark: number;\n protected abstract readonly encodeQueueThreshold: number;\n\n /**\n * Create transform stream for encoding\n * Implements common stream logic with backpressure handling\n */\n createStream(): TransformStream<TInput, EncoderChunk> {\n return new TransformStream<TInput, EncoderChunk>(\n {\n start: async (controller) => {\n this.controller = controller;\n },\n\n transform: async (input) => {\n // Lazy init: create encoder on first frame or re-create after codec reclaim\n if (!this.isReady) {\n console.warn('Encoder is not ready, initializing...');\n await this.initialize();\n }\n if (!this.encoder || this.encoder.state !== 'configured') {\n console.error('Encoder not configured, throwing error');\n throw new Error('Encoder not configured');\n }\n\n // Check encoder queue pressure\n if (this.encoder.encodeQueueSize >= this.encodeQueueThreshold) {\n // Wait for queue to drain\n await new Promise<void>((resolve) => {\n const check = () => {\n if (!this.encoder || this.encoder.encodeQueueSize < this.encodeQueueThreshold - 1) {\n resolve();\n } else {\n setTimeout(check, 10);\n }\n };\n check();\n });\n }\n\n // Encode the input\n const frame = (input as any).frame || input;\n try {\n this.encode(frame);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error('Encoder error:', msg);\n if (err instanceof DOMException && msg.includes('reclaimed')) {\n console.warn('Codec reclaimed due to inactivity, reset encoder...');\n this.encoder = undefined;\n await this.initialize();\n this.encode(frame);\n } else {\n throw err;\n }\n }\n },\n\n flush: async () => {\n await this.flush();\n },\n },\n // Queuing strategy with backpressure configuration\n {\n highWaterMark: this.highWaterMark,\n size: () => 1, // Count-based\n }\n );\n }\n\n // Abstract method for encoding\n abstract encode(input: TInput): void;\n}\n\ninterface EncoderInit {\n output: (chunk: any, metadata: any) => void;\n error: (error: DOMException) => void;\n}\n"],"names":[],"mappings":"AAYO,MAAe,YAMpB;AAAA,EACU;AAAA,EACA;AAAA,EACA,aAAoE;AAAA,EAE9E,YAAY,QAAiB;AAC3B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,YAAqB;AACnB,WAAO,EAAE,GAAG,KAAK,OAAA;AAAA,EACnB;AAAA,EAEA,IAAc,gBAAyB;AACrC,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,kBAAkB,SAAoC;AAC9D,UAAM,OAAO,EAAE,GAAG,KAAK,QAAQ,GAAG,QAAA;AAClC,UAAM,OAAO,OAAO,KAAK,WAAW,CAAA,CAAE;AACtC,eAAW,OAAO,MAAM;AACtB,UAAI,QAAQ,GAAG,MAAM,UAAa,KAAK,GAAG,MAAM,KAAK,OAAO,GAAG,GAAG;AAChE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEU,iBAAiB,MAAwB;AACjD,UAAM,iBAAiB,OAAO,QAAQ,KAAK,MAAM;AACjD,eAAW,CAAC,KAAK,KAAK,KAAK,gBAAgB;AACzC,UAAI,KAAK,GAAG,MAAM,OAAO;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,eAAW,OAAO,OAAO,KAAK,IAAI,GAA2B;AAC3D,UAAI,KAAK,OAAO,GAAG,MAAM,KAAK,GAAG,GAAG;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEU,aAAa,GAAY,GAAqB;AACtD,WAAO,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAM,aAA4B;AAChC,YAAQ,KAAK,4BAA4B;AACzC,QAAI,KAAK,SAAS,UAAU,cAAc;AACxC,cAAQ,KAAK,yDAAyD;AACtE;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB,KAAK,MAAM;AAE5D,QAAI,CAAC,YAAY,WAAW;AAC1B,cAAQ,KAAK,wBAAwB,KAAK,UAAU,KAAK,MAAM,CAAC;AAChE,YAAM,IAAI,MAAM,wBAAwB,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AAAA,IACvE;AAEA,SAAK,UAAU,KAAK,cAAc;AAAA,MAChC,QAAQ,KAAK,aAAa,KAAK,IAAI;AAAA,MACnC,OAAO,KAAK,YAAY,KAAK,IAAI;AAAA,IAAA,CAClC;AAEA,SAAK,QAAgB,UAAU,KAAK,MAAM;AAC3C,YAAQ,KAAK,wBAAwB;AAAA,EACvC;AAAA,EAEA,MAAM,YAAY,QAAyC;AACzD,YAAQ,KAAK,6BAA6B;AAC1C,QAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAC/C;AAAA,IACF;AAEA,UAAM,aAAa,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAA;AAExC,QAAI,KAAK,aAAa,KAAK,QAAQ,UAAU,GAAG;AAC9C;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,SAAS;AACjB,WAAK,SAAS;AACd,YAAM,KAAK,WAAA;AACX;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,UAAU,cAAc;AACvC,YAAM,KAAK,QAAQ,MAAA;AAAA,IACrB;AAEA,UAAM,cAAc,MAAM,KAAK,kBAAkB,UAAU;AAC3D,QAAI,CAAC,YAAY,WAAW;AAC1B,YAAM,IAAI,MAAM,oCAAoC,WAAW,KAAK,EAAE;AAAA,IACxE;AAEA,SAAK,SAAS;AACb,SAAK,QAAgB,UAAU,KAAK,MAAM;AAC3C,YAAQ,KAAK,yBAAyB;AAAA,EACxC;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,UAAM,KAAK,QAAQ,MAAA;AAAA,EACrB;AAAA,EAEA,MAAM,QAAuB;AAC3B,YAAQ,KAAK,yBAAyB;AACtC,QAAI,CAAC,KAAK,SAAS;AACjB,cAAQ,KAAK,4CAA4C;AACzD;AAAA,IACF;AAEA,SAAK,QAAQ,MAAA;AACb,SAAK,QAAA;AACL,YAAQ,KAAK,qBAAqB;AAAA,EACpC;AAAA,EAEA,MAAM,QAAuB;AAC3B,YAAQ,KAAK,uBAAuB;AACpC,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,UAAU,cAAc;AACvC,YAAM,KAAK,QAAQ,MAAA;AAAA,IACrB;AAEA,SAAK,QAAQ,MAAA;AACb,SAAK,UAAU;AACf,YAAQ,KAAK,mBAAmB;AAAA,EAClC;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,SAAS,UAAU;AAAA,EACjC;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,SAAS,mBAAmB;AAAA,EAC1C;AAAA,EAEU,aAAa,OAAe,UAA2B;AAE/D,QAAI,KAAK,YAAY;AACnB,UAAI;AACF,aAAK,WAAW,QAAQ,EAAE,OAAO,UAAU;AAAA,MAC7C,SAAS,OAAO;AACd,gBAAQ,MAAM,yBAAyB,KAAK;AAE5C,YAAI,EAAE,iBAAiB,aAAa,MAAM,QAAQ,SAAS,QAAQ,IAAI;AACrE,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEU,YAAY,OAA2B;AAE/C,QAAI,MAAM,QAAQ,SAAS,WAAW,GAAG;AACvC,cAAQ,KAAK,yEAAyE;AACtF;AAAA,IACF;AACA,YAAQ,MAAM,IAAI,KAAK,eAAA,CAAgB,0BAA0B;AAAA,MAC/D,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,cAAc,KAAK,SAAS;AAAA,MAC5B,WAAW,KAAK;AAAA,MAChB,UAAU,OAAO,cAAc,cAAc,UAAU,WAAW;AAAA,IAAA,CACnE;AACD,SAAK,YAAY,MAAM,KAAK;AAAA,EAC9B;AAAA;AAAA,EAQU,UAAgB;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,eAAsD;AACpD,WAAO,IAAI;AAAA,MACT;AAAA,QACE,OAAO,OAAO,eAAe;AAC3B,eAAK,aAAa;AAAA,QACpB;AAAA,QAEA,WAAW,OAAO,UAAU;AAE1B,cAAI,CAAC,KAAK,SAAS;AACjB,oBAAQ,KAAK,uCAAuC;AACpD,kBAAM,KAAK,WAAA;AAAA,UACb;AACA,cAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,UAAU,cAAc;AACxD,oBAAQ,MAAM,wCAAwC;AACtD,kBAAM,IAAI,MAAM,wBAAwB;AAAA,UAC1C;AAGA,cAAI,KAAK,QAAQ,mBAAmB,KAAK,sBAAsB;AAE7D,kBAAM,IAAI,QAAc,CAAC,YAAY;AACnC,oBAAM,QAAQ,MAAM;AAClB,oBAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,kBAAkB,KAAK,uBAAuB,GAAG;AACjF,0BAAA;AAAA,gBACF,OAAO;AACL,6BAAW,OAAO,EAAE;AAAA,gBACtB;AAAA,cACF;AACA,oBAAA;AAAA,YACF,CAAC;AAAA,UACH;AAGA,gBAAM,QAAS,MAAc,SAAS;AACtC,cAAI;AACF,iBAAK,OAAO,KAAK;AAAA,UACnB,SAAS,KAAK;AACZ,kBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,oBAAQ,MAAM,kBAAkB,GAAG;AACnC,gBAAI,eAAe,gBAAgB,IAAI,SAAS,WAAW,GAAG;AAC5D,sBAAQ,KAAK,qDAAqD;AAClE,mBAAK,UAAU;AACf,oBAAM,KAAK,WAAA;AACX,mBAAK,OAAO,KAAK;AAAA,YACnB,OAAO;AACL,oBAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,QAEA,OAAO,YAAY;AACjB,gBAAM,KAAK,MAAA;AAAA,QACb;AAAA,MAAA;AAAA;AAAA,MAGF;AAAA,QACE,eAAe,KAAK;AAAA,QACpB,MAAM,MAAM;AAAA;AAAA,MAAA;AAAA,IACd;AAAA,EAEJ;AAIF;"}
@@ -1 +1 @@
1
- {"version":3,"file":"VideoChunkEncoder.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/VideoChunkEncoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,WAAW,CAChD,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,iBAAiB,EACjB,yBAAyB,CAC1B;IACC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAK;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAAK;IAE3D,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IAEhD,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,gBAAgB,CAAM;gBAElB,MAAM,EAAE,kBAAkB;cAetB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAK9F,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY;IAI7D,SAAS,CAAC,cAAc,IAAI,MAAM;cAIf,OAAO,IAAI,IAAI;IAIlC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAW/B,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI3C,OAAO,CAAC,sBAAsB;CAM/B"}
1
+ {"version":3,"file":"VideoChunkEncoder.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/VideoChunkEncoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,WAAW,CAChD,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,iBAAiB,EACjB,yBAAyB,CAC1B;IACC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAK;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAAK;IAE3D,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IAEhD,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,gBAAgB,CAAM;gBAElB,MAAM,EAAE,kBAAkB;cAuBtB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAK9F,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY;IAI7D,SAAS,CAAC,cAAc,IAAI,MAAM;cAIf,OAAO,IAAI,IAAI;IAIlC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAc/B,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK3C,OAAO,CAAC,sBAAsB;CAM/B"}
@@ -1,4 +1,4 @@
1
- import { StreamTarget, ArrayBufferTarget, Muxer } from "../../node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js";
1
+ import { StreamTarget, ArrayBufferTarget, Muxer } from "../../medeo-fe/node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js";
2
2
  import { checkBrowserCompatibility } from "../../utils/platform-utils.js";
3
3
  class MP4Muxer {
4
4
  muxer;
@@ -1,4 +1,4 @@
1
- import * as mp4box_all from "../node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js";
1
+ import * as mp4box_all from "../medeo-fe/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js";
2
2
  const lib = mp4box_all;
3
3
  const MP4Box = lib.default && typeof lib.default.createFile === "function" ? lib.default : lib;
4
4
  if (typeof MP4Box.createFile !== "function") {
@@ -2322,11 +2322,14 @@ class BaseEncoder {
2322
2322
  return JSON.stringify(a) === JSON.stringify(b);
2323
2323
  }
2324
2324
  async initialize() {
2325
+ console.info("Encoder is initializing...");
2325
2326
  if (this.encoder?.state === "configured") {
2327
+ console.warn("Encoder is already initialized, skipping initialization");
2326
2328
  return;
2327
2329
  }
2328
2330
  const isSupported = await this.isConfigSupported(this.config);
2329
2331
  if (!isSupported.supported) {
2332
+ console.warn("Codec not supported:", JSON.stringify(this.config));
2330
2333
  throw new Error(`Codec not supported: ${JSON.stringify(this.config)}`);
2331
2334
  }
2332
2335
  this.encoder = this.createEncoder({
@@ -2334,8 +2337,10 @@ class BaseEncoder {
2334
2337
  error: this.handleError.bind(this)
2335
2338
  });
2336
2339
  this.encoder.configure(this.config);
2340
+ console.info("Encoder is initialized");
2337
2341
  }
2338
2342
  async reconfigure(config) {
2343
+ console.info("Encoder is reconfiguring...");
2339
2344
  if (!config || Object.keys(config).length === 0) {
2340
2345
  return;
2341
2346
  }
@@ -2357,6 +2362,7 @@ class BaseEncoder {
2357
2362
  }
2358
2363
  this.config = nextConfig;
2359
2364
  this.encoder.configure(this.config);
2365
+ console.info("Encoder is reconfigured");
2360
2366
  }
2361
2367
  async flush() {
2362
2368
  if (!this.encoder) {
@@ -2365,13 +2371,17 @@ class BaseEncoder {
2365
2371
  await this.encoder.flush();
2366
2372
  }
2367
2373
  async reset() {
2374
+ console.info("Encoder is resetting...");
2368
2375
  if (!this.encoder) {
2376
+ console.warn("Encoder is not initialized, skipping reset");
2369
2377
  return;
2370
2378
  }
2371
2379
  this.encoder.reset();
2372
2380
  this.onReset();
2381
+ console.info("Encoder is resetted");
2373
2382
  }
2374
2383
  async close() {
2384
+ console.info("Encoder is closing...");
2375
2385
  if (!this.encoder) {
2376
2386
  return;
2377
2387
  }
@@ -2380,6 +2390,7 @@ class BaseEncoder {
2380
2390
  }
2381
2391
  this.encoder.close();
2382
2392
  this.encoder = void 0;
2393
+ console.info("Encoder is closed");
2383
2394
  }
2384
2395
  get isReady() {
2385
2396
  return this.encoder?.state === "configured";
@@ -2392,6 +2403,7 @@ class BaseEncoder {
2392
2403
  try {
2393
2404
  this.controller.enqueue({ chunk, metadata });
2394
2405
  } catch (error) {
2406
+ console.error("Encoder output error:", error);
2395
2407
  if (!(error instanceof TypeError && error.message.includes("closed"))) {
2396
2408
  throw error;
2397
2409
  }
@@ -2399,6 +2411,10 @@ class BaseEncoder {
2399
2411
  }
2400
2412
  }
2401
2413
  handleError(error) {
2414
+ if (error.message.includes("reclaimed")) {
2415
+ console.warn("Encoder reclaimed by browser due to inactivity, skipping error handling");
2416
+ return;
2417
+ }
2402
2418
  console.error(`[${this.getEncoderType()}Encoder] Encode error:`, {
2403
2419
  name: error.name,
2404
2420
  message: error.message,
@@ -2420,12 +2436,14 @@ class BaseEncoder {
2420
2436
  {
2421
2437
  start: async (controller) => {
2422
2438
  this.controller = controller;
2439
+ },
2440
+ transform: async (input) => {
2423
2441
  if (!this.isReady) {
2442
+ console.warn("Encoder is not ready, initializing...");
2424
2443
  await this.initialize();
2425
2444
  }
2426
- },
2427
- transform: async (input) => {
2428
2445
  if (!this.encoder || this.encoder.state !== "configured") {
2446
+ console.error("Encoder not configured, throwing error");
2429
2447
  throw new Error("Encoder not configured");
2430
2448
  }
2431
2449
  if (this.encoder.encodeQueueSize >= this.encodeQueueThreshold) {
@@ -2441,7 +2459,20 @@ class BaseEncoder {
2441
2459
  });
2442
2460
  }
2443
2461
  const frame = input.frame || input;
2444
- this.encode(frame);
2462
+ try {
2463
+ this.encode(frame);
2464
+ } catch (err) {
2465
+ const msg = err instanceof Error ? err.message : String(err);
2466
+ console.error("Encoder error:", msg);
2467
+ if (err instanceof DOMException && msg.includes("reclaimed")) {
2468
+ console.warn("Codec reclaimed due to inactivity, reset encoder...");
2469
+ this.encoder = void 0;
2470
+ await this.initialize();
2471
+ this.encode(frame);
2472
+ } else {
2473
+ throw err;
2474
+ }
2475
+ }
2445
2476
  },
2446
2477
  flush: async () => {
2447
2478
  await this.flush();
@@ -2471,6 +2502,14 @@ class VideoChunkEncoder extends BaseEncoder {
2471
2502
  if (config.keyFrameInterval !== void 0) {
2472
2503
  this.keyFrameInterval = Math.max(1, config.keyFrameInterval);
2473
2504
  }
2505
+ console.info(
2506
+ "VideoChunkEncoder initialized with encodeQueueThreshold:",
2507
+ this.encodeQueueThreshold,
2508
+ " highWaterMark:",
2509
+ this.highWaterMark,
2510
+ " keyFrameInterval:",
2511
+ this.keyFrameInterval
2512
+ );
2474
2513
  }
2475
2514
  async isConfigSupported(config) {
2476
2515
  const result = await VideoEncoder.isConfigSupported(config);
@@ -2486,16 +2525,20 @@ class VideoChunkEncoder extends BaseEncoder {
2486
2525
  this.frameCount = 0;
2487
2526
  }
2488
2527
  encode(frame) {
2489
- const keyFrame = this.shouldGenerateKeyFrame();
2490
- const encodeOptions = {
2491
- keyFrame
2492
- };
2493
- this.encoder.encode(frame, encodeOptions);
2494
- this.frameCount++;
2495
- frame.close();
2528
+ try {
2529
+ const keyFrame = this.shouldGenerateKeyFrame();
2530
+ const encodeOptions = {
2531
+ keyFrame
2532
+ };
2533
+ this.encoder.encode(frame, encodeOptions);
2534
+ this.frameCount++;
2535
+ } finally {
2536
+ frame.close();
2537
+ }
2496
2538
  }
2497
2539
  setKeyFrameInterval(interval) {
2498
2540
  this.keyFrameInterval = Math.max(1, interval);
2541
+ console.info("Key frame interval set to:", this.keyFrameInterval);
2499
2542
  }
2500
2543
  shouldGenerateKeyFrame() {
2501
2544
  if (this.frameCount === 0) {
@@ -3209,4 +3252,4 @@ const export_worker = null;
3209
3252
  export {
3210
3253
  export_worker as default
3211
3254
  };
3212
- //# sourceMappingURL=export.worker.BYttrqTQ.js.map
3255
+ //# sourceMappingURL=export.worker.SahP9aVK.js.map