heygen-com/hyperframes · error
Whisper did not produce output. Check the input file.
Error message
Whisper did not produce output. Check the input file.
What it means
After the whisper-cli child process exits (exit code 0), transcribe() expects a transcript JSON at `${outputDir}/transcript.json`. If existsSync() reports it missing, this error fires. It means whisper returned success but wrote no output file, almost always indicating the input audio was empty, corrupt, in an incompatible format, or too short for whisper to segment.
Source
Thrown at packages/cli/src/whisper/transcribe.ts:506
stdio: "ignore",
timeout: whisperTimeoutMs,
});
} catch (err) {
// Surface the timeout knob when the child was killed by our own timeout —
// otherwise the reporter sees a bare ETIMEDOUT / SIGTERM with no hint that
// `--timeout` even exists. Non-timeout errors flow through unchanged so the
// existing stderr-tail handling in `transcribeAudio` still applies.
throw wrapWhisperTimeoutError(err, {
effectiveTimeoutMs: whisperTimeoutMs,
model: effectiveModel,
wasOverride: options?.timeoutMs != null,
});
}
// 6. Read and validate output
const transcriptPath = `${outputBase}.json`;
if (!existsSync(transcriptPath)) {
throw new Error("Whisper did not produce output. Check the input file.");
}
const transcript = JSON.parse(readFileSync(transcriptPath, "utf-8"));
const segments = transcript.transcription ?? [];
let wordCount = 0;
let maxEnd = 0;
for (const seg of segments) {
for (const token of seg.tokens ?? []) {
const text = (token.text ?? "").trim();
if (text && !text.startsWith("[_") && !text.startsWith("[BLANK")) wordCount++;
if (token.offsets?.to > maxEnd) maxEnd = token.offsets.to;
}
}
// 7. Detect speech onset before cleaning up the WAV
options?.onProgress?.("Detecting speech onset...");
const speechOnsetSeconds = detectSpeechOnset(wavPath);View on GitHub (pinned to c2996c8626)
Solutions
- Inspect the prepared WAV: play it or run `ffprobe ./prepared.wav` to confirm it has audio stream, a sane duration (>0), and 16kHz mono; re-source the input if it is empty/silent.
- Give each transcribe() call a unique outputDir so concurrent runs cannot clobber each other's transcript.json (the base name 'transcript' is hard-coded).
- Re-run the whisper step manually with the same args (printed in the failure) and read its stderr — whisper-cli often logs why it produced no segments even on exit 0.
- Verify the output directory is writable and has free disk space before the run.
Example fix
// before
await transcribe(silentOrEmptyClip, sharedOutputDir);
// after — guard duration and use a per-call output dir
import { statSync } from "node:fs";
const wav = prepareAudio(silentOrEmptyClip);
// ffprobe / inspect: if duration is ~0, the source has no usable audio
const out = join(tmpdir(), `tx-${randomUUID()}`);
await transcribe(wav, out); Defensive patterns
Strategy: try-catch
Validate before calling
import { statSync, existsSync } from "node:fs";
// pre-check the prepared WAV is non-empty and the output dir is writable & unique
if (statSync(wavPath).size === 0) throw new Error('prepared WAV is empty — source has no audio');
const out = join(tmpdir(), `tx-${randomUUID()}`); // unique dir avoids collisions Type guard
null
Try / catch
try {
await transcribe(input, uniqueOutDir);
} catch (err) {
if (/did not produce output/.test(String(err))) {
// inspect the WAV with ffprobe; re-source silent/empty input; do not retry unchanged
} else throw err;
} Prevention
- Give every concurrent transcribe() call a unique outputDir to avoid transcript.json collisions.
- Verify the input has a non-zero audio stream (ffprobe) before transcribing.
- Ensure the output directory is writable with free disk space.
- Do not retry the identical command — re-source or repair the input first.
When it happens
Trigger: whisper-cli was invoked with a WAV that is 0 seconds long, contains only silence, has an unsupported sample rate/channel layout, or is a malformed WAV header; whisper exits 0 but emits nothing. Also possible if the output directory is on a read-only / full filesystem, or if two concurrent transcribe() calls collide on the same outputDir (transcript base name is fixed as 'transcript').
Common situations: A scene whose captured audio is silent (no narration was recorded); a video with no audio track at all, where extractAudio produced an empty WAV; parallel renders sharing one outputDir; a corrupt download used as input.
Related errors
- Parakeet did not produce output.
- ffmpeg is required to extract audio from video. Install: ${g
- ffmpeg is required to prepare audio. Install: ${getFFmpegIns
- Unsupported file type: ${ext}
- Unknown effect type: ${type}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/caeb8a52b9bee091.
Report an issue: GitHub.