# Why Claude Video Shows "No Frames Extracted": 6 Root Causes and Fixes

> Decode why Claude Video shows no frames extracted. Explore 6 common causes like transcript-only mode, audio-only downloads, and FFmpeg issues, plus learn practical fixes to resolve them.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: troubleshooting
- Published: 2026-07-26

---

**Claude Video displays "_No frames extracted._" when the processing pipeline skips frame extraction due to transcript-only mode, audio-only downloads, zero-duration metadata, aggressive deduplication, out-of-range timestamps, or missing FFmpeg binaries.**

When using the `bradautomates/claude-video` open-source tool to analyze video content, the final report occasionally contains a "_No frames extracted._" placeholder in the Frames section. This output originates from [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) when the frame extraction logic is bypassed or produces empty results. Understanding the specific conditions that trigger this state is essential for debugging video processing workflows and ensuring you receive visual analysis when needed.

## How Frame Extraction Works in Claude Video

The processing pipeline in `bradautomates/claude-video` follows a conditional path: first downloading the source media via [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py), then checking the `detail` parameter to determine whether visual analysis is required. Only when `detail` is set to `"balanced"` or `"high"` (and not `"transcript"`) does the system proceed to [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) to extract candidate frames. After extraction, frames pass through `dedupe_perceptual()` for deduplication before final inclusion in the report. If any step in this chain fails or is intentionally skipped, the script reaches line 52 of [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) and prints the default placeholder.

## Six Reasons You See "No Frames Extracted"

### 1. Transcript-Only Detail Mode

The most explicit cause occurs when you request **transcript-only output**. In [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) lines 38–40, the code checks `if detail == "transcript"` and skips the entire frame extraction block. This is the default behavior when using the `--detail transcript` flag or when the configuration in [`config.py`](https://github.com/bradautomates/claude-video/blob/main/config.py) specifies transcript mode.

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --detail transcript

```

*Result:* The report shows "_No frames extracted._" because the pipeline bypasses visual processing entirely.

### 2. Audio-Only Downloads Without Timestamps

When `detail` is set to `"transcript"` and you provide **no cue timestamps**, the script sets `audio_only = True` in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) lines 11–13. This prevents the download of video streams, leaving `video_path` as `None`. Without a valid video file path, subsequent calls to frame extraction functions are bypassed automatically.

To force a full video download in transcript mode, add explicit timestamps:

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --detail transcript \
    --timestamps "00:10,00:20"

```

### 3. Zero-Duration or Unreadable Metadata

If **FFprobe cannot determine the video duration**, `duration_seconds` becomes `0`. In [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) lines 22–26, the `auto_fps` function calculates a target of `1` frame, but the subsequent extraction receives a `max_frames` value of `0` (calculated as `fps` multiplied by `0` seconds). This results in an empty frame list before deduplication even occurs.

### 4. Complete Removal by Deduplication (Static Videos)

For **static screen recordings or slide decks**, the **perceptual deduplication** step may remove every extracted frame. In [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) lines 48–49, the function `dedupe_perceptual()` compares mean-pixel differences between frames. If the video content is essentially unchanged throughout, all candidates fall below the similarity threshold and are discarded, leaving no frames for the final report.

```bash
python -m skills.watch.scripts.watch \
    "path/to/static-screen-recording.mp4" \
    --detail balanced \
    --no-dedup   # omit this to see frames disappear

```

Without the `--no-dedup` flag, the static video produces zero frames after deduplication.

### 5. Timestamps Outside the Focus Window

Supplying **cue timestamps that fall outside your裁剪 window** causes silent frame drops. When you specify `--start` and `--end` parameters alongside `--timestamps`, [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) lines 88–94 invoke `extract_at_timestamps()`. This function drops cues outside the specified window, populating `cue_meta["dropped_out_of_window"]`. If all requested timestamps lie outside the range, the cue list empties and no frames are generated.

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --start 01:00 --end 01:30 \
    --timestamps "00:10,00:20"

```

*Result:* Both timestamps precede the 1-minute start window, so extraction produces no output.

### 6. Missing FFmpeg or FFprobe Binaries

If **FFmpeg or FFprobe is not installed** or not in your system PATH, the helper scripts abort with a `SystemExit` before writing any frames. [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) lines 86–89 contain binary validation guards that raise errors immediately if these dependencies are missing, halting execution before frame extraction begins.

## Practical Examples Reproducing the Issue

The following commands demonstrate specific scenarios that trigger the "_No frames extracted._" message:

**Transcript-only mode (intentional skip):**

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --detail transcript

```

**Audio-only with forced video download via timestamps:**

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --detail transcript \
    --timestamps "00:10,00:20"

```

**Static content losing frames to deduplication:**

```bash
python -m skills.watch.scripts.watch \
    "path/to/static-screen-recording.mp4" \
    --detail balanced

```

**Out-of-range timestamp filtering:**

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=example" \
    --start 01:00 --end 01:30 \
    --timestamps "00:10,00:20"

```

## How to Fix "No Frames Extracted" Issues

Resolve the empty frame state by addressing the specific trigger:

- **Use `--detail balanced` or `--detail high`** instead of `transcript` when you need visual analysis.
- **Add `--timestamps`** when using transcript mode to force full video downloads.
- **Verify video metadata** with `ffprobe` before processing; re-encode files with corrupted headers if necessary.
- **Append `--no-dedup`** for screen recordings or slide presentations to prevent aggressive frame removal.
- **Align timestamps** with your `--start` and `--end` window, or omit the window parameters to process the entire video.
- **Install FFmpeg and FFprobe** and ensure they are accessible in your system PATH.

## Summary

- **Transcript mode bypasses frames:** The `--detail transcript` flag explicitly skips extraction in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py).
- **Audio-only downloads lack video files:** Without timestamps in transcript mode, `video_path` remains `None`.
- **Zero duration yields zero frames:** Failed duration detection in [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py) results in `max_frames = 0`.
- **Deduplication eliminates static content:** `dedupe_perceptual()` removes frames from unchanged video segments.
- **Window constraints filter timestamps:** Out-of-range cues are dropped, potentially emptying the extraction list.
- **Missing dependencies halt execution:** Absent FFmpeg/FFprobe binaries trigger early exits in [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py).

## Frequently Asked Questions

### Why does Claude Video say "No frames extracted" when I only want a transcript?

This is expected behavior. When you specify `--detail transcript`, the code in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) lines 38–40 explicitly bypasses the frame extraction logic to optimize processing time and bandwidth. To receive both transcripts and frames, use `--detail balanced` or `--detail high`.

### Can I extract frames from a static screen recording?

Yes, but you must disable deduplication. Static videos trigger `dedupe_perceptual()` in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) lines 48–49 to remove near-duplicate frames, which often results in all frames being discarded. Add the `--no-dedup` flag to preserve frames from screen recordings and slide decks.

### How do I force frame extraction when using transcript detail mode?

Supply explicit timestamps using the `--timestamps` flag. In [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py), providing timestamps forces `audio_only` to `False`, ensuring the video file downloads and becomes available for frame extraction even when `detail` is set to `transcript`.

### What happens if FFprobe cannot read the video duration?

The `auto_fps` function in [`skills/watch/scripts/frames.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/frames.py) lines 22–26 calculates a target frame count based on `duration_seconds`. If this value is `0` or unreadable, the multiplication of `fps` by duration yields `0` frames requested, resulting in no extraction and the "_No frames extracted._" message in the final report.