fix
This commit is contained in:
@@ -6,22 +6,20 @@ describe("shouldFailDecodeEndedEarly", () => {
|
||||
expect(
|
||||
shouldFailDecodeEndedEarly({
|
||||
cancelled: false,
|
||||
segmentsLength: 1,
|
||||
completedSegments: 1,
|
||||
lastDecodedFrameSec: 5.33,
|
||||
requiredEndSec: 6.498,
|
||||
streamDurationSec: 5.33,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("fails when decode stops before the remaining segments can be covered", () => {
|
||||
it("fails when decode stops far before the required end", () => {
|
||||
expect(
|
||||
shouldFailDecodeEndedEarly({
|
||||
cancelled: false,
|
||||
segmentsLength: 2,
|
||||
completedSegments: 1,
|
||||
lastDecodedFrameSec: 5.33,
|
||||
requiredEndSec: 6.498,
|
||||
requiredEndSec: 10,
|
||||
streamDurationSec: 5.33,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
@@ -30,11 +28,20 @@ describe("shouldFailDecodeEndedEarly", () => {
|
||||
expect(
|
||||
shouldFailDecodeEndedEarly({
|
||||
cancelled: false,
|
||||
segmentsLength: 1,
|
||||
completedSegments: 0,
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,26 +14,22 @@ export interface DecodedVideoInfo {
|
||||
|
||||
type EarlyDecodeEndCheck = {
|
||||
cancelled: boolean;
|
||||
segmentsLength: number;
|
||||
completedSegments: number;
|
||||
lastDecodedFrameSec: number | null;
|
||||
requiredEndSec: number;
|
||||
streamDurationSec?: number;
|
||||
};
|
||||
|
||||
const EARLY_DECODE_END_THRESHOLD_SEC = 1;
|
||||
const METADATA_TAIL_TOLERANCE_SEC = 1.5;
|
||||
const STREAM_DURATION_MATCH_TOLERANCE_SEC = 0.25;
|
||||
|
||||
export function shouldFailDecodeEndedEarly({
|
||||
cancelled,
|
||||
segmentsLength,
|
||||
completedSegments,
|
||||
lastDecodedFrameSec,
|
||||
requiredEndSec,
|
||||
streamDurationSec,
|
||||
}: EarlyDecodeEndCheck): boolean {
|
||||
if (cancelled || segmentsLength === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we already satisfied every segment, the exporter has successfully
|
||||
// filled any short metadata tail using the last decoded frame.
|
||||
if (completedSegments >= segmentsLength) {
|
||||
if (cancelled || requiredEndSec <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -41,7 +37,28 @@ export function shouldFailDecodeEndedEarly({
|
||||
return true;
|
||||
}
|
||||
|
||||
return requiredEndSec - lastDecodedFrameSec > 1;
|
||||
const decodeGapSec = requiredEndSec - lastDecodedFrameSec;
|
||||
if (decodeGapSec <= EARLY_DECODE_END_THRESHOLD_SEC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof streamDurationSec !== "number" || !Number.isFinite(streamDurationSec)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const metadataTailSec = requiredEndSec - streamDurationSec;
|
||||
const decodedNearStreamEnd =
|
||||
Math.abs(lastDecodedFrameSec - streamDurationSec) <= STREAM_DURATION_MATCH_TOLERANCE_SEC;
|
||||
|
||||
if (
|
||||
decodedNearStreamEnd &&
|
||||
metadataTailSec > 0 &&
|
||||
metadataTailSec <= METADATA_TAIL_TOLERANCE_SEC
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Caller must close the VideoFrame after use. */
|
||||
@@ -400,10 +417,9 @@ export class StreamingVideoDecoder {
|
||||
if (
|
||||
shouldFailDecodeEndedEarly({
|
||||
cancelled: this.cancelled,
|
||||
segmentsLength: segments.length,
|
||||
completedSegments: segmentIdx,
|
||||
lastDecodedFrameSec,
|
||||
requiredEndSec,
|
||||
streamDurationSec: this.metadata.streamDuration,
|
||||
})
|
||||
) {
|
||||
const decodedAtLabel =
|
||||
|
||||
@@ -87,8 +87,8 @@ test("exports a GIF from a loaded video", async () => {
|
||||
await editorWindow.getByTestId("testId-gif-format-button").click();
|
||||
await editorWindow.getByTestId("testId-export-button").click();
|
||||
|
||||
// ── 6. Wait for the toast to say exported successfully
|
||||
await expect(editorWindow.getByText(`GIF exported successfully to pending`)).toBeVisible({
|
||||
// ── 6. Wait for the success toast.
|
||||
await expect(editorWindow.getByText("GIF exported successfully")).toBeVisible({
|
||||
timeout: 90_000,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user