{"record":{"id":"876b427d0a1de477","repo":"heygen-com/hyperframes","slug":"ffmpeg-is-required-to-extract-video-frames-for-sna","errorCode":null,"errorMessage":"FFmpeg is required to extract video frames for snapshots. ${getFFmpegInstallHint()}","messagePattern":"FFmpeg is required to extract video frames for snapshots\\. (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/snapshot.ts","lineNumber":108,"sourceCode":"  const atClipEnd = Math.abs(globalTime - clipEnd) <= clipEndTolerance;\n  if (!atClipEnd) return relativeTime;\n\n  const sourceEnd = sourceDuration > 0 ? sourceDuration : relativeTime;\n  return Math.max(0, Math.min(relativeTime, sourceEnd - 1 / 30));\n}\n\n/** Prefer the runtime's canonical absolute media start. The authored value is\n * only a compatibility fallback for pages built with an older runtime. */\nexport function resolveSnapshotVideoClipStart(input: {\n  authoredStart: number;\n  runtimeResolvedStart: number | null;\n}): number {\n  return input.runtimeResolvedStart ?? input.authoredStart;\n}\n\nexport function requireSnapshotFfmpeg(ffmpegPath: string | undefined): string {\n  if (ffmpegPath) return ffmpegPath;\n  throw new Error(\n    `FFmpeg is required to extract video frames for snapshots. ${getFFmpegInstallHint()}`,\n  );\n}\n\n/**\n * Extract a single frame from a video file at `timeSeconds` via FFmpeg.\n * Used to work around Chrome-headless's inability to reliably seek\n * <video> elements during snapshot capture.\n */\nasync function extractVideoFrameToBuffer(\n  videoPath: string,\n  timeSeconds: number,\n  useVp9AlphaDecoder = false,\n): Promise<Buffer | null> {\n  const tmp = mkdtempSync(join(tmpdir(), \"hf-snapshot-frame-\"));\n  const outPath = join(tmp, \"frame.png\");\n  try {\n    const ffmpegPath = requireSnapshotFfmpeg(findFFmpeg());","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/snapshot.ts#L90-L126","documentation":"Thrown by requireSnapshotFfmpeg when ffmpegPath is undefined. Snapshot capture for video clips uses ffmpeg to extract a single frame (working around Chrome-headless's unreliable <video> seeking), so ffmpeg is mandatory for that path. findFFmpeg() is called upstream and returns undefined when no ffmpeg is found on PATH.","triggerScenarios":"Capturing a snapshot from a composition containing a <video> clip triggers requireSnapshotFfmpeg(findFFmpeg()) at snapshot.ts:126; if findFFmpeg() returned undefined the function throws with the platform install hint appended.","commonSituations":"ffmpeg not installed (common on fresh macOS/Windows); ffmpeg installed but not on PATH in the current shell/CI; running in a minimal container without media tools; snapshotting a video-backed composition for the first time.","solutions":["Install ffmpeg and ensure it is on PATH (`ffmpeg -version`)","Follow the install hint echoed in the error message (brew install ffmpeg / winget / apt)","In CI add an ffmpeg setup step (e.g. `apt-get install -y ffmpeg`)","If ffmpeg lives elsewhere, set the path your host configures for HYPERFRAMES_FFMPEG_PATH"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { execFileSync } from \"node:child_process\";\nfunction ffmpegAvailable(): boolean {\n  try { execFileSync(\"ffmpeg\", [\"-version\"], { stdio: \"ignore\" }); return true; }\n  catch { return false; }\n}\nif (!ffmpegAvailable()) throw new Error(\"Install ffmpeg before snapshotting video clips.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install ffmpeg and confirm `ffmpeg -version` in the snapshotting environment","Add an ffmpeg setup step in CI containers","Avoid compositions with <video> clips if ffmpeg can't be provisioned"],"tags":["snapshot","ffmpeg","external-dependency","media"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}