Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.tlq5l/agentic-video

PYPI · AGENTIC-VIDEO

Local video tools for AI agents: contact sheets, transcripts, cuts, loudness and sync checks.

Available components

77 Trust /100

Last scanned (7 hours ago)

Scores higher than 75% of PyPI servers

Category Design and Media

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
  • 2 of 29 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to tlq5l/agentic-video). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 3 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability58
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 11897 tokens (~475/item across 25 items; 25 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management17
  • Stability observed for 5 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage98
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 93% of tool parameters carry a description.Partial
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 25 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 25 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities20
  • Spec-recency check failed: implements MCP spec 2024-11-05; the latest is 2026-07-28. See how to fix → Fail
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 5 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

  • 3 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

  • 1 Nov 26 +16
    • Tool safety: pass → unverified ▼ security
    • Malware scan: unverified → pass ▲ security
    • Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. security
    • Capabilities: fail → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • Stability: unverified → 0.03 ▲ functional
    • First check of Schema quality: unverified functional
    • Package version: 0.3.3 → 0.3.4 functional
  • 31 Oct 26 59

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 5 Nov 2026 · Analysed pypi/agentic-video@0.3.4

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem pypi
Reason Verified
Discovered via Registry attestation endpoint
Source repo tlq5l/agentic-video
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/tlq5l/agentic-video/.github/workflows/publish.yml@refs/tags/v0.3.4
Rekor log index 3625917787
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:03d3bcae49d5ee20178039cff910853b6488e6bf95bb7936db753489a57db467

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted hatchling.build

Background: Why install scripts are a supply-chain risk →

Dependencies 29 packages
Packages resolved 29
Stale 1
No linked repository 1
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 25 exposed · ~11,897 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
audio_onsets ~547

List non-speech sound attacks (hits, claps, beats) with millisecond timestamps and five-band energy profiles, optionally restricted to a frequency band (band_hz: sub, low_mid, mid, high, air, or [low_hz, high_hz]) and compared with another source (compare_to). min_strength 0-1 (default 0.12): raise it for only strong onsets. min_gap_sec (default 0.035 s) merges onsets within that gap of a group's first onset into one onset at the first time with the group's strongest strength; 0 keeps every raw onset. At most 500 onsets are listed; `total` is the full count and the result says how to see the rest. Needs an audio track (probe_video has_audio); audio-only files (.m4a, .mp3, .wav) work. For level over time use loudness_timeline; for speech use transcribe. To name what a sound is, use label_sounds (cloud).

NameTypeReqDescription
band_hz––Restrict to a named band (sub, low_mid, mid, high, air) or a [low_hz, high_hz] range.
compare_tostring–Path or video URL of another media file whose in-band energy is compared at each onset.
end_secnumber|string–Optional exclusive end in seconds; omit to analyze to the end. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
min_gap_secnumber|string–Onsets closer than this many seconds to a group's first onset are merged into it: the group keeps the first onset's time and the strongest strength. 0 keeps every raw onset (default 0.035). Also acce…
min_strengthnumber–Onset strength cutoff 0-1 (default 0.12). Raise it to keep only stronger onsets.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Optional inclusive start in seconds; omit to analyze from the beginning. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
band_hz–––
compare_min_delta_dbnumber|null––
compare_tostring|null––
end_secnumber––
hop_samplesinteger––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
merged_countinteger–How many detected onsets were merged into a neighbouring onset by min_gap_sec.
min_strengthnumber––
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
onsetsarray––
onsets_omittedinteger–How many onsets entries were left out of the list.
retry_after_secondsinteger––
sample_rateinteger––
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
time_resolution_msnumber––
totalinteger––

No examples provided.

build_visual_index ~143

Start or poll construction of the local visual frame index that search_visual needs. Call it once, then repeat the same call (or search_visual, which reports status=index_required or partial) until the status is complete; frames are processed in bounded chunks. count_occurrences, contact_sheet and the inspect tools do not need the index.

NameTypeReqDescription
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…

Structured output declared, but exposes no named fields.

No examples provided.

check_frame_cadence ~348

Find stretches where the picture updates less often than the file's frame rate, e.g. a 30 fps capture padded to 60 fps so every frame is doubled (judder). It decodes every frame at 160x90 grey and calls a frame a repeat when it is near-identical to the one before; a range is a stretch of at least 0.5 s where repeats fill at least a quarter of every half second while other frames still change. Each range gives start_sec, end_sec, frames, duplicate_frames and effective_fps (unique frames per second; compare with frame_rate). Runs of repeats longer than 0.5 s are holds (still shots, title cards, stalls) and are not ranges; held_frames counts them (use detect_cuts and the frozen-picture check in `python -m src.loop check` for those). It does not judge whether a range is intended: a 24 fps film in a 60 fps file is one range covering the whole file, and a slow, smooth pan can look like repeats. Look at a range with inspect_window to see what moves there. At most 500 ranges are listed; `total` is the full count. Reads the whole file: about 1 s per 700 frames of 1080p; there are no range arguments.

NameTypeReqDescription
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
NameTypeReqDescription
frame_ratenumber–Frame rate in frames per second (the stream's r_frame_rate; a variable-rate file is decoded at it, gaps filled with copies).
framesinteger–Frames decoded.
held_framesinteger–Frames inside holds (runs of repeats longer than 0.5 s), left out of the ranges.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: omitted items or an ignored unknown argument.
rangesarray––
ranges_omittedinteger–How many ranges entries were left out of the list.
retry_after_secondsinteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
totalinteger–Number of ranges found.

No examples provided.

contact_sheet ~301

Get ONE grid image of evenly spaced frames, with burned timestamp badges, across the whole video or a start_sec/end_sec range: the cheapest way to see what a video contains before searching. Default 12 samples, at most 150 (larger values are clamped and the result says so). Use it to survey; use search_visual to find a specific thing, overview_chunks to survey a long video as ordered sheets, and inspect_window or inspect_windows for dense consecutive frames of a short span.

NameTypeReqDescription
colsinteger–Grid columns (default 4).
end_secnumber|string–Optional exclusive end of the overview range in absolute video seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
samplesinteger–Requested number of thumbnails; values above 150 are accepted and clamped to 150.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Optional inclusive start of the overview range in absolute video seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
colsinteger––
end_secnumber––
file_pathstring––
frame_heightinteger––
frame_widthinteger––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring––
retry_after_secondsinteger––
rowsinteger––
sample_countinteger––
samples_clamped_frominteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
timestampsarray––
tool_fileobject––

No examples provided.

count_occurrences ~1,189

Count how many separate times a specific symbol/object or exact on-screen text appears. Use for questions like 'how many separate times does the yellow outlined circle appear (ignore other colours)', 'how many times does the exact word RELEASE appear (not RELEASED)', 'how many times does the green diamond cross the screen'. Give `description` (colour and shape words are enforced, so look-alikes in another colour or shape do not count) and/or `text` (whole-word match by offline OCR). Returns `count` plus one span per continuous appearance (start_sec, end_sec, representative_sec, region, travel, weak); gaps of min_gap_sec or more separate spans. Verify a span with inspect_window at its representative_sec. Not for periodic reps or cycles (use count_repetitions) and not for locating one moment (use search_visual, which ranks frames, is capped at top_k 20 and cannot count). No visual index needed. Repeat the same call while status=in_progress. Lists at most max_spans spans (default 20, maximum 100; larger values are clamped and the result says so); `count` includes any omitted. If 100 or more spans match, the description is too broad: `count` is null, `capped` is true and `spans_found` says how many matched, so narrow the description or window and rerun instead of reporting a number. A min_gap_sec above 0.3 can join separate appearances; then `gaps_merged` is set, and `count_without_merges` too when no `direction` is passed (with a direction, rerun with the default min_gap_sec to see the separate appearances). The count is a rough first pass: it can merge separate appearances that are split by a scene cut, split one appearance into many spans, and count appearances rather than crossings; `direction` (e.g. left_to_right) narrows the count to appearances that travel that way, plus spans too brief to show motion (travel unknown), which count under any direction: check those with inspect_window. The result also carries `contact_sheet`, one labeled image with a tile per list…

NameTypeReqDescription
case_sensitiveboolean–Require the same letter case for `text`.
descriptionstring–Visible thing to count, e.g. 'yellow outlined circle', 'green diamond', 'red star'. Name its colour and shape; text on screen goes in `text`.
directionstring–Count the appearances whose net motion across the frame is this way, e.g. left_to_right for 'how many times did it cross left to right'. Motion is estimated from each span's first and last positions,…
end_secnumber|string|null–Defaults to the end of the video. At most 2400 frames are analyzed per call, so fps is lowered automatically on long windows. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
fpsnumber–Sampling rate, default 5. Appearances shorter than 1/fps can be missed; raise it for brief flashes. Larger values than 15 are clamped to 15 and the result says so.
max_spansinteger–Maximum spans listed (default 20, maximum 100; larger values are clamped to 100 and the result says so). `count` always includes every span.
min_gap_secnumber|string–Absence of at least this long starts a new span; shorter dropouts stay inside one span. Raising it above the default 0.3 JOINS separate appearances whose gap is shorter than it (0.8 merges appearance…
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Seconds, or a timecode string in MM:SS.mmm form, e.g. 00:14.250.
textstring–Exact on-screen phrase, matched as whole words (RELEASE matches 'RELEASE' and 'RELEASE NOTES', not 'RELEASED' or 'PRE-RELEASE').
NameTypeReqDescription
cappedboolean–True when 100 or more spans matched: the description is too broad and count is null.
checksobject––
contact_sheetobject|null–One image (file_path, tool_file) with a labeled tile per listed span, in span order, up to 24: a zoomed frame of the span's best detection with the match boxed. `labels` lists the tile labels, e.g. '…
countinteger|null–Number of separate appearances. When `direction` was passed: those travelling that way plus spans too brief to show motion (travel unknown), which count under any direction; check those with inspect_…
count_without_mergesinteger–The count if those joined pairs were kept apart. Set only when no direction was passed; with a direction, rerun with the default min_gap_sec instead.
fps_usednumber––
frames_analyzedinteger––
frames_sampledinteger––
gaps_mergedinteger–Appearance pairs joined because min_gap_sec is above the default 0.3; only set when it joined some.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
messagestring––
notestring––
retry_after_secondsnumber––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
spansarray––
spans_foundinteger–How many spans matched; only set when capped.
spans_omittedinteger––
spans_returnedinteger––
statusstring––
travel_countsobject–Net motion of moving appearances across the frame, by direction (left_to_right, right_to_left, top_to_bottom, bottom_to_top); only set when some move. Each value is an estimate from a span's first an…
verifystring––
windowobject––

No examples provided.

count_repetitions ~670

Count completed cycles of a repeated visual action (jumps, claps, bounces, swings) inside one window of at most 180 seconds. Give `region` (fractions of the frame: x, y, w, h) to isolate the moving thing. Repeat the same call while status=in_progress; verify peak badges and ambiguous edges with inspect_window. For separate appearances of a specific symbol or exact on-screen text use count_occurrences; to locate one moment use search_visual. For a longer clip call once per window, cutting at pauses between cycles so none straddles an edge. The count is a rough first pass and can be far off on real footage. Before answering, count cycles by eye with inspect_window or contact_sheet over the window; if your count differs, trust your own.

NameTypeReqDescription
action_hintstring–Short phrase naming the action being counted, e.g. 'jumping jacks'.
end_secnumber|string|null–End of the window in seconds; defaults to the end of the video. Give both bounds for a video longer than 180 s. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
fpsnumber–Sampling rate, default 10. Larger values than 15 are clamped to 15 and the result says so.
max_period_secnumber|string–Longest expected cycle in seconds (default 3); must exceed min_period_sec. Bounds the amplitude counter only; the periodicity check ignores it. Also accepts a timecode string in MM:SS.mmm form, e.g.…
methodstring–auto (default) picks between motion, embedding and a periodicity check; motion or embedding forces that amplitude counter alone.
min_period_secnumber|string–Shortest expected cycle in seconds (default 0.4). Bounds the amplitude counter only; the periodicity check ignores it and searches from 0.25 s. Also accepts a timecode string in MM:SS.mmm form, e.g.…
region––Rectangle that contains the repeating motion, as fractions of the frame: x, y (top-left) and w, h (size), with x+w <= 1 and y+h <= 1. Uses w/h; width/height with the same meaning is also accepted. Fo…
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Start of the window in seconds (default 0). The window may be at most 180 s long. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
confidencenumber––
contact_sheetobject|null––
countinteger––
cyclesarray––
embedding_countinteger|null––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
median_period_secnumber|null––
messagestring––
method_usedstring––
motion_countinteger––
notestring––
period_secnumber|null––
periodic_countinteger|null––
regularitynumber––
retry_after_secondsnumber––
signal_qualitystring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––

No examples provided.

detect_cuts ~442

List scene changes (timestamp_sec, score, kind) in the whole video or a start_sec/end_sec range. Hard cuts and animated changes (fades, dissolves, slides, wipes, zooms) are both returned; `kind` tells them apart: "cut" or "transition". A transition's timestamp is its middle. Scores of the two kinds are not comparable. threshold 0-1 (default 0.25) applies to hard cuts only: raise it to keep only stronger cuts. A hard cut between two similar pictures is found by a second check and listed as a cut with a score below the default threshold; any threshold above 0.25 leaves these out. A change that is over within about 4 frames (a very fast wipe) is listed as a cut, and a few similar-picture cuts still come back as a transition. Film footage with heavy motion can still give false transitions; check a doubtful one with inspect_moments. At most 500 cuts are listed; `total` is the full count and the result says how to see the rest. Use it to segment a video into shots or find edit points; use audio_onsets for sounds and sync_check to compare both.

NameTypeReqDescription
end_secnumber|string–Optional exclusive end of the cut-search range in absolute video seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Optional inclusive start of the cut-search range in absolute video seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
thresholdnumber–Cut strength cutoff 0-1 (default 0.25). Raise it to keep only stronger cuts.
NameTypeReqDescription
cutsarray––
cuts_omittedinteger–How many cuts entries were left out of the list.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
totalinteger––

No examples provided.

frame_at ~516

Use this when you need one exact frame at full size, or a crop to read small text; for many frames use inspect_window or contact_sheet. Returns one PNG of the frame shown at time_sec, at the source's native resolution, with no timestamp drawn on it. An optional crop (x, y, width, height in source pixels) cuts a rectangle out of that frame, and scale (1 to 4, default 1) enlarges the crop with Lanczos so small text is easier to read. frame_time_sec is the start time of the frame actually decoded: the last frame starting at or before time_sec, so on variable-frame-rate video it can be well before time_sec. A repeat call with the same source, time_sec, crop and scale returns the saved file. With read_text true it also returns the on-screen text read from that frame (Apple Vision, macOS only).

NameTypeReqDescription
cropobject–Optional rectangle in source pixels: x and y (top-left corner, >= 0) and width and height (>= 1). It must lie inside the frame as displayed (rotation applied): x + width <= source width and y + heigh…
read_textboolean–Also read the on-screen text in each returned frame with Apple Vision OCR (macOS only). Each frame then lists text_lines: the text, confidence and box (x, y, width, height; 0 to 1, top-left origin) o…
scalenumber–Enlargement of the (cropped) frame, 1 to 4. The default 1 leaves the pixels as they are. Use 2 to 4 to read small text.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
time_secnumber|stringyesMoment in seconds, from 0 to the media duration. Returns the frame shown at that moment. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
cropobject|null–The crop applied, in source pixels; null when no crop was given.
file_pathstring–The PNG on disk; open this for the full-size pixels.
frame_time_secnumber|null–Start time of the frame shown at time_sec, from the decoder; it can be earlier than time_sec. Null when the decoder reports no time.
heightinteger–Height of the saved PNG in pixels (the crop height times scale).
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
scalenumber–The enlargement applied (1 when none was asked for).
source_heightinteger–Height of the source video as displayed (rotation applied), in pixels.
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
source_widthinteger–Width of the source video as displayed (rotation applied), in pixels.
statusstring––
text_linesarray–Lines of on-screen text read from this frame by Apple Vision, top to bottom then left to right. Present only when read_text was true. An empty list means OCR found no text in the frame.
text_lines_notestring–Present when the frame had more than 40 text lines: lists the first 40 and says how many there were.
tool_fileobject––
widthinteger–Width of the saved PNG in pixels (the crop width times scale).

No examples provided.

inspect_moments ~425

Look closely around specific instants: for each moment (timestamp_sec, optional label) returns a contact sheet of frames before, at and after it (default 4 s before and 4 s after, samples_per_moment 9). Use it to verify a hit from search_visual, search_transcript, detect_cuts, audio_onsets or track_region_changes. At most 16 moments per call and max_total_samples frames in all (default 144, maximum 400); a call over budget fails and says what to lower. For one continuous span of frames use inspect_window.

NameTypeReqDescription
after_secnumber|string–Seconds of context after each moment (default 4). Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
before_secnumber|string–Seconds of context before each moment (default 4). Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
colsinteger––
max_momentsinteger–Most moments accepted (default and maximum 16; larger values are clamped).
max_total_samplesinteger–Frame budget: moments x samples_per_moment must not exceed it (default 144, maximum 400; larger values are clamped).
momentsarrayyesInstants to inspect, e.g. [{"timestamp_sec": 12.5, "label": "door opens"}], at most 16, each within the video.
samples_per_momentinteger–Frames per moment, an odd number 3-25 (default 9; larger values are clamped to 25).
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
NameTypeReqDescription
estimated_vision_tokensinteger––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_moments_clamped_fromnumber–The value you requested for max_moments before it was lowered to its cap.
max_total_samples_clamped_fromnumber–The value you requested for max_total_samples before it was lowered to its cap.
momentsarray––
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
samples_per_moment_clamped_fromnumber–The value you requested for samples_per_moment before it was lowered to its cap.
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
totalinteger––
total_samplesinteger––

No examples provided.

inspect_window ~428

Dense consecutive frames of ONE short window [start_sec, end_sec] (both required) with timestamp overlays, as a contact sheet plus frame list. Default 4 fps, maximum 30 (larger values are clamped). At most about 150 frames and 600 seconds per call: frames = fps x duration, so a 10 s window allows at most 15 fps; a call over budget fails and says the fps that fits. Use it to verify a moment or a count. For a wide overview use contact_sheet; for several ranges use inspect_windows. With read_text true each frame also lists the on-screen text read from it (Apple Vision, macOS only).

NameTypeReqDescription
end_secnumber|stringyesEnd of the window in seconds; must be within the video. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
fpsnumber–Sampling rate (default 4, maximum 30; larger values are clamped). Frames = fps x duration and must stay within about 150.
read_textboolean–Also read the on-screen text in each returned frame with Apple Vision OCR (macOS only). Each frame then lists text_lines: the text, confidence and box (x, y, width, height; 0 to 1, top-left origin) o…
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|stringyesStart of the window in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
contact_sheet_pathstring|null––
end_secnumber––
estimated_vision_tokensinteger––
fpsnumber––
fps_clamped_fromnumber–The value you requested for fps before it was lowered to its cap.
framesarray––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
tool_fileobject––

No examples provided.

inspect_windows ~353

Dense consecutive frames (default 4 fps) for several time ranges in one call, with optional context_sec padding and merging of overlapping windows. At most 16 windows and max_total_frames frames in all (default 150, maximum 500); a call over budget fails and says to lower fps or shorten the windows. For one range use inspect_window, for a coarse survey use contact_sheet, for frames around single instants use inspect_moments.

NameTypeReqDescription
context_secnumber|string–Seconds of padding added to each side of every window (default 0). Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
fpsnumber–Sampling rate (default 4, maximum 30; larger values are clamped).
max_total_framesinteger–Frame budget for all windows together (default 150, maximum 500; larger values are clamped). Lower fps or shorten the windows to fit.
max_windowsinteger–Most windows accepted (default and maximum 16; larger values are clamped).
merge_overlapsboolean–Merge overlapping windows into one (default true).
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
windowsarrayyesTime ranges to inspect, e.g. [{"start_sec": 10, "end_sec": 14}], at most 16, each within the video.
NameTypeReqDescription
estimated_vision_tokensinteger––
fps_clamped_fromnumber–The value you requested for fps before it was lowered to its cap.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_total_frames_clamped_fromnumber–The value you requested for max_total_frames before it was lowered to its cap.
max_windows_clamped_fromnumber–The value you requested for max_windows before it was lowered to its cap.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
totalinteger––
total_framesinteger––
windowsarray––

No examples provided.

label_sounds ~596

Name the sounds in a stretch of a video's audio: cuts [start_sec, end_sec] (both required) into windows of window_sec (default 5 s, at most 60 windows per call) and returns, per window, the chance of each label plus none_chance, from a cloud model (Clef-omni on Cloudflare Workers AI). THIS SENDS THE AUDIO TO CLOUDFLARE: never use it on personal recordings. The server needs CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN (or AGENTIC_VIDEO_CF_TOKEN_COMMAND, a command that prints the token) and the call fails with a message naming what is missing. `labels` (default: 20 common sounds such as dog barking, siren, glass breaking, church bells) is the closed list to choose from, so a sound outside the list is forced onto the nearest label or none: list every sound that may be present. Steady musical chords can be named church bells, so treat top_chance under 0.5 as weak and check a hit with spectrogram_window. top_label is null when none_chance beats every label. It does not search: find candidate times with audio_onsets or loudness_timeline first, then label those ranges. For speech use transcribe or search_transcript. Needs an audio track. No window starts after about 40 s and the call answers within about 50 s: a longer range returns the windows finished in time with complete=false and next_start_sec to continue from.

NameTypeReqDescription
end_secnumber|stringyesEnd of the range in seconds; at least 1 s after start_sec, and the range may hold at most 60 windows. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
labelsarray–Sound names to choose from, e.g. ["dog barking", "siren"] (at most 50, distinct). Default: 20 common sounds.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|stringyesStart of the range in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
window_secnumber|string–Length of each labelled window in seconds (default 5, from 1 to 30). The last window may be shorter; a remainder under 1 s is not labelled. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:1…
NameTypeReqDescription
completeboolean–false when the call stopped early (the time limit or a failed window); the windows returned are the finished ones in order.
end_secnumber––
input_tokensinteger––
labelsarray––
local_pathstring––
modelstring––
next_start_secnumber|null–Where to start the next call so the unfinished windows are covered; null when complete.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsnumber––
source_pathstring––
source_urlstring––
start_secnumber––
statusstring––
window_secnumber––
windowsarray––

No examples provided.

loudness_timeline ~533

Measure loudness over time: RMS, peak, band energies, spectral centroid, silence gaps, and band-energy outliers classified as steps, ramps or transients, in fixed windows (window_sec 0.01-600, default 0.25) or beat-length windows (bpm 20-300; give one or the other). At most 500 windows are listed in `windows` (`total` is the full count; `outliers` and `silence_gaps` always cover the whole range); use a larger window_sec or a start_sec/end_sec range for the rest. Ranges needing over 50,000 windows are rejected with the window_sec that fits. Needs an audio track (audio-only files work too). For discrete hits use audio_onsets. `peak_dbfs` (top level, with `peak_sec`, and per window) is the loudest sample on any channel, as ffmpeg reports sample peak; `rms_dbfs` and `band_db` are measured on the mono mix (L+R)/1.414, so on centred stereo they read up to 3 dB above a per-channel meter.

NameTypeReqDescription
bpmnumber–Use one-beat windows at this tempo, 20-300. Give this or window_sec, not both.
end_secnumber|string–Optional exclusive end in seconds; omit to analyze to the end. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
ignore_rangesarray–Ranges with a reason (e.g. an intentional silence) that are excluded from outlier detection.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Optional inclusive start in seconds; omit to analyze from the beginning. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
window_secnumber|string–Fixed window length in seconds, 0.01-600 (default 0.25). Larger values than 600 are clamped to 600. Give this or bpm, not both. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
bpmnumber|null––
end_secnumber––
ignore_rangesarray––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
outliersarray––
peak_dbfsnumber–Loudest sample on any channel in the range (sample peak, as ffmpeg astats/ebur128 report it).
peak_secnumber–Time of that loudest sample.
retry_after_secondsinteger––
silence_gapsarray––
silence_threshold_dbfsnumber––
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
totalinteger––
window_secnumber––
window_sec_clamped_fromnumber–The value you requested for window_sec before it was lowered to its cap.
windowsarray––
windows_omittedinteger–How many windows entries were left out of the list.

No examples provided.

overview_chunks ~392

Survey a long video as consecutive contact sheets, one per chunk_sec (default 60 s), so every stretch is covered in order. At most max_chunks sheets per call (default and maximum 32): for a longer video raise chunk_sec or page through it with start_sec/end_sec; a call over budget fails and says what chunk_sec would fit. samples_per_chunk defaults to 8 (maximum 150, larger values are clamped). Use contact_sheet instead when one sheet is enough.

NameTypeReqDescription
chunk_secnumber|string–Seconds covered by each sheet (default 60, maximum 600). Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
colsinteger––
end_secnumber|string–Optional exclusive end in absolute video seconds; defaults to the end of the video. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
max_chunksinteger–Most sheets in one call (default and maximum 32; larger values are clamped). The call fails if the range needs more chunks: raise chunk_sec or narrow the range.
samples_per_chunkinteger–Thumbnails per sheet (default 8; values above 150 are clamped to 150 and the result says so).
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Optional inclusive start in absolute video seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
chunk_secnumber––
chunksarray––
end_secnumber––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_chunks_clamped_fromnumber–The value you requested for max_chunks before it was lowered to its cap.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
samples_per_chunk_clamped_fromnumber–The value you requested for samples_per_chunk before it was lowered to its cap.
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
totalinteger––

No examples provided.

probe_video ~283

Read a video's duration, frame rate, resolution, codecs, and whether it has an audio track and a video track. Call this first: duration_sec bounds every start_sec/end_sec you pass to other tools. Audio-only files (.m4a, .mp3, .wav) are accepted: has_video is false and width, height and fps are 0. has_audio tells you whether transcribe, search_transcript and the audio tools (audio_onsets, loudness_timeline, spectrogram_window) can work; the visual tools and sync_check need has_video true. `source` is a local file path or a video URL and is the same in every tool: an x.com / Twitter post with a video, a YouTube link, another site yt-dlp supports, or a direct .mp4 link. A URL is downloaded once (up to 1080p) and cached; the result gives source_url and local_path, and while the download runs it is status=in_progress, so call again.

NameTypeReqDescription
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
NameTypeReqDescription
audio_codecstring|null––
duration_secnumber––
fingerprintstring––
format_namestring––
fpsnumber––
has_audioboolean––
has_videoboolean–False for audio-only files: width, height and fps are 0, and the visual tools refuse the file.
heightinteger––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
size_bytesinteger––
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
video_codecstring|null––
widthinteger––

No examples provided.

refine_temporal_beam ~399

Zoom into candidate time windows: splits each window into `fanout` contiguous child ranges and returns one timestamped contact sheet per child, without ranking relevance. Use it after contact_sheet or search_visual has narrowed the answer to a few windows and you want to localize inside them; use inspect_windows for dense consecutive frames instead. Budget: windows x fanout x samples_per_child must be at most max_total_samples (default 96, maximum 300); a call over budget fails and says which of the three to lower.

NameTypeReqDescription
align_to_cutsboolean––
colsinteger––
compact_parent_sheetboolean––
context_secnumber|string–Seconds of padding added to each side of every window (default 0). Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
fanoutinteger–Child ranges per window (default 4, maximum 8; larger values are clamped and the result says so).
max_total_samplesinteger–Frame budget: windows x fanout x samples_per_child must not exceed it (default 96, maximum 300; larger values are clamped and the result says so).
samples_per_childinteger–Thumbnails per child range (default 3, maximum 12; larger values are clamped and the result says so).
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
windowsarrayyesAbsolute time ranges to zoom into, e.g. [{"start_sec": 10, "end_sec": 40}], each within the video.
NameTypeReqDescription
estimated_vision_tokensinteger––
fanout_clamped_fromnumber–The value you requested for fanout before it was lowered to its cap.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_total_samples_clamped_fromnumber–The value you requested for max_total_samples before it was lowered to its cap.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
parentsarray––
retry_after_secondsinteger––
samples_per_child_clamped_fromnumber–The value you requested for samples_per_child before it was lowered to its cap.
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
total_samplesinteger––

No examples provided.

review_video ~374

First look at a video in ONE call: container metadata (duration, size, fps, codecs, has_audio), a contact sheet image with burned timestamp badges (default 24 samples; `samples` up to 150, larger values are clamped and the result says so), every cut and transition from detect_cuts, every near-black stretch of at least 0.2 s (`black_ranges`: start, end and duration; at most 50 are listed and `black_total` counts them all), and a loudness summary (average and peak level, silence gaps, the strongest band-energy outliers with their times). It runs probe_video, contact_sheet, detect_cuts, the black scan and loudness_timeline for you, so start here instead of calling them one by one. A first call on a 10-minute 1080p clip takes about 35 s (the cuts scan and the black scan share one decode of the file); repeat calls on the same file return from cache. `loudness` is null when the video has no audio track. Use the times it returns to zoom in with inspect_window or spectrogram_window; for a different threshold, window or time range call detect_cuts or loudness_timeline directly. Any step failing fails the whole call with that step's error message.

NameTypeReqDescription
samplesinteger–Contact sheet thumbnails (default 24; values above 150 are clamped to 150 and the result says so).
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
NameTypeReqDescription
black_rangesarray–Stretches of at least 0.2 s where the picture is near-black, in time order. At most 50 are listed; black_total is the full count.
black_ranges_omittedinteger–How many black_ranges entries were left out of the list.
black_totalinteger–How many near-black stretches were found in all.
contact_sheetobject–Same fields as contact_sheet: file_path, sample_count, rows, cols, start_sec, end_sec, timestamps, frame_width, frame_height, tool_file (the image), and samples_clamped_from when samples was lowered.
cutsarray––
cuts_omittedinteger–How many cuts entries were left out of the list.
cuts_totalinteger–How many cuts and transitions were found in all.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
loudnessobject|null–Null when the video has no audio track.
metadataobject–Same fields as probe_video: source_path, duration_sec, width, height, fps, format_name, size_bytes, has_audio, has_video, audio_codec, video_codec, fingerprint.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––

No examples provided.

search_transcript ~449

Find when a word or phrase is SPOKEN. Audio-only files (.m4a, .mp3, .wav) work too. Default mode=hybrid lists exact keyword matches first (match=exact: the phrase; match=all_terms: every content word in one segment), then passages that match by meaning (match=semantic: a 20 s window, found on this Mac with EmbeddingGemma 2; nothing is sent to the cloud), so a reworded question still finds the moment. mode=lexical gives keyword matches only. When no hit is exact or all_terms, the words were not found in the speech: semantic hits are the closest passages, not proof, so read their text before answering. If semantic search is not set up or not ready, hits are keyword-only and `note` says why. Returns up to top_k timestamped hits (default 5, maximum 50; larger values are clamped and the result says so; `note` says when more keyword matches exist). For text shown on screen use count_occurrences, and for visible things use search_visual. If ASR is needed, starts or joins background transcription and returns status=in_progress with retry_after_seconds instead of waiting; repeat the same call after that delay. A hit on a flagged line carries `suspect` (see transcribe).

NameTypeReqDescription
modestring–hybrid (default): keyword matches first, then matches by meaning. lexical: keyword matches only. For example: "mode": "lexical".
querystringyesWords or a phrase to find in the speech, e.g. 'launch date'. Punctuation and case are ignored.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
top_kinteger–Maximum hits (default 5, maximum 50; larger values are clamped to 50 and the result says so).
NameTypeReqDescription
cached_model_sizestring––
elapsed_secinteger–While status=in_progress: seconds since the background transcription started.
estimated_percentinteger–While status=in_progress: elapsed / estimated total, capped at 99. An estimate, not a measurement.
estimated_total_secinteger–While status=in_progress: rough estimate of the whole run, from the audio length and model speed.
hitsarray––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
model_substitutionstring–Only when the requested model is not installed: names the installed model used instead.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
requested_model_cachedboolean––
requested_model_sizestring––
retry_after_secondsinteger––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
top_k_clamped_fromnumber–The value you requested for top_k before it was lowered to its cap.
totalinteger––
transcription_messagestring––
transcription_statusstring––

No examples provided.

search_visual ~504

Find WHEN something visible happens: an object, person, action or scene (semantic match between the query and sampled frames). It matches meaning, not letters, so it cannot find on-screen words or numbers (names, scores, jersey or bib numbers): find those with count_occurrences `text`, which reads text in frames, one window of up to 2400 s per call. Returns up to top_k ranked frame hits (default 5, maximum 20; larger values are clamped and the result says so), merged intervals (the one holding rank 1 grows from its best frames only over neighbouring frames that score close to the best, up to 8 seconds, so it can be shorter; a span already longer than 8 seconds, such as a held frame or hits merged together, is kept whole, so it can be longer and can include lower-scoring hits; intervals that overlap it are merged into it), and a contact sheet to verify them. It ranks frames, so it cannot count: to count separate appearances of a symbol or exact on-screen text use count_occurrences, for a repeated action use count_repetitions, for spoken words use search_transcript. Build the local visual index first (build_visual_index), then repeat the same query to poll until complete. Use start_sec/end_sec to search one range at a time.

NameTypeReqDescription
end_secnumber|string|null–Exclusive end of the range to search, in seconds; defaults to the end of the video. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
querystringyesNatural-language description of visible content.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|string–Inclusive start of the range to search, in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
top_kinteger–Maximum frame hits (default 5, maximum 20; larger values are clamped to 20 and the result says so). This ranks frames and cannot count: use count_occurrences for counts.

Structured output declared, but exposes no named fields.

No examples provided.

spectrogram_window ~281

Render a log-frequency dB spectrogram PNG for [start_sec, end_sec] (both required, at most 600 s) with absolute timecode badges and optional event marks (time_sec + label). Use a short window (a few seconds) to look at one sound; find candidate times with audio_onsets or loudness_timeline first. Needs an audio track (audio-only files work too).

NameTypeReqDescription
end_secnumber|stringyesEnd of the window in seconds; the window may be at most 600 s long. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
marksarray–Optional event markers drawn on the image, e.g. [{"time_sec": 12.5, "label": "kick"}].
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|stringyesStart of the window in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
end_secnumber––
file_pathstring––
frequency_ticksarray––
heightinteger––
hop_samplesinteger––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
marksarray––
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
sample_rateinteger––
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
timecode_badgesarray––
tool_fileobject––
widthinteger––

No examples provided.

sync_check ~377

Check audio/video sync: compares visual cuts with measured audio onsets, and optionally with intended sound cues (time_sec, label, optional band_hz), within tolerance_ms (0-5000, default 80). Returns per-cut and per-cue matches and unmatched strong onsets (the cuts and unmatched_strong_onsets lists show at most 500 items each; the cues list is never cut short; total_cuts and total_cues are the full counts). Each cue reports candidate_onsets_count, the number of onsets near it; verbose true reports that cue's candidate_onsets list instead of the count. Needs an audio track. To look at the two signals separately use detect_cuts and audio_onsets.

NameTypeReqDescription
bpmnumber–Tempo of the music, 20-300. Compares each cue with uncued moments at the same beat phase, so steady backing percussion does not hide a missing sound.
cuesarray–Intended sound cues to check, e.g. [{"time_sec": 12.5, "label": "hit"}]. Omit to compare cuts with onsets only.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
tolerance_msnumber–Match window in milliseconds (default 80, maximum 5000; larger values are clamped).
verboseboolean–false (default) gives each cue candidate_onsets_count; true gives each cue candidate_onsets (the onsets near it with time_sec, offset_ms and strength) instead of the count.
NameTypeReqDescription
beats_per_barinteger|null–Beats per bar used with bpm; null without bpm.
bpmnumber|null–The tempo passed in, or null.
cue_recovery_window_msnumber––
cue_signaturesobject–Learned sound signature for each cue group, keyed by group name.
cuesarray––
cutsarray––
cuts_omittedinteger–How many cuts entries were left out of the list.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
retry_after_secondsinteger––
search_window_msnumber–The window used to pair cues with onsets, in ms.
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
strong_onset_thresholdnumber––
systematic_lagsarray––
tolerance_msnumber––
tolerance_ms_clamped_fromnumber–The value you requested for tolerance_ms before it was lowered to its cap.
total_cuesinteger––
total_cutsinteger––
uncued_soundsarray–Strong sounds with no cue, found from a cue group's repeated sound.
unmatched_strong_onsetsarray––
unmatched_strong_onsets_omittedinteger–How many unmatched_strong_onsets entries were left out of the list.

No examples provided.

track_region_changes ~629

Watch one fixed rectangle of the frame (region: x, y, width, height as fractions 0-1) from start_sec to end_sec (both required) and rank the moments its pixels change most, as candidates to verify with inspect_moments or inspect_window. Use for a scoreboard, counter, indicator light or door. Slow continuous motion ranks no candidates: read steady_change.detected for that. Returns ranked candidates, not a count: for a bounded count of state transitions use track_region_events. Budget: about (end_sec - start_sec) x sample_fps frames, at most max_total_frames (default 600, maximum 2000); a call over budget fails and says the sample_fps that fits. This tool's region uses width/height (count_repetitions uses w/h).

NameTypeReqDescription
end_secnumber|stringyesEnd of the range in seconds; must be within the video. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
frame_widthinteger–Decoded frame width in pixels (default 640, maximum 1920; larger values are clamped).
max_candidatesinteger–Most candidates returned (default 32, maximum 128; larger values are clamped). Raise min_change_score to keep only stronger ones.
max_total_framesinteger–Frame budget for the whole range (default 600, maximum 2000; larger values are clamped). The call fails when (end_sec - start_sec) x sample_fps exceeds it.
min_change_scorenumber––
min_separation_secnumber|string–Seconds, or a timecode string in MM:SS.mmm form, e.g. 00:14.250.
region–yesRectangle to watch, as fractions of the frame: x, y (top-left) and width, height, with x+width <= 1 and y+height <= 1. Uses width/height, not w/h; w/h with the same meaning is also accepted. For exam…
robust_sigmanumber––
sample_fpsnumber–Sampling rate (default 0.25, maximum 10; larger values are clamped and the result says so). Changes shorter than 1/sample_fps can be missed.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|stringyesStart of the range in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
baseline_madnumber––
baseline_mediannumber––
candidatesarray––
end_secnumber––
frame_width_clamped_fromnumber–The value you requested for frame_width before it was lowered to its cap.
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_candidates_clamped_fromnumber–The value you requested for max_candidates before it was lowered to its cap.
max_total_frames_clamped_fromnumber–The value you requested for max_total_frames before it was lowered to its cap.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
regionobject––
retry_after_secondsinteger––
sample_countinteger––
sample_fpsnumber––
sample_fps_clamped_fromnumber–The value you requested for sample_fps before it was lowered to its cap.
samplesarray––
scan_segmentsarray––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
steady_changeobject––
temporal_resolution_secnumber––
thresholdnumber––

No examples provided.

track_region_events ~634

Count discrete state changes (transitions) inside one fixed rectangle of the frame (region: x, y, width, height as fractions 0-1) between start_sec and end_sec (both required). Returns event_count plus before/after evidence moments to verify. Use for 'how many times did the light turn on' or 'how often does the counter change'. For ranked change candidates without a count use track_region_changes; for a periodic action use count_repetitions; for a symbol appearing anywhere on screen use count_occurrences. Budget: about (end_sec - start_sec) x sample_fps frames, at most max_total_frames (default 600, maximum 2000); a call over budget fails and says the sample_fps that fits. This tool's region uses width/height (count_repetitions uses w/h).

NameTypeReqDescription
ambiguity_marginnumber––
change_thresholdnumber––
end_secnumber|stringyesEnd of the range in seconds; must be within the video. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
frame_widthinteger–Decoded frame width in pixels (default 640, maximum 1920; larger values are clamped).
max_eventsinteger–Most events returned (default 32, maximum 128; larger values are clamped). Raise change_threshold to keep only stronger ones.
max_total_framesinteger–Frame budget for the whole range (default 600, maximum 2000; larger values are clamped). The call fails when (end_sec - start_sec) x sample_fps exceeds it.
min_separation_secnumber|string–Seconds, or a timecode string in MM:SS.mmm form, e.g. 00:14.250.
region–yesRectangle to watch, as fractions of the frame: x, y (top-left) and width, height, with x+width <= 1 and y+height <= 1. Uses width/height, not w/h; w/h with the same meaning is also accepted. For exam…
sample_fpsnumber–Sampling rate (default 0.25, maximum 10; larger values are clamped and the result says so). Transitions shorter than 1/sample_fps can be missed.
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
start_secnumber|stringyesStart of the range in seconds. Also accepts a timecode string in MM:SS.mmm form, e.g. 00:14.250.
NameTypeReqDescription
end_secnumber––
event_countinteger|null––
frame_width_clamped_fromnumber–The value you requested for frame_width before it was lowered to its cap.
incompleteboolean––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
max_events_clamped_fromnumber–The value you requested for max_events before it was lowered to its cap.
max_total_frames_clamped_fromnumber–The value you requested for max_total_frames before it was lowered to its cap.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
regionobject––
retry_after_secondsinteger––
sample_countinteger––
sample_fpsnumber––
sample_fps_clamped_fromnumber–The value you requested for sample_fps before it was lowered to its cap.
scan_segmentsarray––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
start_secnumber––
statusstring––
temporal_resolution_secnumber––
transitionsarray––
uncertainboolean––
uncertainty_reasonstring|null––

No examples provided.

transcribe ~320

Get the full speech transcript as timestamped segments (cached after the first run). Audio-only files (.m4a, .mp3, .wav) work too. To find where a specific word or phrase is spoken, use search_transcript instead of reading it all. If the requested model is not cached, returns another cached transcript with cached_model_size and requested_model_cached=false while one background job runs; with no transcript cached, returns status=in_progress and retry_after_seconds, so repeat the same call after that delay. model_size: tiny, base or small (more accurate, slower on the CPU), or turbo (Whisper large-v3-turbo on the GPU via whisper.cpp: the most accurate and, where installed, the fastest, about 1 minute per hour of audio). Omit model_size to get turbo where it is installed, else tiny. Long audio is decoded in 60-second chunks. Lines repeated 3 or more times in a row carry `suspect` and `notice` names them: speech models often invent such lines over music or silence, though a real chant can repeat too. A line without `suspect` is not verified.

NameTypeReqDescription
model_sizestring––
sourcestringyesLocal video file path, or a video URL (X/Twitter post, YouTube link, other sites yt-dlp supports, direct .mp4 link). A URL is downloaded once and cached; while it downloads the result is status=in_pr…
NameTypeReqDescription
cached_model_sizestring––
confidencenumber|null––
duration_secnumber––
elapsed_secinteger–While status=in_progress: seconds since the background transcription started.
estimated_percentinteger–While status=in_progress: elapsed / estimated total, capped at 99. An estimate, not a measurement.
estimated_total_secinteger–While status=in_progress: rough estimate of the whole run, from the audio length and model speed.
has_speechboolean––
languagestring––
local_pathstring–Cached local copy of `source_url`; pass it to other tools or ffmpeg to skip the URL lookup.
model_substitutionstring–Only when the requested model is not installed: names the installed model used instead.
notestring–Plain-English remark about the call: a capped argument, omitted items, or an ignored unknown argument.
noticestring––
requested_model_cachedboolean––
requested_model_sizestring––
retry_after_secondsinteger––
segment_countinteger––
segmentsarray––
segments_omittedinteger–Only with transcript_path: how many segments are left out of `segments`.
source_pathstring––
source_urlstring–The video URL you passed as `source`; only present when `source` was a URL.
statusstring––
transcript_pathstring–Only when the transcript was too long to list in full: path of a JSON file with every segment.
transcription_messagestring––
transcription_statusstring––
uncertaintystring––

No examples provided.

Install

How do I install the io.github.tlq5l/agentic-video MCP server?

io.github.tlq5l/agentic-video runs locally as a PyPI package, launched with uvx agentic-video. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · agentic-video

# add to Claude Code
claude mcp add tlq5l-agentic-video -- uvx agentic-video
Common questions

What is the io.github.tlq5l/agentic-video MCP server?

io.github.tlq5l/agentic-video is an MCP server listed in the public MCP registry as io.github.tlq5l/agentic-video. Local video tools for AI agents: contact sheets, transcripts, cuts, loudness and sync checks. This page covers its PyPI package (agentic-video).

Is the io.github.tlq5l/agentic-video MCP server safe to use?

io.github.tlq5l/agentic-video scores 77 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.tlq5l/agentic-video MCP server expose?

io.github.tlq5l/agentic-video exposes 25 tools: count_repetitions, count_occurrences, probe_video, transcribe, search_transcript, and 20 more. Their descriptions and schemas cost roughly 11,897 tokens of context every time the server is loaded.

Is the io.github.tlq5l/agentic-video MCP server still maintained?

io.github.tlq5l/agentic-video is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the io.github.tlq5l/agentic-video MCP server under?

io.github.tlq5l/agentic-video declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.