{"record":{"id":"9e72db5d6a5a859b","repo":"mifi/lossless-cut","slug":"cannot-find-any-keyframe-after-the-desired-start-c","errorCode":null,"errorMessage":"Cannot find any keyframe after the desired start cut point","messagePattern":"Cannot find any keyframe after the desired start cut point","errorType":"exception","errorClass":"UserFacingError","httpStatus":null,"severity":"error","filePath":"src/renderer/src/smartcut.ts","lineNumber":39,"sourceCode":"\n  const keyframeAtExactTime = findKeyframeAtExactTime(keyframes, desiredCutFrom);\n  if (keyframeAtExactTime) {\n    console.log('Start cut is already on exact keyframe', keyframeAtExactTime.time);\n\n    return {\n      losslessCutFrom: keyframeAtExactTime.time,\n      segmentNeedsSmartCut: false,\n    };\n  }\n\n  let nextKeyframe = findNextKeyframe(keyframes, desiredCutFrom);\n\n  if (nextKeyframe == null) {\n    // try again with a larger window\n    keyframes = await readKeyframes(60);\n    nextKeyframe = findNextKeyframe(keyframes, desiredCutFrom);\n  }\n  if (nextKeyframe == null) throw new UserFacingError(i18n.t('Cannot find any keyframe after the desired start cut point'));\n\n  console.log('Smart cut from keyframe', { keyframe: nextKeyframe.time, desiredCutFrom });\n\n  return {\n    losslessCutFrom: nextKeyframe.time,\n    segmentNeedsSmartCut: true,\n  };\n}\n\n// eslint-disable-next-line import/prefer-default-export\nexport async function getCodecParams({ path, fileDuration, streams }: {\n  path: string,\n  fileDuration: number | undefined,\n  streams: Pick<FFprobeStream, 'has_b_frames' | 'time_base' | 'codec_type' | 'disposition' | 'index' | 'bit_rate' | 'codec_name'>[],\n}) {\n  const videoStreams = getRealVideoStreams(streams);\n  if (videoStreams.length > 1) throw new Error('Can only smart cut video with exactly one video stream');\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/mifi/lossless-cut/blob/3b9a59c288bf6e11076b583c932cfa48ddab3b02/src/renderer/src/smartcut.ts#L21-L57","documentation":"Thrown by needsSmartCut() in smartcut.ts when, after probing keyframes in a 10s window and re-trying with a 60s window, findNextKeyframe still returns null. The desired cut start is not already on a keyframe and there is no keyframe at or after it within 60 seconds, so the smart-cut split point cannot be determined. Smart cut fundamentally needs the next keyframe forward to define the lossless portion.","triggerScenarios":"Calling needsSmartCut with a desiredCutFrom that lies after the last keyframe in the file; a stream with extremely sparse keyframes (>60s GOP, rare but possible in some surveillance/long-GOP encodes); a keyframe probe that returned an empty or partial list due to a read error.","commonSituations":"Cutting within the final GOP of a file (no keyframe after the cut); keyframe probe window did not cover the cut; corrupted index/keyframe table; very long-GOP HEVC/AV1 streams; cutting near end of a live recording that is still being written.","solutions":["Probe keyframes over a wider window (e.g. the full file duration) before giving up.","If cutting near the end with no forward keyframe, fall back to lossless cut or re-encode the tail.","Re-encode the source with denser keyframes (-g, -force_key_frames) if forward cuts are required there.","Confirm the keyframe list is non-empty and spans the cut with `ffprobe -select_streams v -show_frames -skip_frame nokey`."],"exampleFix":"// before\nif (nextKeyframe == null) throw new UserFacingError(i18n.t('Cannot find any keyframe after the desired start cut point'));\n\n// after\nif (nextKeyframe == null) {\n  // no forward keyframe: degrade to lossless cut at requested time\n  return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };\n}","handlingStrategy":"fallback","validationCode":"// Probe keyframes across the full file duration as a last resort\nconst fullKeyframes = await readKeyframesAroundTime({ filePath: path, streamIndex, aroundTime: desiredCutFrom, window: fileDuration ?? 600 });\nif (!findNextKeyframe(fullKeyframes, desiredCutFrom)) {\n  // no forward keyframe anywhere; degrade to lossless cut\n  return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await needsSmartCut({ path, desiredCutFrom, videoStream });\n} catch (err) {\n  if (err instanceof UserFacingError && /keyframe after the desired start cut/.test(err.message)) {\n    return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };\n  }\n  throw err;\n}","preventionTips":["Probe keyframes over a window at least as large as the file duration for cuts near the end.","Fall back to lossless cut when no forward keyframe exists instead of aborting the export.","Re-encode long-GOP sources with denser keyframes if forward smart cuts are needed.","Confirm keyframe coverage with ffprobe before relying on smart cut."],"tags":["smart-cut","keyframe","ffmpeg","export","video"],"backgroundTag":null,"analyzedSha":"3b9a59c288bf6e11076b583c932cfa48ddab3b02","analyzedAt":"2026-08-12T20:54:25.651Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}