From 46f55dc61a3ffa3644ef3968f2c26eb634ba94dd Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Sun, 5 Apr 2026 18:14:42 +1000 Subject: [PATCH] Fix encoder errors reported as cancellations --- src/lib/exporter/modernVideoExporter.ts | 18 +++++++++++++++--- src/lib/exporter/videoExporter.ts | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/lib/exporter/modernVideoExporter.ts b/src/lib/exporter/modernVideoExporter.ts index 921a0496..4031c3cd 100644 --- a/src/lib/exporter/modernVideoExporter.ts +++ b/src/lib/exporter/modernVideoExporter.ts @@ -132,6 +132,7 @@ export class ModernVideoExporter { private renderFrameTimeMs = 0; private encodeWaitTimeMs = 0; private encodeWaitEvents = 0; + private encoderError: Error | null = null; private peakEncodeQueueSize = 0; private peakNativeWriteInFlight = 0; private nativeCaptureTimeMs = 0; @@ -149,6 +150,7 @@ export class ModernVideoExporter { try { this.cleanup(); this.cancelled = false; + this.encoderError = null; this.totalExportStartTimeMs = this.getNowMs(); let stageStartedAt = this.getNowMs(); @@ -341,6 +343,14 @@ export class ModernVideoExporter { this.decodeLoopTimeMs = this.getNowMs() - decodeLoopStartedAt; if (this.cancelled) { + if (this.encoderError) { + return { + success: false, + error: this.buildLightningExportError(this.encoderError), + metrics: this.buildExportMetrics(), + }; + } + return { success: false, error: "Export cancelled", metrics: this.buildExportMetrics() }; } @@ -401,14 +411,15 @@ export class ModernVideoExporter { return { success: true, blob, metrics: this.buildExportMetrics() }; } catch (error) { - if (this.cancelled) { + if (this.cancelled && !this.encoderError) { return { success: false, error: "Export cancelled", metrics: this.buildExportMetrics() }; } + const resolvedError = this.encoderError ?? error; console.error("Export error:", error); return { success: false, - error: this.buildLightningExportError(error), + error: this.buildLightningExportError(resolvedError), metrics: this.buildExportMetrics(), }; } finally { @@ -1122,7 +1133,7 @@ export class ModernVideoExporter { `[VideoExporter] Encoder error (codec: ${resolvedCodec}, ${this.config.width}x${this.config.height}):`, error, ); - // Stop export — encoding failed + this.encoderError = error instanceof Error ? error : new Error(String(error)); this.cancelled = true; }, }); @@ -1292,6 +1303,7 @@ export class ModernVideoExporter { this.renderFrameTimeMs = 0; this.encodeWaitTimeMs = 0; this.encodeWaitEvents = 0; + this.encoderError = null; this.peakEncodeQueueSize = 0; this.peakNativeWriteInFlight = 0; this.nativeCaptureTimeMs = 0; diff --git a/src/lib/exporter/videoExporter.ts b/src/lib/exporter/videoExporter.ts index 2a399b54..6db90240 100644 --- a/src/lib/exporter/videoExporter.ts +++ b/src/lib/exporter/videoExporter.ts @@ -99,6 +99,7 @@ export class VideoExporter { private exportStartTimeMs = 0; private progressSampleStartTimeMs = 0; private progressSampleStartFrame = 0; + private encoderError: Error | null = null; private nativeExportSessionId: string | null = null; constructor(config: VideoExporterConfig) { @@ -109,6 +110,7 @@ export class VideoExporter { try { this.cleanup(); this.cancelled = false; + this.encoderError = null; this.exportStartTimeMs = this.getNowMs(); this.progressSampleStartTimeMs = this.exportStartTimeMs; this.progressSampleStartFrame = 0; @@ -230,6 +232,11 @@ export class VideoExporter { ); if (this.cancelled) { + const encoderError = this.encoderError as Error | null; + if (encoderError) { + return { success: false, error: encoderError.message }; + } + return { success: false, error: "Export cancelled" }; } @@ -270,10 +277,15 @@ export class VideoExporter { return { success: true, blob }; } catch (error) { + if (this.cancelled && !this.encoderError) { + return { success: false, error: "Export cancelled" }; + } + + const resolvedError = this.encoderError ?? error; console.error("Export error:", error); return { success: false, - error: error instanceof Error ? error.message : String(error), + error: resolvedError instanceof Error ? resolvedError.message : String(resolvedError), }; } finally { this.cleanup(); @@ -678,7 +690,7 @@ export class VideoExporter { `[VideoExporter] Encoder error (codec: ${resolvedCodec}, ${this.config.width}x${this.config.height}):`, error, ); - // Stop export — encoding failed + this.encoderError = error instanceof Error ? error : new Error(String(error)); this.cancelled = true; }, }); @@ -793,6 +805,7 @@ export class VideoExporter { this.encodeQueue = 0; this.pendingMuxing = Promise.resolve(); this.chunkCount = 0; + this.encoderError = null; this.videoDescription = undefined; this.videoColorSpace = undefined; }