mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 14:50:02 +00:00
fix(cli,core,lint,producer): terminate ffprobe options at every call site
#2740 added `--` to one of nine independent ffprobe invocations, so the bug class it closed stayed open everywhere else while CI reported it fixed — the regression test asserts the argv of that single site. Reproduced on ffprobe 8.1.1: an asset named `-intro.mp4` probes fine through extractMediaMetadata but fails with "Missing argument for option 'intro.mp4'" in audio pad/trim (mid-render), `hyperframes init`, whisper duration probing and webmAlphaCheck. hevcPreviewLint catches and returns false, so a dash-prefixed HEVC preview silently passes the lint rule. Terminated at all of them: producer/services/render/audioPadTrim.ts (x2) producer/plan-parity-analysis.ts cli/commands/init.ts cli/utils/webmAlphaCheck.ts cli/whisper/transcribe.ts (x2) core/mediaGradeAnalyzer.ts lint/hevcPreviewLint.ts audioPadTrim's runFfprobeJson is a near-verbatim clone of the engine's runFfprobe and structurally cannot add the terminator itself, because callers bake the input path into `args`. It now asserts the terminator is present rather than letting a dash-prefixed path through, takes the same stdio ["ignore", ...] as the engine helper, and redacts its stderr — it was throwing raw ffprobe output, which echoes the input path, into logs and telemetry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8e41fa17b9
commit
47564ab94c
@@ -119,6 +119,7 @@ function probeMetadata(outputPath: string): PlanParityStreamMetadata {
|
||||
].join(":"),
|
||||
"-of",
|
||||
"json",
|
||||
"--",
|
||||
outputPath,
|
||||
]);
|
||||
return normalizeFfprobeMetadata(JSON.parse(bytes.toString("utf-8")) as unknown);
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
trackChildProcess,
|
||||
type AudioMetadata,
|
||||
} from "@hyperframes/engine";
|
||||
import { redactTelemetryString } from "@hyperframes/core";
|
||||
|
||||
/**
|
||||
* Tolerance used to decide whether an audio file is already short enough to
|
||||
@@ -361,6 +362,7 @@ async function defaultProbeVideoFrameInfo(
|
||||
"stream=nb_frames,r_frame_rate",
|
||||
"-of",
|
||||
"json",
|
||||
"--",
|
||||
videoPath,
|
||||
],
|
||||
signal,
|
||||
@@ -381,6 +383,7 @@ async function defaultProbeVideoFrameInfo(
|
||||
"stream=nb_read_packets,r_frame_rate",
|
||||
"-of",
|
||||
"json",
|
||||
"--",
|
||||
videoPath,
|
||||
],
|
||||
signal,
|
||||
@@ -434,7 +437,13 @@ async function defaultRunFfmpeg(
|
||||
// ── ffprobe JSON runner (shared between fast/slow video probe paths) ─────
|
||||
|
||||
async function runFfprobeJson<T>(args: string[], signal?: AbortSignal): Promise<T> {
|
||||
const proc = spawn(getFfprobeBinary(), args);
|
||||
// Callers bake the input path into `args` (terminated with "--"), so this
|
||||
// helper cannot add the terminator itself — assert they did rather than
|
||||
// let a dash-prefixed path silently reach ffprobe as an option.
|
||||
if (!args.includes("--")) {
|
||||
throw new Error('[audioPadTrim] ffprobe args must terminate options with "--".');
|
||||
}
|
||||
const proc = spawn(getFfprobeBinary(), args, { stdio: ["ignore", "pipe", "pipe"] });
|
||||
trackChildProcess(proc);
|
||||
let stdout = "";
|
||||
proc.stdout.on("data", (data: Buffer) => {
|
||||
@@ -452,7 +461,9 @@ async function runFfprobeJson<T>(args: string[], signal?: AbortSignal): Promise<
|
||||
throw outcome.error ?? new Error(outcome.stderr);
|
||||
}
|
||||
if (outcome.reason !== "exit" || outcome.exitCode !== 0) {
|
||||
throw new Error(`ffprobe ${outcome.reason}: ${outcome.stderr}`);
|
||||
// Redacted: raw ffprobe stderr echoes the input path, and this message
|
||||
// reaches logs and telemetry.
|
||||
throw new Error(`ffprobe ${outcome.reason}: ${redactTelemetryString(outcome.stderr, 2000)}`);
|
||||
}
|
||||
try {
|
||||
return JSON.parse(stdout) as T;
|
||||
|
||||
Reference in New Issue
Block a user