Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Sparse-keyframe check silently skips single-keyframe videos — the worst case goes unreported (0.8.10)

オープン
#3,460 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@ravsau がすでに取り組んでいます。

2026年9月15日 から。

  • #3538 @rajanpanth による — マージされずにクローズ
  • #3573 @miga-heygen による — マージされずにクローズ
  • #3576 @miga-heygen による — マージされずにクローズ
  • #3762 @Abhishek-kumarsingh による — マージされずにクローズ
  • #3971 @ravsau による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript

調査の方向性

Start in engine/src/utils/ffprobe.ts at analyzeKeyframeIntervalsUncached, then inspect the duration path in extractVideoMetadata and the compiler warning entry point. Reproduce the single-keyframe and two-keyframe cases from the issue, and verify that single-keyframe videos use their stream duration while zero-keyframe and zero-duration assets retain their existing behavior.

索引モデルが issue の本文から書いたものです。

説明

triage/needs-triage

Summary

analyzeKeyframeIntervals bails out when a video has fewer than two keyframes and reports isProblematic: false. But a video with exactly one keyframe is the worst case for the very failure mode the warning exists to catch: every seek past 0 lands inside a single GOP that spans the whole file. The compiler warns about a 5-second GOP and stays silent about a 10-second one.

In analyzeKeyframeIntervalsUncached (bundled from engine/src/utils/ffprobe.ts):

const timestamps = stdout.split("\n").map(l => parseFloat(l.trim())).filter(Number.isFinite);
if (timestamps.length < 2) {
  return { avgIntervalSeconds: 0, maxIntervalSeconds: 0, keyframeCount: timestamps.length, isProblematic: false };
}

The early return is reasonable for still images and 1-frame assets, but it also swallows real single-GOP videos of arbitrary length.

Reproduction

Two 10-second clips, identical except for GOP size:

ffmpeg -y -f lavfi -i testsrc=size=640x360:rate=30:duration=10 \
  -c:v libx264 -pix_fmt yuv420p -g 1000 -keyint_min 1000 -sc_threshold 0 assets/single-gop.mp4
ffmpeg -y -f lavfi -i testsrc=size=640x360:rate=30:duration=10 \
  -c:v libx264 -pix_fmt yuv420p -g 150 -keyint_min 150 -sc_threshold 0 assets/five-second-gop.mp4

Keyframe timestamps:

single-gop.mp4        0.000000
five-second-gop.mp4   0.000000  5.000000

index.html — both clips, each seeking to 8s:

<div id="root" data-composition-id="gop-repro" data-start="0" data-duration="2" data-width="640" data-height="360">
  <video id="single-gop" class="clip layer" data-start="0" data-duration="1" data-track-index="0" data-media-start="8" src="assets/single-gop.mp4" muted></video>
  <video id="five-second-gop" class="clip layer" data-start="1" data-duration="1" data-track-index="0" data-media-start="8" src="assets/five-second-gop.mp4" muted></video>
</div>
npx [email protected] render . -o out.mp4 2>&1 | grep Compiler

Observed

[WARN] [Compiler] WARNING: Video "five-second-gop" has sparse keyframes (max interval: 5s). ...

Nothing for single-gop, whose effective seek distance is 10s — twice as bad.

Expected

single-gop should warn at least as loudly as five-second-gop.

Suggested fix

When exactly one keyframe is found, the effective interval is the stream duration, not zero:

if (timestamps.length === 1) {
  const duration = await probeDurationSeconds(filePath); // already available via extractVideoMetadata
  return {
    avgIntervalSeconds: duration,
    maxIntervalSeconds: duration,
    keyframeCount: 1,
    isProblematic: duration > 2,
  };
}
if (timestamps.length === 0) {
  return { avgIntervalSeconds: 0, maxIntervalSeconds: 0, keyframeCount: 0, isProblematic: false };
}

Still images and single-frame assets keep their current behaviour, since their duration is 0 or below the threshold.

Why it matters in practice

This is not a synthetic corner case. In a 414-clip library downloaded straight from Pexels and Pixabay, 26 files are single-GOP with durations from 2.3s to 10s — exactly the ones the check skips. Overall that library sits well above the 2s threshold anyway (median max interval 3.04s, 82% above 3s), so in practice the check fires on nearly everything except the worst offenders.

Side note, offered as data rather than a complaint

While measuring the above we could not reproduce the failure the warning describes, on hyperframes render at least. Two stands cut deliberately mid-GOP — a stock clip with keyframes 10s apart, and an Archive.org master with 5.51s intervals, cut 3.5s past a keyframe — both rendered frame-accurate: mean per-pixel luma delta against ffmpeg-extracted ground truth was 1.4–1.8, versus 15–60 against any neighbouring moment. The video_extract phase resolves frames through ffmpeg (minVideoFrameCoverageRatio: 1), which decodes from the preceding keyframe correctly. Re-encoding per the suggested command changed render wall-clock by ~3% (95s vs 98s on the same stand), i.e. noise.

So the warning may be aimed at a different path (browser seeking in preview/studio?) than the one render takes. If that is the case, narrowing its wording or its scope might be worth considering alongside the fix above.

Environment: macOS 26.5.2 (arm64), Node 26.0.0, hyperframes 0.8.10 (also verified on 0.7.106).

主要言語
TypeScript
スター
54.1k
フォーク
4.9k
平均マージ
7時間 19分
マージ済み PR(30日)
746

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

heygen-com/hyperframes のほかの issue

heygen-com/hyperframes の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。