diff --git a/.memory/worklog.json b/.memory/worklog.json index 474e125..1e1ce2c 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -125,6 +125,13 @@ "message": "auto-save 2026-05-12 17:12 (~3)", "hash": "e1bc89a", "files_changed": 3 + }, + { + "ts": "2026-05-12T17:17:49+08:00", + "type": "commit", + "message": "auto-save 2026-05-12 17:17 (~1)", + "hash": "4fd43e8", + "files_changed": 1 } ] } diff --git a/api/main.py b/api/main.py index 4799feb..69c7709 100644 --- a/api/main.py +++ b/api/main.py @@ -194,39 +194,28 @@ async def pipeline_analyze(job_id: str, frame_count: int = KEYFRAME_COUNT) -> No ]) n = max(1, min(int(frame_count), 20)) - update(job, message=f"抽取 {n} 张关键帧…", progress=50) + update(job, message=f"抽取 {n} 张关键帧(均匀采样)…", progress=50) frames_dir = d / "frames" if frames_dir.exists(): shutil.rmtree(frames_dir) frames_dir.mkdir(parents=True) - try: + # 均匀采样:在 duration / (n+1) 的等距时间点各抽 1 帧 + # 用 -ss 在 -i 前 = fast seek,每张 < 0.5s + duration = max(float(job.duration or 1.0), 0.1) + step = duration / (n + 1) + for i in range(n): + t = step * (i + 1) + out = frames_dir / f"sample_{i:03d}.jpg" run([ - "ffmpeg", "-y", "-i", str(mp4), - "-vf", "select='gt(scene,0.4)'", - "-fps_mode", "vfr", - "-frames:v", str(n * 3), + "ffmpeg", "-y", + "-ss", str(t), + "-i", str(mp4), + "-frames:v", "1", "-pix_fmt", "yuvj420p", "-q:v", "3", - str(frames_dir / "scene_%03d.jpg"), + str(out), ]) - except Exception: - pass - scene_frames = sorted(frames_dir.glob("scene_*.jpg")) - - if len(scene_frames) < n: - sample_count = n - len(scene_frames) - duration = job.duration or 1.0 - step = duration / (sample_count + 1) - for i in range(sample_count): - t = step * (i + 1) - out = frames_dir / f"sample_{i:03d}.jpg" - run([ - "ffmpeg", "-y", "-ss", str(t), "-i", str(mp4), - "-frames:v", "1", - "-pix_fmt", "yuvj420p", - "-q:v", "3", str(out), - ]) all_frames = sorted(frames_dir.glob("*.jpg"))[:n] renamed: list[KeyFrame] = []