captions
Reach for this when caption text from a YouTube video is wanted: reading a video instead of watching it, quoting or translating speech, accessibility (deaf/HoH) needs, content revi…
artemchuikin
@artemchuikin
Install
$ openclaw skills install @artemchuikin/captionsCaptions
Extract closed captions from YouTube videos via TranscriptOut.com.
Setup
If $TRANSCRIPTOUT_API_KEY is not set, read references/auth-setup.md and follow the instructions there to get and store the key.
Required Header
Every request needs one header:
- Authorization:
Bearer $TRANSCRIPTOUT_API_KEY
Every response is one JSON envelope. Success: {"ok": true, "request_id": "...", "data": {...}}. Error: {"ok": false, "code": "...", "detail": "...", "request_id": "..."}. Branch on the machine-readable code, not on the human text. The remaining credit balance rides in the X-Credits-Remaining response header.
GET /v1/transcript · 1 credit
Fetch the closed captions of any YouTube video: timed JSON segments, plain text, or ready-made SRT/VTT files.
# SRT body inside the JSON envelope
curl -s "https://api.transcriptout.com/v1/transcript?video=VIDEO_URL_OR_ID&format=srt" \
-H "Authorization: Bearer $TRANSCRIPTOUT_API_KEY"
# or the raw .srt file itself
curl -s "https://api.transcriptout.com/v1/transcript?video=VIDEO_URL_OR_ID&format=srt&download=true" \
-H "Authorization: Bearer $TRANSCRIPTOUT_API_KEY"
| Param | Required | Default | Values |
|---|---|---|---|
video | yes | - | YouTube URL (full/short/shorts) or 11-char video ID |
lang | no | en | language code of the track (en, de, ...) |
format | no | json | json, text, srt, vtt, srv3 |
kind | no | manual if present | manual, auto |
segment | no | auto tracks: 180 (80 for srt/vtt). Manual tracks keep the author's lines | 20-5000, max characters per segment |
video_metadata | no | false | true adds data.metadata (title, channel, duration, views) for the same 1 credit |
download | no | false | true returns the raw file instead of the JSON envelope (text/srt/vtt/srv3 only) |
With format=srt or format=vtt the default segmenting for auto-generated tracks is subtitle-sized (~80 characters per cue). Manual tracks keep the author's own line breaks in every format. download=true returns the bare file instead of the JSON envelope.
Response for format=json. With format=text/srt/vtt/srv3 the transcript field is one string in that format:
{
"ok": true,
"request_id": "req_...",
"data": {
"video_id": "dQw4w9WgXcQ",
"language": "en",
"kind": "manual",
"transcript": [
{ "text": "Never gonna give you up", "start": 18.0, "duration": 4.12 },
{ "text": "Never gonna let you down", "start": 22.12, "duration": 3.85 }
],
"available_langs": [
{ "code": "en", "kind": "manual", "name": "English" },
{ "code": "en", "kind": "auto", "name": "English (auto-generated)" }
]
}
}
Tips
format=textis the cheapest form to reason over. Ask forjsononly when timestamps matter.- Transcript AND title/channel wanted? One call:
video_metadata=true. Never a separate/v1/videofirst. - Transcribe last: search and listings are for choosing, and pulling transcripts for a whole results page nobody asked to read is the fastest way to burn a balance.
Errors
| Code | Meaning | Action |
|---|---|---|
| 400/422 | Bad parameter | Fix the request. Credit refunded automatically |
| 401 | Bad or missing API key | Check the key. It must start with sk_ |
| 402 | Out of credits | transcriptout.com/billing |
| 404 | No captions on that language/track, or bad ID | Definitive answer, do not retry. Try another lang or kind=auto. Billed |
| 410 | Video removed | Do not retry |
| 451 | Age-restricted or members-only | Do not retry |
| 429 | Rate limit (200 req/min per key) | Wait, respect Retry-After. Refunded |
| 502 | Failed on YouTube's side | One retry is reasonable. Billed |
| 503 | Service at capacity | Retry after Retry-After. Refunded |
Every error body carries a machine-readable code and a request_id. Include the request_id when contacting support.
Top skills in this category
Nano Banana Pro
@steipeteGenerate/edit images with Nano Banana Pro (Gemini 3 Pro Image). Use for image create/modify requests incl. edits. Supports text-to-image + image-to-image; 1K/2K/4K; use --input-image.
AdMapix
@fly0pantsAdMapix raw data layer for ad creatives, apps, rankings, downloads/revenue, and market metadata. Returns structured JSON from the AdMapix API; the calling ag...
YouTube Watcher
@michaelgatharaFetch and read transcripts from YouTube videos. Use when you need to summarize a video, answer questions about its content, or extract information from it.
SuperDesign
@mpociotExpert frontend design guidelines for creating beautiful, modern UIs. Use when building landing pages, dashboards, or any user interface.
Video Frames
@steipeteExtract frames or short clips from videos using ffmpeg.