Short Video Transcriber - TikTok, Reels & Shorts to Text, SRT avatar

Short Video Transcriber - TikTok, Reels & Shorts to Text, SRT

Pricing

from $1.70 / 1,000 transcript from native captions

Go to Apify Store
Short Video Transcriber - TikTok, Reels & Shorts to Text, SRT

Short Video Transcriber - TikTok, Reels & Shorts to Text, SRT

Transcribe TikTok videos and YouTube Shorts to text, timestamped segments, SRT and VTT. Uses each platform's native captions when they exist and falls back to Whisper speech-to-text when they don't. No API key, no cookies.

Pricing

from $1.70 / 1,000 transcript from native captions

Rating

0.0

(0)

Developer

Saulius Saulenas

Saulius Saulenas

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Short Video Transcriber — TikTok, Reels & Shorts to Text, SRT

TikTok and YouTube Shorts to transcript, SRT and VTT. Native captions when they exist, Whisper when they don't.

Paste short-form video URLs, get back the words. Every video comes back as plain text, timestamped segments, a ready-to-use .srt subtitle file, a .vtt file, and the basic source metadata — author, caption, hashtags, duration, language.

The Actor reads each platform's own caption track first and only runs Whisper speech-to-text on videos that have none. That is why it is fast, and why videos with captions cost a fraction of what a transcribe-everything tool charges.

  • No API key, no login, no cookies.
  • 90+ languages. The transcript comes back in the video's own language by default.
  • Bulk-safe. One dead link never breaks the rest of the run.
  • You only pay for delivered transcripts. Failures, private videos and over-length videos are free.

Supported platforms

PlatformVideo URLsNative captionsWhisper fallback
TikToktiktok.com/@user/video/123…, vm.tiktok.com/… share links✅ creator captions and TikTok's own auto-captions
YouTube Shortsyoutube.com/shorts/ID, youtu.be/ID, youtube.com/watch?v=ID✅ creator captions and YouTube auto-captions
Instagram Reels

Instagram Reels URLs are recognised and rejected with a clear message. Reels support ships as its own Actor; this one does not pretend to handle it.


What you get

One dataset row per video:

{
"url": "https://www.youtube.com/shorts/BDf5mOfSkkw",
"platform": "youtube_shorts",
"videoId": "BDf5mOfSkkw",
"author": "UCUvUKGDBCqJzV4OwJkQWCHg",
"authorName": "King Arthur Baking Company",
"title": "The Only Sourdough Recipe You'll Ever Need",
"hashtags": ["baking", "sourdough"],
"durationSeconds": 15.0,
"language": "en",
"source": "native_captions",
"text": "I'm going to show you how to make the only sourdough bread that you need to know…",
"segments": [
{ "start": 0.0, "end": 1.14, "text": "I'm going to show you how to make the" },
{ "start": 1.14, "end": 2.46, "text": "only sourdough bread that you need to" }
],
"srt": "1\n00:00:00,000 --> 00:00:01,140\nI'm going to show you how to make the\n\n2\n…",
"vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:01.140\nI'm going to show you how to make the\n\n…",
"wordCount": 62,
"segmentCount": 9,
"isAutoGenerated": true,
"sourceDetail": "youtube_shorts_auto_captions",
"viewCount": 184231,
"publishedAt": "2026-02-14T10:03:11+00:00",
"status": "ok",
"error": null
}

source is always exactly one of:

  • native_captions — the words came from the platform's own caption track.
  • whisper_asr — the video had no usable captions, so the audio was transcribed with Whisper.

The srt and vtt fields are complete, valid subtitle files. Overlapping caption cues from auto-generated tracks are trimmed, so subtitles do not double up on screen.


How it works

For every URL:

  1. Identify the platform and reject anything that is not a single short-form video, with a specific reason.
  2. Resolve the video — title, author, hashtags, duration, view count.
  3. Check the duration against your cap before doing anything expensive.
  4. Try native captions. If the platform has a usable track, normalise it into text, timed segments, SRT and VTT. Charged as caption_transcript.
  5. Otherwise download the audio and run Whisper (faster-whisper, CPU, int8). Charged as asr_transcript.

A video is charged for exactly one of those two events, after the row is written — never both, never before.


Pricing

