How Working Directory Cleanup Works After Video Processing in Claude Video

The watch skill in bradautomates/claude-video implements a strict "cleanup contract" that deletes temporary files at four distinct stages—before extraction, after perceptual deduplication, after even-sampling selection, and during final key-frame generation—to ensure only the selected frames remain on disk.

The claude-video repository handles video processing through a systematic pipeline that prevents disk space bloat by aggressively removing intermediate files. According to the source code in skills/watch/scripts/frames.py, the cleanup process follows a predictable lifecycle that guarantees no stray JPEGs or temporary artifacts survive after processing completes.

The Four-Stage Cleanup Process

The working directory maintenance operates through four specific phases, each targeting different categories of temporary files created during frame extraction.

Stage 1: Pre-Extraction Purge

Before any frame extraction begins, the target output folder is sanitized to remove leftovers from previous runs. In skills/watch/scripts/frames.py (lines 596–599), the code ensures a clean slate:

out_dir.mkdir(parents=True, exist_ok=True)
for existing in out_dir.glob("frame_*.jpg"):
    existing.unlink()

This pre-extraction purge eliminates any existing frame_*.jpg files that might remain from interrupted or previous processing sessions, preventing contamination of the new extraction batch.

Stage 2: Deduplication Removal

After frames are extracted, the dedupe_perceptual function identifies near-identical images. The cleanup logic (lines 500–505) immediately deletes these redundant files from disk rather than merely excluding them from the selection set:

for cand in dropped:
    Path(cand["path"]).unlink()

This deduplication removal ensures that perceptually similar frames—those deemed too close in visual content—are physically removed, freeing space before the final sampling stage.

Stage 3: Even-Sampling Prune

When the _even_sample function selects the final frame distribution, it generates a list of kept paths (keep_paths). Any candidate frames not selected for the final set are purged (lines 404–410):

for cand in candidates:
    if cand["path"] not in keep_paths:
        Path(cand["path"]).unlink()

This even-sampling prune operation guarantees that only the evenly distributed representative frames remain, deleting all intermediate candidates that failed the selection criteria.

Stage 4: Key-Frame Extraction Finalization

The high-level extract_keyframes helper orchestrates the complete workflow by repeating the pre-extraction purge (Stage 1) and then invoking ffmpeg to write fresh key-frame JPEGs into the now-empty directory. This final stage ensures that the output directory contains only the definitive set of selected frames, with all processing artifacts removed.

Complete Working Example

The cleanup process operates automatically when calling the extraction helpers. The following example demonstrates how extract_keyframes manages the entire lifecycle:

from pathlib import Path
from skills.watch.scripts.frames import extract_keyframes

# Example: extract up to 50 keyframes from a video

video = "sample.mp4"
out_dir = Path("/tmp/video_frames")
selected_frames, meta = extract_keyframes(
    video_path=video,
    out_dir=out_dir,
    resolution=512,
    max_frames=50,
)

print(f"Kept {len(selected_frames)} frames – directory now contains only these files.")

Executing this snippet performs the complete cleanup contract automatically: it creates out_dir if missing, deletes pre-existing frame_*.jpg files, writes new keyframes, removes near-duplicates, and finally retains only the evenly-sampled set.

Supporting Cleanup in Other Modules

While frames.py handles the core image cleanup, the cleanup contract extends to other components:

Summary

  • Pre-extraction purge: Deletes existing frame_*.jpg files before processing begins (frames.py:596–599)
  • Deduplication cleanup: Physically removes near-duplicate frames identified by dedupe_perceptual (frames.py:500–505)
  • Sampling cleanup: Unlinks rejected candidates after _even_sample selects the final distribution (frames.py:404–410)
  • Orchestrated cleanup: The extract_keyframes helper and watch.py entry point ensure temporary files never persist between runs
  • Cross-module hygiene: Download and transcription modules implement similar cleanup patterns for their respective temporary files

Frequently Asked Questions

What happens if a video processing job is interrupted midway?

The next run automatically triggers the pre-extraction purge (lines 596–599), which deletes any frame_*.jpg files in the output directory before new extraction begins. This ensures no orphaned frames from failed runs contaminate subsequent processing.

Why does the cleanup delete files during deduplication rather than just marking them as skipped?

The dedupe_perceptual function uses Path(cand["path"]).unlink() (lines 500–505) to immediately delete near-duplicate frames. This aggressive approach prevents disk space exhaustion when processing long videos that might generate hundreds of temporary frames before the final selection.

How does the even-sampling algorithm decide which frames to delete?

The _even_sample function creates a keep_paths set containing only the selected frame paths. It then iterates through all candidates and calls unlink() on any path not present in that set (lines 404–410), ensuring only the evenly-distributed final selection remains physically on disk.

Are there any temporary files that persist after processing completes?

No. According to the source code in bradautomates/claude-video, the design guarantees that only the final, selected frames remain in the working directory. All temporary files created during intermediate stages—including duplicates and rejected candidates—are explicitly deleted before the function returns.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →