fix(export): relax early decode termination on Windows
On Windows, tolerate small decode gaps (<=3 seconds) to work around driver quirks, allowing export to complete with available frames.
This commit is contained in:
@@ -638,6 +638,18 @@ export function registerIpcHandlers(
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles saving an exported video file.
|
||||
* Shows a save dialog, normalizes the file path for the current OS,
|
||||
* ensures the directory exists, and writes the video data.
|
||||
* @param _ - Unused event parameter.
|
||||
* @param videoData - The exported video as an ArrayBuffer.
|
||||
* @param fileName - Suggested filename for the save dialog.
|
||||
* @returns Object with success status, optional file path, and error details.
|
||||
*/
|
||||
|
||||
|
||||
ipcMain.handle("save-exported-video", async (_, videoData: ArrayBuffer, fileName: string) => {
|
||||
try {
|
||||
// Determine file type from extension
|
||||
|
||||
@@ -217,7 +217,15 @@ export class StreamingVideoDecoder {
|
||||
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes all video frames from the loaded source and invokes a callback for each.
|
||||
* Handles trimming and speed adjustments, and resamples to the target frame rate.
|
||||
* On Windows, early decode termination is tolerated to work around driver quirks.
|
||||
* @param targetFrameRate - Desired output frame rate.
|
||||
* @param trimRegions - Array of time regions to keep (others discarded).
|
||||
* @param speedRegions - Array of speed adjustments for specific time ranges.
|
||||
* @param onFrame - Async callback receiving each decoded VideoFrame.
|
||||
*/
|
||||
async decodeAll(
|
||||
targetFrameRate: number,
|
||||
trimRegions: TrimRegion[] | undefined,
|
||||
@@ -491,33 +499,29 @@ export class StreamingVideoDecoder {
|
||||
}
|
||||
this.decoder = null;
|
||||
|
||||
const requiredEndSec = segments.length > 0 ? segments[segments.length - 1].endSec : 0;
|
||||
const isWindows = typeof navigator !== "undefined" && /Windows/.test(navigator.userAgent);
|
||||
const isWindows = typeof navigator !== "undefined" && /Windows/.test(navigator.userAgent);
|
||||
|
||||
if (
|
||||
shouldFailDecodeEndedEarly({
|
||||
cancelled: this.cancelled,
|
||||
lastDecodedFrameSec,
|
||||
requiredEndSec,
|
||||
streamDurationSec: this.metadata.streamDuration,
|
||||
})
|
||||
) {
|
||||
const decodedAtLabel =
|
||||
lastDecodedFrameSec === null ? "no decoded frame" : `${lastDecodedFrameSec.toFixed(3)}s`;
|
||||
|
||||
if (isWindows) {
|
||||
console.warn(
|
||||
`[StreamingVideoDecoder] Decode ended early on Windows at ${decodedAtLabel} (needed ${requiredEndSec.toFixed(3)}s) – proceeding anyway.`,
|
||||
);
|
||||
// Do not throw on Windows; allow export to complete with the frames we have.
|
||||
} else {
|
||||
throw new Error(
|
||||
`Video decode ended early at ${decodedAtLabel} (needed ${requiredEndSec.toFixed(3)}s).`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldFailDecodeEndedEarly({
|
||||
cancelled: this.cancelled,
|
||||
lastDecodedFrameSec,
|
||||
requiredEndSec,
|
||||
streamDurationSec: this.metadata.streamDuration,
|
||||
})) {
|
||||
const decodedAtLabel = lastDecodedFrameSec === null ? "no decoded frame" : `${lastDecodedFrameSec.toFixed(3)}s`;
|
||||
const decodeGapSec = lastDecodedFrameSec === null ? Infinity : requiredEndSec - lastDecodedFrameSec;
|
||||
|
||||
// On Windows, tolerate a small decode gap (<= 3 seconds) to work around driver quirks.
|
||||
// For severe failures (no frames at all, or a large gap), still throw.
|
||||
if (isWindows && lastDecodedFrameSec !== null && decodeGapSec <= 3.0) {
|
||||
console.warn(
|
||||
`[StreamingVideoDecoder] Decode ended early on Windows with a small gap (${decodeGapSec.toFixed(2)}s) – proceeding anyway.`,
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Video decode ended early at ${decodedAtLabel} (needed ${requiredEndSec.toFixed(3)}s).`,
|
||||
);
|
||||
}
|
||||
}
|
||||
private computeSegments(
|
||||
totalDuration: number,
|
||||
trimRegions?: TrimRegion[],
|
||||
|
||||
Reference in New Issue
Block a user