mifi/lossless-cut · error · UserFacingError

Cannot find any keyframe after the desired start cut point

Error message

Cannot find any keyframe after the desired start cut point

What it means

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.

Source

Thrown at src/renderer/src/smartcut.ts:39

  const keyframeAtExactTime = findKeyframeAtExactTime(keyframes, desiredCutFrom);
  if (keyframeAtExactTime) {
    console.log('Start cut is already on exact keyframe', keyframeAtExactTime.time);

    return {
      losslessCutFrom: keyframeAtExactTime.time,
      segmentNeedsSmartCut: false,
    };
  }

  let nextKeyframe = findNextKeyframe(keyframes, desiredCutFrom);

  if (nextKeyframe == null) {
    // try again with a larger window
    keyframes = await readKeyframes(60);
    nextKeyframe = findNextKeyframe(keyframes, desiredCutFrom);
  }
  if (nextKeyframe == null) throw new UserFacingError(i18n.t('Cannot find any keyframe after the desired start cut point'));

  console.log('Smart cut from keyframe', { keyframe: nextKeyframe.time, desiredCutFrom });

  return {
    losslessCutFrom: nextKeyframe.time,
    segmentNeedsSmartCut: true,
  };
}

// eslint-disable-next-line import/prefer-default-export
export async function getCodecParams({ path, fileDuration, streams }: {
  path: string,
  fileDuration: number | undefined,
  streams: Pick<FFprobeStream, 'has_b_frames' | 'time_base' | 'codec_type' | 'disposition' | 'index' | 'bit_rate' | 'codec_name'>[],
}) {
  const videoStreams = getRealVideoStreams(streams);
  if (videoStreams.length > 1) throw new Error('Can only smart cut video with exactly one video stream');

View on GitHub (pinned to 3b9a59c288)

Solutions

  1. Probe keyframes over a wider window (e.g. the full file duration) before giving up.
  2. If cutting near the end with no forward keyframe, fall back to lossless cut or re-encode the tail.
  3. Re-encode the source with denser keyframes (-g, -force_key_frames) if forward cuts are required there.
  4. Confirm the keyframe list is non-empty and spans the cut with `ffprobe -select_streams v -show_frames -skip_frame nokey`.

Example fix

// before
if (nextKeyframe == null) throw new UserFacingError(i18n.t('Cannot find any keyframe after the desired start cut point'));

// after
if (nextKeyframe == null) {
  // no forward keyframe: degrade to lossless cut at requested time
  return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };
}
Defensive patterns

Strategy: fallback

Validate before calling

// Probe keyframes across the full file duration as a last resort
const fullKeyframes = await readKeyframesAroundTime({ filePath: path, streamIndex, aroundTime: desiredCutFrom, window: fileDuration ?? 600 });
if (!findNextKeyframe(fullKeyframes, desiredCutFrom)) {
  // no forward keyframe anywhere; degrade to lossless cut
  return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };
}

Try / catch

try {
  return await needsSmartCut({ path, desiredCutFrom, videoStream });
} catch (err) {
  if (err instanceof UserFacingError && /keyframe after the desired start cut/.test(err.message)) {
    return { losslessCutFrom: desiredCutFrom, segmentNeedsSmartCut: false };
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mifi/lossless-cut@3b9a59c288 (2026-08-12). Data as JSON: /api/errors/9e72db5d6a5a859b. Report an issue: GitHub.