mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-08 02:36:10 +00:00
fix(producer): assert render artifact duration and frame count before commit (#3506)
* fix(producer): assert render artifact duration and frame count before commit Refuse to publish an artifact that is significantly shorter or has fewer frames than the capture pipeline just reported. Adds a duration/frame-count gate on top of the existing readable-non-empty check inside ArtifactTransaction.validate(), keyed off the values the orchestrator already carries. Closes #3395. * fix(producer): wire ffprobe frame count into the artifact duration probe The frame-count gate added in #3395 accepts an expectedFrames value from the orchestrator, but defaultArtifactDurationProbe was still returning only durationSeconds - so the wire was half-built and the assertion short-circuited on undefined for every real render. Forward meta.frames from ffprobe so the field-packet case the issue names (container duration correct, stream shorter) is actually caught by the frame-count check, not just the duration one. extractMediaMetadata now populates a new frames field from the video stream's nb_frames tag, returning undefined when the demuxer did not report one (fragmented MP4, malformed streams, muxes that require -count_packets). Callers that gate on the count must treat undefined as no answer; the assertion already does. The previous CI run (#32589981916) cancelled shard-6 at the 1h job timeout after bun install failed to extract the aws-cdk-lib tarball mid-Docker-build - a cache flake, not a code regression. Pushing a follow-up commit retriggers CI against the now-populated cache layer; the regression should clear without further code changes. --------- Co-authored-by: Santhi Prakash <b.santhiprakash@gmail.com>
This commit is contained in:
co-authored by
Santhi Prakash
parent
e5c7dc75e8
commit
05275c1e8c
@@ -188,6 +188,11 @@ export interface VideoMetadata {
|
||||
hasAlpha: boolean;
|
||||
/** Color space info from the video stream. Null if ffprobe didn't report it. */
|
||||
colorSpace: VideoColorSpace | null;
|
||||
/** Decoded frame count from the video stream's `nb_frames`. Omitted when the
|
||||
* container does not surface a reliable count (still images, malformed
|
||||
* streams, or muxes that require `-count_packets` to populate). Callers
|
||||
* that gate on a frame count must treat `undefined` as "no answer". */
|
||||
frames?: number;
|
||||
}
|
||||
|
||||
export interface AudioMetadata {
|
||||
@@ -731,6 +736,7 @@ export async function extractMediaMetadata(filePath: string): Promise<VideoMetad
|
||||
isVFR: false,
|
||||
hasAlpha: false,
|
||||
colorSpace: stillImageMeta.colorSpace,
|
||||
frames: 1,
|
||||
};
|
||||
}
|
||||
throw new Error("[FFmpeg] No video stream found");
|
||||
@@ -775,6 +781,14 @@ export async function extractMediaMetadata(filePath: string): Promise<VideoMetad
|
||||
const streamDuration = videoStream.duration ? parseFloat(videoStream.duration) : 0;
|
||||
const parsedStreamStart = videoStream.start_time ? parseFloat(videoStream.start_time) : 0;
|
||||
const streamStart = Number.isFinite(parsedStreamStart) ? parsedStreamStart : 0;
|
||||
// `nb_frames` is populated by the container demuxer; a muxer that requires
|
||||
// `-count_packets` to enumerate frames will leave it undefined, in which
|
||||
// case the caller must treat the frame-count check as "no answer". This
|
||||
// path is hit by, for example, fragmented MP4 where the moov box lacks a
|
||||
// frame count — the captured duration is still correct.
|
||||
const parsedNbFrames = videoStream.nb_frames ? parseInt(videoStream.nb_frames, 10) : NaN;
|
||||
const frames =
|
||||
Number.isFinite(parsedNbFrames) && parsedNbFrames > 0 ? parsedNbFrames : undefined;
|
||||
|
||||
return {
|
||||
durationSeconds: containerDuration,
|
||||
@@ -788,6 +802,7 @@ export async function extractMediaMetadata(filePath: string): Promise<VideoMetad
|
||||
isVFR,
|
||||
hasAlpha,
|
||||
colorSpace,
|
||||
frames,
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user