Video transcription
One transcribe() function that returns the spoken words of a video on YouTube, TikTok, Instagram, Facebook, X, Reddit or LinkedIn. 30 credits on YouTube, 100 on the others.
You will build one transcribe(url) function that returns what was said in a social video, whichever of seven platforms it lives on. Every transcript endpoint answers in the same shape, so the only platform-specific part is choosing the endpoint.
Cost per run
30 credits for a YouTube video, 100 credits for a video on any of the other six platforms. You make exactly one call per video. A video with no captions or no speech is not charged. Transcribing the same URL again is charged again, so store the transcript.
How do you turn a social video into text?
Pass the video URL to that platform's transcript endpoint. Each one returns the spoken content as text. Transcripts are the densest signal in social video: captions and thumbnails are written to get the click, while the spoken words are what the creator actually said.
What you need
| Endpoint | Covers | Credits |
|---|---|---|
GET /v1/youtube/video/transcript | YouTube videos and Shorts | 30 |
GET /v1/tiktok/post/transcript | TikTok videos | 100 |
GET /v1/instagram/media/transcript | Instagram reels and videos up to 2 minutes | 100 |
GET /v1/facebook/post/transcript | Facebook video posts | 100 |
GET /v1/twitter/tweet/transcript | Videos attached to X posts | 100 |
GET /v1/reddit/post/transcript | Reddit video posts | 100 |
GET /v1/linkedin/post/transcript | Videos in LinkedIn posts | 100 |
Every one takes a url parameter.
When there is nothing to transcribe
- YouTube, Instagram and LinkedIn answer
404when a video has no captions or no speech, and name the reason (for exampleno_captionsorno_speech). That is an expected outcome, not a failure, and it is not charged. - Reddit answers with a transcript whose
textisnullwhen Reddit publishes no captions for the video, and liststranscript.textinunavailable. - TikTok reads the video's captions. Add
use_ai_as_fallback=trueto fall back to AI transcription when there are none.
One shape on every platform
Every transcript endpoint returns data.transcript with three fields:
text: the whole transcript as one string, ornullwhen there is none.language: the language tag the platform gives, such asen, ornull.segments: timed cues, each{ text, start_seconds, duration_seconds }, ornullwhen the platform has no timings. YouTube has them; most of the others return the text only.
See Transcript for the full schema.
The code
# transcribe.py
# Returns the transcript of a social video URL on any of seven platforms.
# Run with: INSIGHTSOCIAL_API_KEY=isk_live_... python transcribe.py
import os
from urllib.parse import urlparse
import requests
KEY = os.environ["INSIGHTSOCIAL_API_KEY"]
BASE = "https://api.insightsocial.app/v1"
ENDPOINT = {
"youtube": "youtube/video/transcript",
"tiktok": "tiktok/post/transcript",
"instagram": "instagram/media/transcript",
"facebook": "facebook/post/transcript",
"twitter": "twitter/tweet/transcript",
"reddit": "reddit/post/transcript",
"linkedin": "linkedin/post/transcript",
}
HOSTS = {"youtube.com": "youtube", "youtu.be": "youtube", "tiktok.com": "tiktok",
"instagram.com": "instagram", "facebook.com": "facebook", "fb.watch": "facebook",
"x.com": "twitter", "twitter.com": "twitter", "reddit.com": "reddit",
"v.redd.it": "reddit", "linkedin.com": "linkedin"}
def platform_of(url):
host = urlparse(url).netloc.lower().removeprefix("www.").removeprefix("m.")
for suffix, platform in HOSTS.items():
if host == suffix or host.endswith("." + suffix):
return platform
raise ValueError(f"unsupported host: {host}")
def extract_text(data):
# The same on all seven platforms. `text` is null when there is no transcript.
return data["transcript"]["text"] or ""
def transcribe(url):
platform = platform_of(url)
res = requests.get(f"{BASE}/{ENDPOINT[platform]}", params={"url": url},
headers={"x-api-key": KEY}, timeout=120)
body = res.json()
if not body["success"]:
# A 404 here usually means "no captions" or "no speech", and costs nothing.
return {"platform": platform, "text": None, "error": body["error"]["type"],
"credits_used": body["credits_used"]}
return {"platform": platform, "text": extract_text(body["data"]),
"language": body["data"]["transcript"]["language"],
"segments": body["data"]["transcript"]["segments"],
"credits_used": body["credits_used"]}
# Any public video URL on the seven platforms works; add your own to the list.
for url in [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
]:
t = transcribe(url)
if t["text"] is None:
print(f"[{t['platform']}] no transcript ({t['error']}), {t['credits_used']} credits")
else:
print(f"[{t['platform']}] {len(t['text'])} chars, {t['credits_used']} credits")
print(t["text"][:200], "...")What you get back
{
"success": true,
"platform": "youtube",
"endpoint": "/v1/youtube/video/transcript",
"schema_version": "2",
"data": {
"transcript": {
"language": "en",
"text": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ...",
"segments": [
{ "text": "[♪♪♪]", "start_seconds": 1.36, "duration_seconds": 1.68 },
{ "text": "♪ We're no strangers to love ♪", "start_seconds": 18.64, "duration_seconds": 3.24 }
]
}
},
"unavailable": [],
"credits_used": 30,
"credits_remaining": 9940,
"request_id": "req_1a2b3c4d5e6f",
"cached": false,
"idempotent_replay": false,
"charge_reason": "miss",
"free_call": false
}On another platform the same call returns the same keys. Where the platform has no timings, segments is null and text carries the whole transcript.
What to change
- Cheaper YouTube. If you can parse caption files yourself,
GET /v1/youtube/video/subtitles(10 credits, beta) returns the caption tracks with download URLs instead. - Find a moment instead of reading everything. Where
segmentsis filled, search it for a phrase and readstart_secondsto jump to that point in the video, for example to find a discount code or a sponsor mention. - Pick a language. YouTube, TikTok and Reddit take
language, a two-letter code. - Ads too.
GET /v1/facebook/adlibrary/ad/transcript(100 credits) returns what a Facebook Ad Library video ad says out loud. Pass the adidor its library URL.
Related
Search then enrich
Find the posts about a topic on TikTok and Instagram, collect the accounts that made them, and fetch each account's full profile into one lead list. From 120 credits per run.
Ad library aggregation
Pull the ads a brand is running on Meta, LinkedIn and TikTok in one parallel fan-out and flatten them into one table. 150 to 270 credits per brand.