Agents can read, but they can't watch. Give ReelQL a video link and get back one typed JSON document: scenes, speech, on-screen text, products and the emotional arc, each with its timestamp.
Paste a public link. ReelQL fetches the video, transcribes it with speaker labels, watches it 30 seconds at a time and writes one JSON document.
02
Jev judges
Jev, TypeSafe's judgment model, reads only text, so it judges a video through ReelQL's fields. Ask it typed questions, such as whether a video is on brief or brand-safe, and it answers with probabilities.
03
Your code decides
Sort, filter, route or flag on those numbers instead of parsing prose.
Running times
From link to JSON, on real runs.
Starbucks TikTok0:06 → 16 s
Wing It!above3:58 → 22 s
MKBHD LG G5 unboxing4:00 → 23 s
Phone review10:34 → 57 s
Walking tour, no speech14:05 → 65 s
What it's for
For videos where the picture matters.
ReelQL reads what's on screen: products, logos, text and what people do. Speech is in the document too, but for a video that is all talk, a transcript does the job.
Brand scouting
Spot new brands on TikTok
A grocery buyer runs tens of thousands of TikToks through ReelQL to find brands worth stocking. Count the brands in each week's results: the names that keep climbing are the shortlist. A 30-second TikTok costs 2.5 cents, and a key runs five videos at a time.
brandsproducts[].appearanceson_screen_text
Ad review
Check a cut against the brief
Does the product show up early, and does the tone fit? ReelQL turns the video into fields and Jev answers each question with a probability, so you can sort a stack of ads instead of watching each one.
key_momentsstory.toneproductstranscript
Creator vetting
See what your brand would sit next to
Before you sponsor a creator, run their recent posts. The transcript, the text on screen and what happens in each scene come back with timestamps, so you can check anything that looks off.
transcripton_screen_textscenes[].action
Skip it when
Everything is said out loud
Lectures, podcasts and most tutorials live in their audio. Their subtitles are free and tell you as much, so start there. ReelQL is worth paying for when what matters is on screen.
The output
What comes back.
An excerpt from the Wing It! run above. The full document has twelve analysis fields, the speaker-labelled transcript, the video's metadata and per-step timing.
1A character gets a name only when the title, channel, on-screen text or transcript gives one. Otherwise ReelQL writes a label, such as "Grey Cat", because models make names up.
2Every time is in seconds from the start of the video.
3brand and advertiser are null when nothing in the video supports them.
4Emotions come from a fixed list of 21, so you can compare arcs across videos. Intensity runs from 1 to 5.
5It reads the text on screen, down to the license in the end credits.
The skill's bundled script sends ReelQL's fields to Jev with five questions per video and sorts on the answers. With both keys set, ask Claude to rank some ads.
The briefFamily-friendly ad that shows the product in use
#
Video · advertiser
On brief
Hook
Product
Payoff
Unsafe
1
samsungSamsung
58%
0.32
0.65
0.55
1%
2
psgGoogle
55%
0.28
0.59
0.03
2%
3
fifaworldcupLay's
28%
0.56
0.29
0.98
2%
4
starbucksStarbucks
21%
0.83
0.09
0.12
2%
5
natgeonatgeo
4%
0.49
0.01
0.01
1%
Output of scripts/jev.py on the five TikToks in examples/ (jev-1.13.0, 2026-09-25). Jev's scores vary a little from run to run. Jev is made by TypeSafe; ReelQL is not affiliated with them.
The same in your code
Python · typesafe_sdk
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
a = video["analysis"] # a ReelQL result
brief = "Upbeat, family-friendly, shows the product in use"
state = {"summary": a["summary"], "tone": a["story"]["tone"], "brands": a["brands"],
"moments": {str(i): m["what"] for i, m in enumerate(a["key_moments"])},
"transcript": " ".join(s["text"] for s in video["speech"]["transcript"])}
with TypeSafeClient() as jev: # reads TYPESAFE_API_KEY
r = jev.system_one(state=state, questions={
"unsafe": Noul(instructions="Does `transcript` contain profanity, violence or adult content?"),
"on_brief": Noul(instructions={"brief": brief, "question": "Does the video match `brief`?"}),
"fit": Score(instructions={"brief": brief, "question": "How well does `tone` fit `brief`?"},
criteria=["Contradicts it", "Neutral", "Clearly fits"]),
"best": Choice(instructions={"brief": brief, "question": "Which of `moments` best matches `brief`?"},
criteria={**{k: Nonefor k in state["moments"]}, "none": None}),
})
print(r.nouls["unsafe"].noul, r.nouls["on_brief"].noul, r.scores["fit"].score, r.choices["best"].choice)
Other things to build
Recipe
ReelQL fields in
Jev question out
Brand safety
transcript, on_screen_text, scenes[].action
One yes/no per hazard, plus a severity score
On-brief check
summary, story.tone, story.themes, advertiser
"Matches the brief?" and a fit score
Cut-down picker
key_moments, scenes
Which moment best matches the brief
Rank a batch
The same fields for many videos
Hook, product clarity and payoff scores, then sort in code
Verify placements
products[].appearances, transcript
Is each product claim supported by the evidence?
Send Jev only the fields a question needs: a long video's transcript can exceed its context. Do numeric comparisons, like views and likes, in code.
Get started
Get a key, then paste a link.
For your agent
Terminal
claude plugin marketplace add tomascupr/reelql
claude plugin install reelql@reelql
export REELQL_API_KEY=<your key>
export TYPESAFE_API_KEY=<your Jev key># optional: rankings and judgments
"Analyze this video <url>" gets you a short brief. You can also ask something specific, like "when does the product first appear?" Jev keys come from console.typesafe.ai.
On Team and Enterprise plans: download reelql.zip, upload it under Settings → Capabilities → Skills, and paste your key when Claude asks.
An organization owner first has to add reelql.tail6c0e2d.ts.net to the domains code execution may reach. On Pro and Max the sandbox reaches only package registries, so use Claude Code there.
Works from any agent that can make HTTP requests. A key without a browser: curl -s -X POST https://reelql.tail6c0e2d.ts.net/keys. GET /openapi.json describes the API, including the paid endpoint for MPP clients.
Box office
A key comes with 10 free minutes of video, without an account or a card.
or use a key you have
Your key
Copy it now. ReelQL keeps only a hash of it, so a lost key can't be recovered.
For Claude Code or curl:
Minutes left
…
Account
…
Pricing
Five cents a minute.
You pay for the length of each video from prepaid credit. There is no subscription and no invoice.
Admit one
$0.05
Minute of video
10Minutes free
Every new key starts with 10 free minutes.
A job costs the video's length, rounded up to the second and taken from your credit when it starts. A job that fails costs nothing. GET /balance shows the minutes left.
Top up $5 to $500 in whole dollars; $5 buys 100 minutes. People pay on a Stripe page, and Stripe adds VAT or sales tax where it applies.
Agents can pay for themselves.POST /credits speaks MPP, the Machine Payments Protocol: it answers 402 with a payment challenge, and an agent with an MPP wallet pays and retries.
The fine print
Any public video that yt-dlp can fetch (YouTube, TikTok, Vimeo and many more), or a direct link to a media file. Nothing behind a login, and no live streams.
Up to 30 minutes and 4 GB per video.
Five jobs queued or running per key. Results are kept for a day.
When many jobs are waiting, a new one gets 503 with Retry-After. A queued job's status shows its place in the queue.
ReelQL runs on a single GPU server, with no uptime promise. Jobs survive a restart of the service.
ReelQL keeps the fetched video and the result on its server. Don't send anything you aren't allowed to share.
The analysis runs on open models on our own GPUs, with no third-party AI APIs.