claw-advisor
This skill should be used when the user asks about OpenClaw configuration, troubleshooting, setup, architecture, or any OpenClaw…
Extracts first and/or last frames of every shot from a video using adaptive scene detection. Use this skill when the user says "extract frames", "get shot frames", "pull frames", "shot breakdown", "scene detect", "first frame of each shot", "last frame of each shot", "extract
$ npx -y skills add gupsammy/Claudest --skill extract-frames --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/extract-framesContext preview
The summary Claude sees to decide when to auto-load this skill.
Extracts first and/or last frames of every shot from a video using adaptive scene detection. Use this skill when the user says "extract frames", "get shot frames", "pull frames", "shot breakdown", "scene detect", "first frame of each shot", "last frame of each shot", "extract
name: extract-frames description: > Extracts first and/or last frames of every shot from a video using adaptive scene detection. Use this skill when the user says "extract frames", "get shot frames", "pull frames", "shot breakdown", "scene detect", "first frame of each shot", "last frame of each shot", "extract shots from video", or wants to extract key frames at shot cut points from a video file. allowed-tools: - Bash(ffprobe:*) - Bash(ffmpeg:*) - Bash(awk:*) - Bash(tr:*) - Bash(mkdir:*) - AskUserQuestion - Read argument-hint: "<video-path> [--first] [--last] [--all] [--shots N,N] [--threshold X]"
Parse the user's request for:
Default: extract first frame of every shot.
1. Validate the video file exists. 2. Get video metadata via ffprobe:
ffprobe -v error -show_entries format=duration -show_entries stream=r_frame_rate,width,height,codec_name -of default "$INPUT"
3. Parse fps (needed for last-frame calculation) and duration. 4. Create output directory next to the video: `{video_basename}_frames/`. If it already exists, check for `scores.txt` — if present, skip Phase 1.
Dump per-frame scene scores for the entire video:
ffmpeg -i "$INPUT" -vf "select='gte(scene,0)',metadata=print:file=$OUTPUT_DIR/scores.txt" -fps_mode vfr -f null - 2>&1
This is the expensive step. The output file `scores.txt` contains blocks like:
frame:0 pts:0 pts_time:0.000000 lavfi.scene_score=0.000000
Parse scores.txt with this awk one-liner to get distribution + all candidate frames:
awk '
/pts_time/ { split($0, a, "pts_time:"); ts=a[2]+0 }
/scene_score/ { split($0, a, "="); score=a[2]+0;
if (score < 0.01) b1++;
else if (score < 0.05) b2++;
else if (score < 0.10) b3++;
else if (score < 0.20) b4++;
else b5++;
total++;
if (score > max) max=score;
if (score > 0.05) printf " ts=%.3fs score=%.6f\n", ts, score;
}
END {
print "\n--- Distribution ---";
printf "< 0.01: %d (%.1f%%)\n", b1, b1/total*100;
printf "0.01 - 0.05: %d (%.1f%%)\n", b2, b2/total*100;
printf "0.05 - 0.10: %d (%.1f%%)\n", b3, b3/total*100;
printf "0.10 - 0.20: %d (%.1f%%)\n", b4, b4/total*100;
printf "0.20+: %d (%.1f%%)\n", b5, b5/total*100;
printf "Max score: %.6f\n", max;
}' "$OUTPUT_DIR/scores.txt"**Step 2a — Startup artifact filter:** Discard any frames in the first 0.5s where `score > 0.05` (a fixed preliminary value — the final user-confirmed threshold is not known yet). Fade-ins from black or codec initialization commonly produce score=1.0 spikes at t=0.03-0.08s that are not real cuts. After discarding these, recompute max score from the remaining frames.
**Step 2b — Branch on max score.** If max score (after startup filter) < 0.05, the video has no cuts:
**Step 2c — Gap analysis and threshold.** If max score >= 0.05, use the raw candidates (all frames with score > 0.05, after startup filter) to find the noise ceiling and the lowest-scoring candidate. Place the proposed threshold at the midpoint of the gap. Present to user via AskUserQuestion:
If `--threshold` was provided, skip confirmation and set `$THRESHOLD_VALUE` directly. Otherwise set `$THRESHOLD_VALUE` to the user-confirmed value before proceeding.
**Step 2d — Run-based dedup.** Using `$THRESHOLD_VALUE` from Step 2c, identify cut points. A "run" is a sequence of consecutive frames where every frame scores above threshold. The principle: an aftershock immediately follows its parent cut (consecutive frames both above threshold), while a real cut always rises from the noise floor (preceded by at least one below-threshold frame).
awk -v THRESHOLD="$THRESHOLD_VALUE" '
/pts_time/ { split($0, a, "pts_time:"); ts=a[2]+0 }
/scene_score/ { split($0, a, "="); score=a[2]+0;
if (score > THRESHOLD) {
if (!in_run) { run_best_ts = ts; run_best_score = score; in_run = 1; }
else if (score > run_best_score) { run_best_ts = ts; run_best_score = score; }
} else {
if (in_run) { printf "%.3f %.6f\n", run_best_ts, run_best_score; in_run = 0; }
}
}
END { if (in_run) printf "%.3f %.6f\n", run_best_ts, run_best_score }
' "$OUTPUT_DIR/scores.txt"This keeps the peak frame of each run and discards aftershocks within the same run. It correctly handles:
For each detected cut point (plus t=0 for shot 1):
**First frame** (default):
ffmpeg -y -ss $TIMESTAMP -i "$INPUT" -frames:v 1 -update 1 "$OUTPUT_DIR/shot_${NUM}_${TIME}s.png"**Last frame** (`--last`):
ffmpeg -y -ss $LAST_TIME -i "$INPUT" -frames:v 1 -update 1 "$OUTPUT_DIR/shot_${NUM}_last_${TIME}s.png"If a last-frame ext
A highly opinionated plugin marketplace for augmenting your Claude Code. Battle-tested skills and tools that actually work.
This skill should be used when the user asks about OpenClaw configuration, troubleshooting, setup, architecture, or any OpenClaw…
This skill should be used when the user asks to "create an OpenClaw skill", "make a claw skill", "build a skill for OpenClaw",…
This skill should be used when the user says "clean up branches", "delete merged branches", or "prune stale branches". Use…
This skill should be used when the user says "commit my changes", "commit this", "create a commit", "git commit", "save my work",…
This skill should be used when the user says "get PR comments", "show PR feedback", "what comments on my PR", "PR review…