// Classifies the result of an ffmpeg transcode-to-null probe of a partial // (or finalized) media file. Used by the audio-checked download flow to // detect mid-stream corruption that would render the final transcode useless. // // The probe runs a real transcode (e.g. libmp3lame) to /dev/null. ffmpeg's // exit code is one signal, but it is unreliable on its own: a stream can // fail to decode on hundreds of packets and ffmpeg still exits 0 because // the encoder kept producing output from the packets that did decode. So // we also count per-packet decoder failures in stderr — above a small // threshold, the stream is malformed regardless of exit code or whether // the container is also truncated. // // Pure-function module: no side effects, no IO. Keeps test specs from having // to pull execa/etc. into the test process. export type StreamVerdict = "clean" | "partial" | "malformed"; // Stderr line that ffmpeg emits when the input container is cut off // mid-frame but the encoder still got enough decoded audio to produce a // valid output. Presence of this line means the file is partial-but-clean. export const PARTIAL_STDERR_PATTERN = /partial file/i; // Per-packet decoder failure ffmpeg prints (at -v error) when the av_codec // layer rejects a packet as undecodable. A genuinely truncated container // produces at most one or two of these at the tail; mid-stream corruption // produces hundreds. export const DECODER_ERROR_PATTERN = /Error submitting packet to decoder: Invalid data found when processing input/g; // Above this many decoder failures we classify as malformed. Tuned from // observed logs: clean/partial probes show 0–2 trailing errors; corrupt // streams show 100+. export const DECODER_ERROR_THRESHOLD = 5; export function classifyFfmpegProbe( exitCode: number | null, stderr: string, ): StreamVerdict { if (exitCode !== 0) return "malformed"; const decoderErrors = stderr.match(DECODER_ERROR_PATTERN)?.length ?? 0; if (decoderErrors > DECODER_ERROR_THRESHOLD) return "malformed"; return PARTIAL_STDERR_PATTERN.test(stderr) ? "partial" : "clean"; }