EventPriceWhen it fires
caption_transcript$0.002A transcript was produced from the platform's native captions.
asr_transcript$0.040A transcript was produced by Whisper because there were no captions.
apify-actor-start$0.00005Apify's standard start event, charged once per gigabyte of the run's memory. This Actor runs at 2 GB, so $0.0001 per run.

Those are the Free-plan prices. Apify's paid plans get its standard Store discount off every event — Bronze 5 %, Silver 10 %, Gold and above 15 % — so asr_transcript costs $0.038, $0.036 or $0.034 on those plans and caption_transcript costs $0.0019, $0.0018 or $0.0017.

Whisper costs about a second of CPU for every 1.5 seconds of audio, which is why it is priced twenty times the caption rate. Most videos never touch it.

Nothing else is charged. In particular you are not charged for:

  • videos that are deleted, private, region-locked or age-restricted;
  • videos longer than your maxDurationSeconds cap;
  • caption-less videos longer than maxAsrDurationSeconds (they return ASR_DURATION_EXCEEDED);
  • videos where Whisper finds no speech at all (music-only clips);
  • malformed URLs or unsupported platforms;
  • any run that fails.

What a run actually costs

Caption availability is what moves the bill. On short-form video it varies a lot by niche — talking-head, educational and news content is largely captioned; dance, music and meme content often is not.

1,000 videosCost
All have captions$2.00
90 % captions / 10 % Whisper$5.80
70 % captions / 30 % Whisper$13.40
None have captions$40.00

(Free-plan prices; a Gold plan pays 15 % less than each of these.)

Turn "Transcribe with Whisper when there are no captions" off to cap the price at $0.002 per video: caption-less videos then return a CAPTIONS_UNAVAILABLE error, free of charge, and you can decide what to do with them.


Input

FieldTypeDefaultWhat it does
videoUrlsarrayRequired. TikTok video URLs and YouTube Shorts URLs.
languagestring(blank)Two-letter code (en, es, pt…). Blank keeps the video's own language — usually what you want for a transcript. Setting it selects that language's caption track when the platform offers one (which may be a translation) and tells Whisper what to expect.
allowWhisperFallbackbooleantrueOff = captions only, and caption-less videos cost nothing.
maxDurationSecondsinteger600Videos longer than this are skipped, free. Max 1200.
maxAsrDurationSecondsinteger180Length limit for the Whisper path only. Caption-less videos longer than this return ASR_DURATION_EXCEEDED, free. Captioned videos are unaffected.
maxVideosinteger1000Safety cap on the number of URLs processed.
forceWhisperbooleanfalseTranscribe with Whisper even when captions exist. Charged at the asr_transcript rate.
whisperModelstringbasetiny, base or small. Only affects the Whisper fallback.
beamSizeinteger1Whisper decoding beam width.
concurrencyinteger5Videos resolved in parallel. Whisper always runs one at a time.
includeFailedItemsbooleantrueKeep a row (with an error code) for every failure, so inputs reconcile to outputs.
useResidentialFallbackbooleantrueRetries through a residential IP when a platform answers the normal proxy with a bot check. YouTube needs this.
proxyConfigurationobjectApify ProxyRecommended. Used for the first attempt on every request.

Minimal input

{
"videoUrls": [
"https://www.tiktok.com/@nasa/video/7189113838831488302",
"https://www.youtube.com/shorts/BDf5mOfSkkw"
]
}

Run it

In the Apify Console

Open the Actor, paste your URLs into Video URLs, one per line, and click Start. Results appear in the dataset and can be exported as JSON, CSV, XLSX or Excel — or you can download the srt column straight into a subtitle file.

API

curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~short-video-transcriber/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"videoUrls": [
"https://www.tiktok.com/@nasa/video/7189113838831488302",
"https://www.youtube.com/shorts/BDf5mOfSkkw"
],
"maxDurationSeconds": 600
}'

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('YOUR_USERNAME/short-video-transcriber').call({
videoUrls: [
'https://www.tiktok.com/@nasa/video/7189113838831488302',
'https://www.youtube.com/shorts/BDf5mOfSkkw',
],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
if (item.status !== 'ok') {
console.warn(`${item.inputUrl}: ${item.error}`);
continue;
}
console.log(`${item.author} (${item.source}): ${item.text}`);
// Save subtitles next to your video files:
// await fs.writeFile(`${item.videoId}.srt`, item.srt);
}

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("YOUR_USERNAME/short-video-transcriber").call(input={
"videoUrls": [
"https://www.tiktok.com/@nasa/video/7189113838831488302",
"https://www.youtube.com/shorts/BDf5mOfSkkw",
],
"allowWhisperFallback": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["status"] != "ok":
print(f"{item['inputUrl']}: {item['error']}{item['errorMessage']}")
continue
print(item["author"], item["language"], item["wordCount"], "words")
with open(f"{item['videoId']}.srt", "w", encoding="utf-8") as handle:
handle.write(item["srt"])

n8n, Make and Zapier

The Actor works with the standard Apify → Run Actor node in n8n and the Apify → Run an Actor module in Make. Point the node at this Actor, pass videoUrls as the input JSON, then read the dataset items in the next step — text for the transcript, srt for a subtitle file, error to branch on failures.

A common shape: a spreadsheet or webhook supplies URLs → this Actor returns transcripts → an LLM node summarises, translates or tags them → the result is written back. Because failures come back as rows with an error field rather than as a broken run, a filter on status == "ok" is all the error handling most workflows need.


Errors

Failed videos get a dataset row with status: "error", an error code and a plain-English errorMessage. They are never charged.

CodeMeaning
VIDEO_UNAVAILABLEDeleted, never existed, or region-locked.
VIDEO_PRIVATEPrivate, friends-only or followers-only.
DURATION_EXCEEDEDLonger than maxDurationSeconds.
ASR_DURATION_EXCEEDEDNo captions, and longer than maxAsrDurationSeconds. Raise that limit to transcribe it anyway.
CAPTIONS_UNAVAILABLENo native captions and the Whisper fallback is turned off.
NO_SPEECH_DETECTEDWhisper found no speech — a music-only or silent video.
UNSUPPORTED_PLATFORMNot a TikTok or YouTube Shorts URL.
INVALID_URLNot a link to a single video (a profile or channel URL, for example).
MEDIA_UNAVAILABLEThe audio could not be downloaded for transcription.
BLOCKED / RATE_LIMITEDThe platform refused the request. Try again, ideally with a proxy.
MEMORY_LIMITThe video does not fit in the run's memory for the chosen model. Raise the memory or pick a smaller model.

Limits and good to know

  • Short-form only. The default cap is 600 seconds and the maximum is 1200. For podcasts, webinars and long YouTube videos, use a general-purpose transcriber instead.
  • Memory. Run with at least 2 GB. That covers the whole duration range with the base model; the Actor refuses an impossible combination up front instead of being killed mid-run.
  • Auto-generated captions are auto-generated. When a transcript comes from a platform's own ASR track (isAutoGenerated: true), it carries that track's mistakes. For the highest accuracy on a specific video, turn captions off in your workflow and let Whisper do it — or use the small model.
  • Public videos only. No login, no cookies, no private content.
  • Caption availability changes. Platforms backfill captions hours after upload, so the same video can take the Whisper path today and the caption path tomorrow.
  • Leave the residential retry on for YouTube. YouTube refuses datacenter IPs outright ("Sign in to confirm you're not a bot"). The Actor retries those requests through a residential IP automatically; with useResidentialFallback off, YouTube Shorts return LOGIN_REQUIRED. TikTok does not need it.
  • Whisper is length-limited; captions are not. A caption-less video is transcribed up to maxAsrDurationSeconds (180 s by default — the length of the longest YouTube Short, and longer than the overwhelming majority of TikToks). Past that, Whisper's cost outgrows a per-video price, so the video returns ASR_DURATION_EXCEEDED and costs you nothing. Raise the limit if you want those anyway. Videos with captions run to the full maxDurationSeconds at the $0.002 rate, whatever their length.

What this Actor does not do

It transcribes videos. It does not scrape comments, profiles, followers or hashtags, does not monitor accounts, and does not summarise, translate or analyse sentiment — pipe the transcript into an LLM step for that.


video to text · video transcript · transcribe video · TikTok transcript · TikTok to text · YouTube Shorts transcript · Shorts to text · caption extractor · subtitle downloader · SRT generator · VTT subtitles · speech to text · Whisper transcription