# How to Filter Video Transcripts by Time Range in Claude Video

> Learn how to filter video transcripts by time range in Claude Video. Discover the overlap-based algorithm that efficiently selects caption segments within your specified window.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: how-to-guide
- Published: 2026-07-31

---

**The Claude Video repository filters transcripts by time range using an overlap-based algorithm in `filter_range()` that keeps any caption segment whose time interval intersects with the user-specified window, defaulting to infinity bounds when arguments are omitted.**

Transcript filtering for specific time ranges allows developers to isolate dialogue from precise moments in a video without processing the entire caption file. In the `bradautomates/claude-video` repository, this functionality is implemented in the **watch** skill, which processes YouTube WebVTT captions or Whisper-generated subtitles and prunes them to match user-defined `--start` and `--end` boundaries before analysis.

## Understanding the Filter Range Implementation

The core filtering logic resides in [`skills/watch/scripts/transcribe.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/transcribe.py) within the `filter_range` function (lines 70‑81). This utility determines whether a caption segment's time interval overlaps with the requested window, ensuring no partially visible dialogue is excluded.

### Parsing WebVTT Segments

Before filtering, the `parse_vtt` function reads subtitle files and normalizes them into a structured format. Each cue is converted to a dictionary containing start time, end time, and cleaned text:

```python
{"start": <seconds>, "end": <seconds>, "text": "<cue text>"}

```

This standardization allows `filter_range` to perform mathematical comparisons regardless of the original caption source, whether from YouTube's auto-generated VTT or local Whisper transcription.

### The Overlap Algorithm

The `filter_range` function accepts a list of segments and two optional boundaries (`start_seconds` and `end_seconds`). When either boundary is `None`, the function substitutes negative or positive infinity to create an unbounded range. The implementation checks for temporal overlap using the condition: a segment is kept if its **end** is greater than or equal to the lower bound **and** its **start** is less than or equal to the upper bound.

```python
def filter_range(
    segments: list[dict],
    start_seconds: float | None,
    end_seconds: float | None,
) -> list[dict]:
    """Return segments whose time range overlaps [start, end]."""
    if start_seconds is None and end_seconds is None:
        return segments
    lo = start_seconds if start_seconds is not None else float("-inf")
    hi = end_seconds if end_seconds is not None else float("inf")
    return [seg for seg in segments if seg["end"] >= lo and seg["start"] <= hi]

```

This logic captures segments that start before the window but end inside it, as well as segments that start inside but extend beyond the boundary. According to the source code in [`transcribe.py`](https://github.com/bradautomates/claude-video/blob/main/transcribe.py), this approach mirrors how subtitles appear on screen—if any portion is visible during the requested time range, the text is considered relevant.

## Integration in the Watch Command

The filtering is invoked from [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) after the CLI parses `--start` and `--end` arguments into seconds using `parse_time`. When a transcript exists (for example, from cached YouTube captions), the script applies the filter before formatting the output for display:

```python
if transcript_segments and focused:
    transcript_segments = filter_range(transcript_segments, start_sec, end_sec)

```

This call appears around line 163 in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py). The repository reuses this same filtering step across multiple fallback paths, including post-processing after Whisper transcription (lines 328‑334) and secondary caption parsing passes, ensuring consistent behavior regardless of how the transcript was generated.

## Edge Cases and Validation

The implementation handles several boundary conditions through pre-validation and default value logic:

- **No bounds specified**: Returns the original list unchanged when both `start_seconds` and `end_seconds` are `None`
- **Only start time provided**: Keeps segments where `end >= start_seconds`, effectively returning everything after the specified timestamp
- **Only end time provided**: Keeps segments where `start <= end_seconds`, returning everything before the specified timestamp
- **Invalid range**: The CLI aborts early if `--start` is greater than or equal to `--end` with an explicit error message
- **Out-of-bounds values**: The watch command validates timestamps against video duration and exits if `--start` exceeds the video length

## Practical Implementation Example

Developers can leverage the filtering logic directly without invoking the full CLI pipeline. The following snippet demonstrates parsing a WebVTT file, applying a time window, and rendering the filtered transcript:

```python
from pathlib import Path
from skills.watch.scripts.transcribe import parse_vtt, filter_range, format_transcript

# Parse a WebVTT file produced by yt-dlp

segments = parse_vtt(Path("my_video.en.vtt"))

# Define a time window (30 seconds to 90 seconds)

start_sec = 30.0
end_sec = 90.0

# Filter the transcript to that window

filtered = filter_range(segments, start_sec, end_sec)

# Render a readable transcript

print(format_transcript(filtered))

```

This pattern is useful for batch processing videos or integrating transcript filtering into custom analysis pipelines outside the standard watch command workflow.

## Summary

- The `filter_range` function in [`skills/watch/scripts/transcribe.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/transcribe.py) (lines 70‑81) implements overlap-based filtering that retains any segment intersecting with the requested time window.
- Segments are represented as dictionaries with `start`, `end`, and `text` keys after parsing by `parse_vtt`.
- The overlap condition `seg["end"] >= lo and seg["start"] <= hi` ensures partially visible captions are included in the filtered results.
- The watch command in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) invokes this filter at line 163 after parsing CLI arguments, applying it consistently across YouTube captions and Whisper transcriptions.
- Invalid time ranges and out-of-bounds timestamps are caught during CLI argument validation before filtering occurs.

## Frequently Asked Questions

### How does the overlap logic handle captions that start before the time range but end inside it?

The algorithm includes these segments because it checks if `seg["end"] >= lo` (the lower bound). If a caption starts at 25 seconds and ends at 35 seconds, and the user requests a range starting at 30 seconds, the segment is retained because 35 is greater than 30, satisfying the overlap condition even though the start time precedes the window.

### Can I use transcript filtering without downloading a YouTube video?

Yes. The `filter_range` function operates on the list of segment dictionaries returned by `parse_vtt`. As long as you have a WebVTT file from any source—whether generated by Whisper, downloaded via yt-dlp, or created manually—you can parse it with `parse_vtt` and apply the same filtering logic without requiring YouTube-specific metadata or API calls.

### What happens if I provide only a start time without an end time?

When `end_seconds` is `None`, the function substitutes `float("inf")` as the upper bound. This means `filter_range` will keep every segment where `seg["start"] <= infinity` (which is always true) and `seg["end"] >= start_seconds`. The result includes all captions from the specified start time through the end of the video.

### Why does the CLI validate time ranges against video duration before filtering?

The validation in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) prevents logical errors and unnecessary processing. If the user specifies a `--start` timestamp that equals or exceeds the total video length, the command aborts early because no valid transcript segments could exist in that range. This check occurs before invoking `filter_range`, saving the overhead of parsing or downloading caption files for impossible time windows.