reelql

agent
Security Audit
Pass
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 28 GitHub stars
Code Pass
  • Code scan — Scanned 10 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Give your agent eyes: any video link in, one typed JSON out. A Claude skill + API.

README.md

ReelQL: give your agent eyes

⭐ Star the repo (and Watch → Releases to hear about updates), and follow @tomcupr on X for launch news.

Paste any video link and get back one typed JSON document: summary, chapters, scenes, cast, key moments, the emotional arc, products and brands, on-screen text and the full transcript. ReelQL watches the video, and Jev turns what it saw into decisions your code can branch on.

Claude Code using the ReelQL skill on a Starbucks TikTok

"analyze this video" in Claude Code, on a 6-second Starbucks TikTok. Real run, played at 1.5×.

Video Length Link to JSON
Starbucks TikTok 0:06 16 s
MKBHD LG G5 unboxing 4:00 23 s
Phone review 10:34 57 s
Walking tour, no speech 14:05 65 s

No key yet? examples/ has the full output for five brand TikToks and the Jev ranking of them.

Why ReelQL + Jev

Agents can read, but they can't watch. Jev, TypeSafe's judgment model, reads text only; its docs say to turn video into text or structured fields first. ReelQL is that step:

  1. ReelQL watches. A link goes in, and one JSON document comes out with every field timestamped.
  2. Jev judges. Give Jev the fields you care about and ask typed questions: is this on brief, is it brand-safe, which moment fits best? You get probabilities back, not prose to parse.
  3. Your code decides. Sort, filter, route or flag on real numbers.

With both keys set, just ask Claude to rank some ads against a brief. The skill runs every link through ReelQL, then its bundled scripts/jev.py asks Jev five questions per video. Those are on brief, hook, product in use, emotional payoff and unsafe content:

Claude Code ranking five brand TikToks against a brief with ReelQL and Jev

Five brand TikToks ranked against "family-friendly, shows the product in use". Samsung wins at 77% because its ad is the product doing something; Nat Geo lands at 6% because it isn't an ad. Real run, played at 2.5×.

The same pairing in your own code:

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: None for 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 you can build from the same pairing:

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, emotional 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, not the whole document: a long video's transcript can exceed Jev's context. Do numeric comparisons (views, likes) in code. Jev is made by TypeSafe; ReelQL is not affiliated with them.

Get started

1. Get a key. One call, no sign-up. A new key comes with 10 free minutes of video:

curl -s -X POST https://reelql.tail6c0e2d.ts.net/keys
# {"key": "rql_...", "account": "k-...", "minutes": 10.0, ...}

2. Install the skill.

Claude Code:

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, from console.typesafe.ai: rankings and judgments with Jev

Then paste a link: "analyze this video " gets you a short brief, or ask something specific such as "when does the product first appear?"

claude.ai (Team and Enterprise): download reelql.zip, upload it under Settings → Capabilities → Skills, and paste your key when Claude asks. An organization owner must first add reelql.tail6c0e2d.ts.net to the allowed domains for code execution. On Pro and Max the sandbox only reaches package registries, so use Claude Code there.

Any other agent, or plain curl:

API=https://reelql.tail6c0e2d.ts.net; H="X-API-Key: $REELQL_API_KEY"
curl -s -H "$H" -H 'Content-Type: application/json' $API/jobs -d '{"url": "https://www.youtube.com/watch?v=..."}'
# {"id": "6b0550c3dc9f", "status": "queued"}
curl -s -H "$H" $API/jobs/6b0550c3dc9f   # queued, running, then done (with "result") or failed (with "error")

A 4-minute video takes about 25 seconds and a 15-minute one about a minute.

Pricing

$0.05 per minute of video, taken from prepaid credit when a job starts. A job that fails costs nothing. GET /balance shows the minutes left, and a job the credit can't cover gets 402.

Top up $5 to $500 in whole dollars ($5 buys 100 minutes):

  • In a browser: POST /credits/checkout {"usd": 5} returns a Stripe payment page. Stripe adds VAT or sales tax where it applies. In Claude Code, the skill makes this link for you when the credit runs out.
  • From an agent: POST /credits {"usd": 5} speaks MPP, the Machine Payments Protocol. It answers 402 with a payment challenge, and an agent with an MPP wallet pays it and sends the request again. With Stripe's Link wallet, for example: npx @stripe/link-cli mpp pay https://reelql.tail6c0e2d.ts.net/credits -X POST -d '{"usd": 5}' -H "X-API-Key: $REELQL_API_KEY". Link's agent wallet isn't available in every country yet. GET /openapi.json describes the paid endpoint for MPP clients.

What you get back

An excerpt from the Starbucks TikTok in the demo:

{
  "schema_version": "1.2",
  "video": { "title": "cat's outta the bag. see you 10.22.", "channel": "starbucks", "platform": "TikTok",
             "duration_s": 6.3, "stats": { "view_count": 12000000, "like_count": 539800 } },
  "analysis": {
    "summary": "A mysterious black cat walks across a dark marble surface, leading to the reveal of the new Starbucks Black Cat Frappuccino with whipped cream and chocolate ears, announced as available from October 22.",
    "advertiser": "Starbucks",
    "brands": ["Starbucks", "Frappuccino"],
    "products": [{ "name": "Starbucks Black Cat Frappuccino", "brand": "Starbucks", "category": "Beverage",
                   "appearances": [{ "t_s": 3.0, "prominence": "Central focus of the latter part of the video." }] }],
    "emotional_arc": [
      { "t_s": 0.0, "emotion": "curiosity",    "intensity": 3, "cue": "Mysterious appearance of the black cat" },
      { "t_s": 3.0, "emotion": "anticipation", "intensity": 4, "cue": "Reveal of the Starbucks cup" },
      { "t_s": 4.4, "emotion": "excitement",   "intensity": 3, "cue": "Announcement of the Black Cat Frappuccino" }
    ],
    "on_screen_text": [{ "t_s": 4.4, "text": "BLACK CAT FRAPPUCCINO 10.22" }]
  }
}

The full document also has story, characters, audio, chapters (one per 30 seconds), scenes, key_moments, a speaker-labelled transcript and per-step timing. The skill file, skills/reelql/SKILL.md, lists every field.

  • All times are seconds from the start of the video.
  • A person's name appears only when the title, channel, on-screen text or transcript contains it. Otherwise ReelQL uses a short label such as "young girl", because the model would otherwise make names up.
  • emotional_arc is what the viewer is meant to feel, drawn from a fixed list of 21 emotions, so arcs can be compared across videos.
  • advertiser and brand are null when nothing in the video supports them.

Limits

  • Any public video that yt-dlp can fetch (YouTube, TikTok, Vimeo and many more), or a direct link to a media file.
  • Up to 30 minutes and 4 GB per video. No live streams, and nothing behind a login.
  • 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; try again after that many seconds. A queued job's status shows its position in the queue.
  • ReelQL runs on a single GPU server, with no uptime promise. Jobs survive a restart of the service: one in progress starts over and finishes. A job id returns 404 after a day.
  • 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.

Built by @tomcupr. If ReelQL is useful to you, star the repo, tell me what you built with it on X, and send the videos it gets wrong: those are the ones that improve it.

Reviews (0)

No results found