304b639b4d
Frame extraction now runs a perceptual dedup pass (default on, --no-dedup to disable) that drops near-identical frames before the budget cap, so the budget goes to distinct content instead of held slides/static recordings. The Frames report line notes how many near-duplicates were dropped. Whisper transcription splits audio over the 25 MB upload cap into evenly sized chunks, transcribes each, shifts segment timestamps back into source time, and tolerates partial failures (only fails if every chunk fails) — length alone no longer fails transcription. token-burner is exempt from the long-video sparse-scan warning since it keeps every scene-change frame. README/SKILL.md updated. Adds test_dedup.py and test_whisper.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
"""End-to-end routing of --detail through watch.py on a local clip."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
WATCH = Path(__file__).resolve().parent.parent / "skills" / "watch" / "scripts" / "watch.py"
|
|
|
|
|
|
def _run(clip: Path, *args: str, env_extra: dict | None = None) -> str:
|
|
env = dict(os.environ)
|
|
env.pop("WATCH_DETAIL", None)
|
|
if env_extra:
|
|
env.update(env_extra)
|
|
proc = subprocess.run(
|
|
[sys.executable, str(WATCH), str(clip), "--no-whisper", *args],
|
|
capture_output=True, text=True, env=env,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return proc.stdout
|
|
|
|
|
|
def test_efficient_uses_keyframe_engine(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "efficient")
|
|
assert "(keyframe" in out
|
|
assert "**Detail:** efficient" in out
|
|
|
|
|
|
def test_balanced_uses_scene_engine(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "balanced")
|
|
assert "(scene" in out
|
|
assert "**Detail:** balanced" in out
|
|
|
|
|
|
def test_token_burner_uses_scene_engine(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "token-burner")
|
|
assert "(scene" in out
|
|
|
|
|
|
def test_transcript_skips_frames(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "transcript")
|
|
assert "skipped" in out
|
|
assert "frame_0000.jpg" not in out
|
|
|
|
|
|
def test_flag_overrides_env(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "efficient", env_extra={"WATCH_DETAIL": "balanced"})
|
|
assert "(keyframe" in out
|
|
|
|
|
|
def test_default_is_balanced(cut_clip: Path):
|
|
out = _run(cut_clip) # no flag, WATCH_DETAIL cleared
|
|
assert "**Detail:** balanced" in out
|
|
assert "(scene" in out
|
|
|
|
|
|
def test_timestamps_add_cue_frames_to_detail(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "balanced", "--timestamps", "1,3")
|
|
assert "reason=transcript-cue" in out
|
|
assert "reason=scene-change" in out # detail frames still present (additive)
|
|
|
|
|
|
def test_timestamps_with_transcript_detail_is_cue_only(cut_clip: Path):
|
|
out = _run(cut_clip, "--detail", "transcript", "--timestamps", "1,3")
|
|
assert "reason=transcript-cue" in out
|
|
assert "reason=scene-change" not in out
|
|
assert "reason=keyframe" not in out
|
|
|
|
|
|
def _frame_lines(out: str) -> int:
|
|
return sum(1 for line in out.splitlines() if "/frames/frame_" in line and "(t=" in line)
|
|
|
|
|
|
def test_dedup_collapses_static_by_default(static_clip: Path):
|
|
out = _run(static_clip) # solid blue → identical frames collapse to one
|
|
assert "near-duplicate" in out
|
|
assert _frame_lines(out) == 1
|
|
|
|
|
|
def test_no_dedup_preserves_static_frames(static_clip: Path):
|
|
out = _run(static_clip, "--no-dedup")
|
|
assert "near-duplicate" not in out
|
|
assert _frame_lines(out) > 1
|