fix(producer): scale frame coverage by playback rate

This commit is contained in:
Miguel Ángel
2026-08-28 21:27:48 +00:00
parent af1cb1c10d
commit bf22cf4919
2 changed files with 15 additions and 2 deletions
@@ -19,6 +19,7 @@ function makeVideo(overrides: Partial<VideoElement> & { id: string }): VideoElem
start: overrides.start ?? 0,
end: overrides.end ?? 1,
mediaStart: overrides.mediaStart ?? 0,
playbackRate: overrides.playbackRate,
loop: overrides.loop ?? false,
hasAudio: overrides.hasAudio ?? false,
};
@@ -133,6 +134,16 @@ describe("resolveVideoCoverageThreshold", () => {
});
describe("computeVideoFrameCoverage", () => {
it("expects only the source frames consumed by a slowed authored slot", () => {
const videos = [makeVideo({ id: "slow", start: 0, end: 4, playbackRate: 0.5 })];
const extracted = [makeExtracted("slow", 60, { durationSeconds: 4 })];
const reports = computeVideoFrameCoverage(videos, extracted, 30);
expect(reports[0]).toMatchObject({ expectedFrames: 60, capturedFrames: 60, ratio: 1 });
expect(() => assertVideoFrameCoverage(reports, 0.95)).not.toThrow();
});
it("reports 1.0 ratio when every video delivered its authored window", () => {
const videos = [
makeVideo({ id: "a", start: 0, end: 1 }),
@@ -45,7 +45,7 @@
*/
import { parseHTML } from "linkedom";
import { fpsToNumber, toFps, type FpsInput } from "@hyperframes/core";
import { fpsToNumber, normalizePlaybackRate, toFps, type FpsInput } from "@hyperframes/core";
import {
extractionFrameCountForDuration,
resolvePlayableVideoDuration,
@@ -166,7 +166,9 @@ function expectedFramesForVideo(
fps: FpsInput,
): number {
const rounding = entry && !entry.metadata.isVFR ? "nearest" : "ceil";
const slotFrames = expectedFramesForClip(video.start, video.end, fps, rounding);
const playbackRate = normalizePlaybackRate(video.playbackRate ?? 1);
const slotSourceDuration = Math.max(0, video.end - video.start) * playbackRate;
const slotFrames = expectedFramesForClip(0, slotSourceDuration, fps, rounding);
if (!entry) return slotFrames;
// A short source in a longer slot has a legitimate delivery ceiling of