ReelQL

SkillFiles & storage

Analyze any video link (YouTube, TikTok, Vimeo, media file): story, brands, products, emotional arc, key moments, transcript. Use whenever the user shares a video URL.

Use ReelQL in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add ReelQL and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the ReelQL skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

What this skill tells your AI

The instructions your AI receives, as published by tomascupr/reelql in skills/reelql/SKILL.md and read by Ahel’s review.

ReelQL turns a video URL into one JSON document. It needs the environment variable REELQL_API_KEY, a personal key that anyone can get for free with 10 minutes of video. The scripts check their own keys; when one is missing they print how to get it. Pass that on to the user as it is and wait for the key. Never inspect REELQL_API_KEY or TYPESAFE_API_KEY yourself (no echo, printenv, env, cat .env, not even to test that one is set), and never write a key into a file or command line.

Run videos

Run the script in this skill's directory, in the foreground (it finishes in a minute or two), from a scratch directory:

bash <this skill's directory>/scripts/reelql.sh "<url>" ["<url>" ...]

It saves each result as reelql-1.json, reelql-2.json, ... in URL order, five videos at a time, and prints done or failed with the reason for each one. A 4-minute video takes about 25 s, a 15-minute one about a minute. It needs curl and jq.

A result is large: the transcript alone can be tens of kB. Read only the parts you need with jq, for example:

jq '.result.analysis | {summary, advertiser, brands, products, emotional_arc, key_moments, on_screen_text}' reelql-1.json
jq '.result.video | {title, channel, platform, duration_s, stats}' reelql-1.json
jq -r '.result.speech.transcript[] | "[\(.start)] \(.speaker): \(.text)"' reelql-1.json

Credit

Each video costs its length, at $0.05 a minute, from the key's prepaid credit. When a video is refused with 402 (no credit left, or the video is longer than the credit), tell the user and offer a payment link:

bash <this skill's directory>/scripts/reelql.sh --topup <dollars, 5 to 500>

It prints a Stripe payment page for the user to open in a browser ($5 buys 100 minutes) and the minutes left. Never pay yourself, and don't pick an amount the user hasn't agreed to.

What to tell the user

If the user asked something specific ("who is the advertiser?", "when does the logo appear?"), answer just that from the fields that hold it, with timestamps.

If they only shared a link or said "analyze this", give this brief, in this order, and skip any part the video has nothing for:

  1. What it is: one sentence, with the platform, channel and length.
  2. Who's selling what: the advertiser, and each product with the time it first appears.
  3. The story: the premise and how it unfolds, in 2-3 sentences.
  4. How it should feel: the emotional arc as a chain (curiosity → anticipation → excitement), with the moment behind each shift.
  5. Key moments: at most 5 lines, formatted as m:ss then what happens.
  6. On-screen text worth knowing (dates, prices, calls to action), and the views and likes if the platform reports them.

Keep it under about 20 lines. Then suggest one next step that fits the video, in a sentence:

  • An ad or a sponsored post: rank it against their brief with Jev, or check it for brand safety (below).
  • A social video with products or brands on screen: offer to run more links they send (the creator's other posts, a hashtag, a competitor) and list the brands and products that keep appearing.
  • Mostly talk (a lecture, a podcast, a tutorial): say that the transcript carries it, and offer the transcript or a summary of what was said.

Or offer a follow-up about this video that the data can answer: the full transcript, scene by scene, the cast.

How many of the videos each brand appears in, most first:

jq -r '.result.analysis | [(.brands // [])[], ((.products // [])[] | .brand // empty)] | unique[]' reelql-*.json | sort | uniq -c | sort -rn

Judge or rank videos with Jev (optional)

If the user wants a judgment rather than a description, and TYPESAFE_API_KEY is set, use Jev (TypeSafe's judgment model). Judgments include "is this on brief?", "rank these ads", "which is safest?" and "which one should we run?".

  1. Run all the videos through scripts/reelql.sh in one call.
  2. Pass the result files to the scripts/jev.py script in this skill's directory:
uv run --with typesafe-sdk python <this skill's directory>/scripts/jev.py "<the brief, in the user's words>" reelql-*.json

It prints a table ranked by the probability that each video is on brief, with hook, product and payoff scores (0 to 1) and the probability that the content is unsafe. Show the table, then say in one or two sentences why the top video wins and what holds back the rest, using the ReelQL fields. Jev's numbers are judgments, not measurements: say so if the user is about to act on a close call. Without TYPESAFE_API_KEY, judge from the ReelQL fields yourself and say that Jev would give calibrated scores.

What the result holds

.result has schema_version, then:

  • video: title, channel, duration_s, platform, url, upload_date, description (the caption), tags, music (TikTok sound), stats (views, likes, comments, as reported at fetch time; null where the platform does not give one).
  • speech.transcript[]: {start, end, speaker, text}, speakers labelled SPEAKER_00...
  • analysis:
    • summary
    • story: premise, tone, themes, arc
    • characters[]: name_or_label, appearance, role, first_seen_s
    • audio: music, sound effects, voiceover, tone
    • advertiser, brands[], products[] (with each appearance's time and prominence)
    • chapters[]: one per 30 s, {start_s, end_s, title, summary}
    • scenes[], key_moments[]
    • emotional_arc[]: what the viewer is meant to feel, {t_s, emotion, intensity 1-5, cue}
    • on_screen_text[]

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 name_or_label is a short description ("young girl"). advertiser, brand and mood are null when nothing in the video supports them. Report these as the video's own evidence, not as verified facts.

Errors

  • 400: the URL was refused (private address, not http(s), a live stream, longer than 30 minutes, over 4 GB, or not a video). The reason is in .detail.
  • 401: missing or wrong key.
  • 402: not enough credit for this video. The reason says how many minutes it needs and how many are left; see Credit.
  • 429: the key already has 5 jobs queued or running, for example from another session. Wait and run again.
  • 503: ReelQL is busy. Wait the seconds in the Retry-After header (60) and submit again. While a job is queued, its position says how many jobs are ahead of it, counting itself.
  • 404 on a job: wrong id, older than a day, or the service restarted (jobs are kept in memory). Submit again.
  • A failed job: .error says why (for example a deleted or region-blocked post).

Signals

GitHub stars
28
Forks
1
Last commit
Sep 2026

Ahel review

  • K6low
    bundled executables the agent is told to run

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Item type
skill
Key
reelql
Source
github.com/tomascupr/reelql