diff --git a/electron/ipc/export/native-video.test.ts b/electron/ipc/export/native-video.test.ts index 6a1f18f2..be54d364 100644 --- a/electron/ipc/export/native-video.test.ts +++ b/electron/ipc/export/native-video.test.ts @@ -1078,6 +1078,47 @@ describe("validateNvidiaCudaExportSummary", () => { expect(issues).toEqual([]); }); + it("rejects inline-audio CUDA output when the helper does not produce audio", () => { + const issues = validateNvidiaCudaExportSummary( + { + success: true, + targetFrames: 300, + durationSec: 10, + nativeSummary: { + success: true, + frames: 300, + sourceTimestampMode: "pts", + selectionStage: "timestamp-mapped-callback", + }, + outputVideo: { duration: "9.999900", nb_frames: "300" }, + }, + { durationSec: 10, targetFrames: 300, requiresTimelineSync: true }, + ); + + expect(issues).toEqual(["missing output audio stream"]); + }); + + it("rejects inline-audio CUDA output when the probed audio stream is empty", () => { + const issues = validateNvidiaCudaExportSummary( + { + success: true, + targetFrames: 300, + durationSec: 10, + nativeSummary: { + success: true, + frames: 300, + sourceTimestampMode: "pts", + selectionStage: "timestamp-mapped-callback", + }, + outputVideo: { duration: "9.999900", nb_frames: "300" }, + outputAudio: { duration: "0.000000" }, + }, + { durationSec: 10, targetFrames: 300, requiresTimelineSync: true }, + ); + + expect(issues).toEqual(["output audio duration is not positive"]); + }); + it("accepts audio CUDA output when the helper reports PTS-aligned selection", () => { const issues = validateNvidiaCudaExportSummary( { diff --git a/electron/ipc/export/native-video.ts b/electron/ipc/export/native-video.ts index 44ba69a1..13adbdd2 100644 --- a/electron/ipc/export/native-video.ts +++ b/electron/ipc/export/native-video.ts @@ -433,6 +433,13 @@ export function validateNvidiaCudaExportSummary( if (expected.requiresTimelineSync && !isNvidiaCudaTimestampAlignedSummary(summary)) { issues.push("CUDA timeline mode is not timestamp-aligned for audio export"); } + if (expected.requiresTimelineSync) { + if (!summary.outputAudio) { + issues.push("missing output audio stream"); + } else if (outputAudioDurationSec !== null && outputAudioDurationSec <= 0) { + issues.push("output audio duration is not positive"); + } + } if (nativeFrames === null) { issues.push("missing native frame count"); } else if (nativeFrames < minimumFrames) { @@ -455,6 +462,7 @@ export function validateNvidiaCudaExportSummary( } if ( outputAudioDurationSec !== null && + outputAudioDurationSec > 0 && Math.abs(outputAudioDurationSec - expectedDurationSec) > durationToleranceSec ) { issues.push(