How to Filter Video Transcripts by Time Range in Claude Video
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 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:
{"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.
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, 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 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:
if transcript_segments and focused:
transcript_segments = filter_range(transcript_segments, start_sec, end_sec)
This call appears around line 163 in 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_secondsandend_secondsareNone - 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
--startis greater than or equal to--endwith an explicit error message - Out-of-bounds values: The watch command validates timestamps against video duration and exits if
--startexceeds 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:
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_rangefunction inskills/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, andtextkeys after parsing byparse_vtt. - The overlap condition
seg["end"] >= lo and seg["start"] <= hiensures partially visible captions are included in the filtered results. - The watch command in
skills/watch/scripts/watch.pyinvokes 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →