mirror of
https://github.com/siddharthvaddem/openscreen.git
synced 2026-08-31 02:04:58 +08:00
5e62ad3215
Two bugs in the export pipeline: 1. Container duration from WebM metadata can be unreliable (Chromium bug on Linux — reports Infinity, 0, or inflated values). The pipeline trusted this value, causing inflated exports, frozen video, and "decode ended early" errors. Fix: scan actual packet timestamps in loadMetadata() and compare against container duration. Use packet-based ground truth when they diverge. 2. The speed-aware audio path (renderPitchPreservedTimelineAudio) recorded in real-time via MediaRecorder but never paused recording during trim-region seeks. Seek dead time was captured as audio, inflating the audio track beyond the video duration. Fix: pause MediaRecorder during trim seeks, skip past initial trim before recording starts, wait for seek completion before resuming. Fixes #276, #433. Partially addresses #428.
79 lines
2.1 KiB
TypeScript
79 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { shouldFailDecodeEndedEarly, validateDuration } from "./streamingDecoder";
|
|
|
|
describe("validateDuration", () => {
|
|
it("returns scanned duration when container reports Infinity", () => {
|
|
expect(validateDuration(Infinity, 15.3)).toBe(15.3);
|
|
});
|
|
|
|
it("returns scanned duration when container reports 0", () => {
|
|
expect(validateDuration(0, 15.3)).toBe(15.3);
|
|
});
|
|
|
|
it("returns scanned duration when container reports NaN", () => {
|
|
expect(validateDuration(NaN, 15.3)).toBe(15.3);
|
|
});
|
|
|
|
it("returns scanned duration when container is inflated beyond threshold", () => {
|
|
expect(validateDuration(42, 15.3)).toBe(15.3);
|
|
});
|
|
|
|
it("returns container duration when values are close", () => {
|
|
expect(validateDuration(15.5, 15.3)).toBe(15.5);
|
|
});
|
|
|
|
it("returns container duration when scanned is slightly higher", () => {
|
|
// container < scanned (scanned overshoot from last frame duration)
|
|
expect(validateDuration(15.0, 15.3)).toBe(15.0);
|
|
});
|
|
|
|
it("returns container duration when scanned is zero (corrupted/empty file)", () => {
|
|
expect(validateDuration(10, 0)).toBe(10);
|
|
});
|
|
});
|
|
|
|
describe("shouldFailDecodeEndedEarly", () => {
|
|
it("does not fail once every segment has been satisfied", () => {
|
|
expect(
|
|
shouldFailDecodeEndedEarly({
|
|
cancelled: false,
|
|
lastDecodedFrameSec: 5.33,
|
|
requiredEndSec: 6.498,
|
|
streamDurationSec: 5.33,
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
|
|
it("fails when decode stops far before the required end", () => {
|
|
expect(
|
|
shouldFailDecodeEndedEarly({
|
|
cancelled: false,
|
|
lastDecodedFrameSec: 5.33,
|
|
requiredEndSec: 10,
|
|
streamDurationSec: 5.33,
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("fails when no frame could be decoded for a non-empty timeline", () => {
|
|
expect(
|
|
shouldFailDecodeEndedEarly({
|
|
cancelled: false,
|
|
lastDecodedFrameSec: null,
|
|
requiredEndSec: 1,
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("fails when the decoder has not reached the reported stream end", () => {
|
|
expect(
|
|
shouldFailDecodeEndedEarly({
|
|
cancelled: false,
|
|
lastDecodedFrameSec: 4.9,
|
|
requiredEndSec: 6.498,
|
|
streamDurationSec: 5.33,
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
});
|