Audio Transcription - Speech to Text, Audio to Text, Whisper avatar

Audio Transcription - Speech to Text, Audio to Text, Whisper

Pricing

from $4.80 / 1,000 audio minutes

Go to Apify Store
Audio Transcription - Speech to Text, Audio to Text, Whisper

Audio Transcription - Speech to Text, Audio to Text, Whisper

Bulk audio transcription with Whisper: transcribe audio to text, video to text, speech to text, MP3 to text, YouTube video transcription, podcast RSS, Google Drive/Dropbox links. SRT/VTT subtitle generator, speaker diarization, TXT/Markdown, 90+ languages. $0.006/min.

Pricing

from $4.80 / 1,000 audio minutes

Rating

0.0

(0)

Developer

Yukai Lin

Yukai Lin

Maintained by Community

Actor stats

0

Bookmarked

84

Total users

68

Monthly active users

2 hours ago

Last modified

Share

What does Audio Transcription - Speech to Text, Audio to Text, Whisper do?

Turn an audio file, video link or podcast RSS feed into searchable text with timestamps and downloadable SRT, VTT, TXT and Markdown files.

WhatsApp / Telegram voice notes: pass direct .ogg / .opus download URLs from n8n, uazapi or Evolution API in urls. The link must still work without a login when this Actor starts downloading it.

n8n HTTP Request JSON body (replace voiceNoteUrl with your previous node's direct media URL field): {"urls":["{{$json.voiceNoteUrl}}"]}

Try one short recording

The input form starts with one public, 8.5-second spoken WAV file; Podcast RSS feeds is empty. Click Start to get one transcript row, then replace the sample URL with your own file. The sample needs no login.

Input: {"urls":["https://webcapture-api.yukailin.workers.dev/samples/speech-sample.wav"]}

Output: one successful row with nonempty text, durationSeconds of about 8.5, charged: true, and srtUrl, vttUrl, txtUrl and mdUrl download links. The run's SUMMARY.status is SUCCESS.

Price: $0.006 per started audio minute (this sample is one billed minute, $0.006); failed, blocked and speechless files are not charged. Speaker labels are $0.015/min instead, and optional AI summary is $0.01/file.

  1. Paste the file links, one per line, into Audio or video file URLs (a direct .mp3 / .mp4 link, or a Google Drive / Dropbox / OneDrive share link set to "anyone with the link"). Check that the file downloads in a signed-out or private browser window and that any temporary link is still valid. If your company does not allow public sharing, use Or upload audio / video files (audioFiles) instead.
  2. Optional: set the Language and turn on Speaker labels ($0.015 per minute instead of $0.006) or AI summary and chapters ($0.01 per file).
  3. Click Start. Each file becomes one row with the text, timestamps and srtUrl / vttUrl / txtUrl / mdUrl links to its subtitle and transcript files.
  4. Download the files from those links, or call the Actor from the API. A 60-minute recording costs $0.36; a file that fails or has no speech costs nothing.

Multiple files in one run

  1. For three recordings, paste three public links, one per line, into Audio or video file URLs (urls), or upload three files under Or upload audio / video files (audioFiles). Example urls values: https://example.com/recording-1.mp3, https://example.com/recording-2.mp3, https://example.com/recording-3.mp3 (placeholders; replace them with your own links). Links must be downloadable without signing in.
  2. Remove the prefilled speech sample from urls if you do not want it in this run; it can be transcribed and charged. Podcast RSS feeds starts empty. Before Start, set Apify's Maximum cost per run in Run options or Max total minutes per run (maxTotalMinutes) in Advanced settings.
  3. Each file gets a result row; failed or silent files are free. With at least two saved transcripts, SUMMARY.combinedTranscript links to the combined TXT and Markdown files. For a failed row with retryable: true, start a new run with that run's key-value store RETRY_INPUT record; after a spending or minute limit, use REMAINING_INPUT for files still to process. Do not rerun the full original input: completed files can be transcribed and charged again.

First run: try the prefilled example

The input form already holds only the short speech sample in Audio or video file URLs. Click Start without changing anything for one result; the 8.5-second recording is billed as one started minute ($0.006). Each result row shows the text and charged: true or false. Then replace the example with your own links (a Google Drive / Dropbox / OneDrive share link must be set to "anyone with the link").

Choose a file or video with spoken words. If the only result is no_text, the run can still say SUCCESS: no speech was detected, no transcript was produced, and the row is free. Check that you selected the track with spoken words, or try another file or link with speech; SUMMARY.nextStep and the run status repeat this hint.

How to transcribe a podcast to SRT subtitles

  1. Paste the podcast's RSS feed (or an Apple Podcasts link) into Podcast RSS feeds, or episode file links into Audio or video file URLs. Optional: Episodes per podcast feed and date or title filters pick the episodes. Captivate episode pages and their direct or tracking-prefixed MP3 links can be used when the public player supplies a working file. If Captivate briefly answers 404, the Actor tries another download route. If its episode redirect has no target on every route, the failed row is free and asks you to retry later or use the current MP3 enclosure URL from the show's RSS feed. A genuinely missing file stays a free not_found row.
  2. Optional: set the Language and turn on Speaker labels ($0.015 per minute instead of $0.006).
  3. Click Start. Each episode becomes one row with the text, timestamps and srtUrl / vttUrl links to its subtitle files.
  4. Download the SRT files from those links, or call the Actor from the API for a whole feed. A 60-minute episode costs $0.36.

How to transcribe a YouTube video to text

  1. Paste YouTube video links (watch, youtu.be or shorts links), one per line, into Audio or video file URLs. Videos up to 4 hours work without changing any setting.
  2. Click Start. The spoken audio is transcribed (not the captions), so videos without captions work too; each video becomes one row with the text, timestamps, the video title and channel, and SRT / VTT / TXT / Markdown files.
  3. Same price as files: $0.006 per audio minute (a 30-minute video costs $0.18). Private, removed or silent videos are free rows.

Why this one

  • $6 per 1,000 audio minutes (Gold and above $4.80), with no start fee and no per-file fee. The two most used file transcribers on Apify Store charge $48 (memo23) and $300 on the Free plan ($9 on Gold, sian.agency) per 1,000 minutes (comparison, checked 2 October 2026).
  • Failed, silent and skipped files are free. Every row says charged: true/false, and the run log shows the cost plan before anything is charged.
  • Apify Free plan ($5 monthly credit) = about 833 audio minutes, e.g. about 13 one-hour podcast episodes. A run that reaches your limit stops cleanly: files left are free and listed, ready to run again (details).
  • Subtitles and transcript files included: SRT, VTT, TXT and Markdown for every file, plus paragraphs and timestamps, at no extra charge.
  • No 25 MB limit, no API key, no proxy: files up to 2 GB and any length, Google Drive / Dropbox / OneDrive share links, podcast RSS feeds, YouTube video links and Loom, Wistia, Streamable and Reddit (v.redd.it) video links in the same run.
  • Find every mention (searchTerms): brands, names or topics with the time, the sentence, the speaker and a link that opens the recording at that moment, plus one CSV of all mentions, at no extra charge.
  • Paste the input you already use: field names of other transcription Actors (audioUrls, mediaUrls, datasetItems, speakerDiarization, ...) are mapped automatically.

Input (copy and paste)

{
"urls": ["https://archive.org/download/gerald-ford-inaugural-address-august-9-1974-720p/Gerald%20Ford%20inaugural%20address_%20August%209%2C%201974%20%28720p%29.mp4"],
"summarize": true
}

Output (real result, shortened)

The 8-minute video above, transcribed in 33 seconds and billed 9 minutes ($0.054) plus the AI summary ($0.01):

{
"success": true,
"durationSeconds": 500.1,
"billedMinutes": 9,
"language": "en",
"text": "Mr. Chief Justice, my dear friends, my fellow Americans, the oath that I have taken is the same oath that was taken by George Washington...",
"segments": [
{ "start": 1.36, "end": 20.4, "text": "Mr. Chief Justice, my dear friends, my fellow Americans, the oath that I have taken ..." }
],
"chapters": [{ "start": "0:00", "title": "Introduction and Compact with the Nation" }, { "start": "5:04", "title": "Message of Hope and Unity" }],
"srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.srt",
"txtUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.txt"
}

All fields, speaker labels and word timestamps: Output example.

How much does it cost?

EventPrice
Audio minute$0.006 per minute ($0.36 per hour)
Audio minute with speaker labels (optional)$0.015 per minute ($0.90 per hour), instead of the regular audio minute, only when speakerLabels is on
Translated subtitles (optional)$0.002 per minute per language (e.g. a 30-minute episode in Spanish and German = $0.12), only for languages that succeed
AI summary and chapters (optional)$0.01 per file, only when summarize is on
  • No start fee. You pay only for transcribed audio.
  • SRT and VTT subtitles, paragraphs and timestamps are included.
  • Billed per started minute of audio (a 500-second video is 9 minutes).
  • Word-level timestamps are included in the regular $0.006 per minute (Whisper word timings). With speaker labels on, words come from nova-3 and the speaker-label price applies, not both.
  • Translated subtitles (subtitleLanguages, up to 5 languages): SRT + VTT per language with the original timings and speaker labels, made right after the transcript. A language that fails is free and reported in translatedSubtitles.
  • YouTube video links are billed like files: the transcribed audio minutes only, no per-video fee. Videos that cannot be transcribed (YouTube access paused, private or removed video, over your limits) are free.
  • Not charged: files that cannot be downloaded or decoded, files with no speech, files skipped by your limits (maxMinutesPerFile, maxTotalMinutes), files skipped by newEpisodesOnly, episodes removed by the feed filters, and the audio minutes of episodes that use the publisher's own transcript (with summarize on, their AI summary is still $0.01).
  • Higher Apify plans get volume discounts (Silver 10%, Gold and above 20%).

How far does the free plan go?

Apify's Free plan includes $5 of credit every month. If you spend it only on this Actor, at $0.006 per audio minute that is about 833 audio minutes:

What you transcribeCost eachWith $5
60-minute podcast episodeabout $0.36about 13 episodes
30-minute videoabout $0.18about 27 videos
60-minute recording with speaker labels ($0.015 per minute)about $0.90about 5 recordings (333 minutes)

Minutes are billed per started minute of each file, so a 60-minute episode can be 61 billed minutes. Options cost extra: speaker labels replace the $0.006 minute with $0.015, the AI summary adds $0.01 per file, and translated subtitles add $0.002 per minute and language.

What happens at the limit. A file is only started when the run's Maximum cost per run still covers all its minutes (and Max total minutes per run, if you set it). Files that do not fit get a free row with errorType: "limit_reached" or are not started, and the run ends normally with SUMMARY.status LIMIT_REACHED. Files in progress at that moment are finished; minutes are charged only after a transcript row is saved.

What to do next. The status message and SUMMARY.limitReached.message say how many files were processed, how many were left and that those were not charged. The links left are in SUMMARY.remainingInputs, and the REMAINING_INPUT record in the run's key-value store is your input with only those links. Then either:

  • raise Maximum cost per run (Run options) or Max total minutes per run and start a run with the REMAINING_INPUT record as input, or
  • if your monthly credit is used up, upgrade your Apify plan or wait for the monthly reset, then run the REMAINING_INPUT record (or paste the links from SUMMARY.remainingInputs).

Files that were already finished are not in that input, so they are not transcribed or charged again.

After a successful Free-plan run with a transcribed file, the status message and SUMMARY.nextStep say you can keep using this Actor for batches. If your Apify monthly credit is actually used up, upgrade your plan or wait for the monthly reset. The Actor does not read your account's remaining credit.

Features

It turns audio files, videos and podcast episodes into text with timestamps, readable paragraphs, and ready-to-use SRT and VTT subtitle files. It uses OpenAI's open Whisper large-v3-turbo model, detects the language automatically and supports 90+ languages.

  • 🎙️ Podcasts, interviews, meetings, lectures, webinars, audiobooks, voice notes
  • 🎬 Video to text: MP4, MOV, MKV, WEBM and more. The audio track is extracted automatically
  • 📡 Podcast RSS feeds: paste a feed (or an Apple Podcasts show link) and the newest episodes are transcribed, with episode title and publish date
  • 📝 Publisher transcripts, no audio minutes: when a podcast publishes its own transcript in the feed (Podcasting 2.0 <podcast:transcript>: VTT, SRT, JSON, HTML or text), it is used instead of transcribing, with the same output and transcriptSource: "publisher"
  • 🗓️ Feed filters: only episodes published since / until a date, or whose title contains (or does not contain) a text
  • 📤 File upload: upload recordings from your computer in Apify Console (audioFiles)
  • ▶️ YouTube video links: the video's audio is transcribed at the same $0.006 per minute, no per-video fee (details)
  • 🎥 Loom and Wistia links: paste a Loom share link (sales demos, async meetings, onboarding videos) or a Wistia media link; the file that the host's public player uses is transcribed at the same per-minute price (details)
  • 🎞️ Streamable and Reddit videos: a Streamable link (streamable.com/...) or a v.redd.it video link is transcribed from its audio track at the same per-minute price (details)
  • 🔎 Keyword search (searchTerms): every mention of a brand, name or topic with its timestamp, sentence, speaker and a link to that moment, counts per term, and KEYWORD_MATCHES.csv for the whole run, e.g. to monitor podcasts for your brand on a schedule (no extra charge, details)
  • 🔁 Retry only what may work later: every failed row says retryable: true/false, and the run saves a ready input with only those links (RETRY_INPUT) for n8n, Make, Zapier or a webhook (details)
  • 🌐 Web pages with one player: a page with exactly one audio or video file (e.g. a news, lecture or archive.org page); the file is found and transcribed
  • 🔗 Google Drive, Dropbox and OneDrive share links work if the file is shared publicly
  • ⏱️ Timestamped segments, paragraphs and full plain text in one result
  • 🗣️ Speaker labels ("speakerLabels": true): who said what, as Speaker 1, Speaker 2… on every segment, paragraph and subtitle line, plus the number of speakers
  • 🔠 Word-level timestamps ("wordTimestamps": true): start and end time of every word, for video editing and precise subtitles (included in the regular price)
  • 🌍 Translated subtitles in one step ("subtitleLanguages": ["Spanish", "German"]): SRT and VTT in up to 5 extra languages, timings and speaker labels kept
  • 🔁 Only new episodes ("newEpisodesOnly": true): scheduled runs skip episodes and files that were already transcribed, and only take episodes released after the newest one already done, so a day without a new episode costs nothing (backfillOlderEpisodes works through the back catalogue instead)
  • 🧾 SRT and VTT subtitles saved for timed transcripts (no extra charge). Each result with saved subtitles includes subtitleTimingSource: segment when a cue keeps its segment boundaries, word when a longer segment uses valid word times, estimated when a longer segment is split with interpolated times or a cue's end is adjusted to avoid overlap, publisher when a publisher cue keeps its original boundaries, or mixed when cues use different sources. This describes the actual subtitle cues, which can use different timing data from the public segments. Untimed publisher transcripts and results without saved subtitles omit the field.
  • 📝 Meeting notes ("meetingNotes": true): summary, decisions, action items (task, owner, due date) and, with speaker labels, talk time and main points per speaker, as JSON and a Markdown file (no extra charge)
  • 🧠 Optional AI summary and chapters ("summarize": true), with no API key needed
  • 🌍 Automatic language detection, or set the language yourself
  • 🔤 Vocabulary hints: give names and terms (e.g. "Apify, Kubernetes") so they are spelled correctly
  • 🎚️ Fast or accurate (transcriptionEngine): fast (default) uses Cloudflare Workers AI Whisper for the quickest results; accurate uses Whisper on our own server, with fewer errors but about twice the time. Same price (details)
  • 📏 Large files: up to 2 GB per file, any length. Long recordings are cut in pauses and transcribed in parallel
  • 🔕 Silent files are free: files with no speech are reported but not charged
  • ⚡ Fast: in our tests an 8-minute MP4 video took 33 seconds and a 26-minute MP3 took 109 seconds
  • 📄 TXT and Markdown transcripts for every file (txtUrl, mdUrl), plus one combined file per run, ready for Google Docs, Notion or an LLM (no extra charge)
  • 🔌 n8n, Make and Zapier: one HTTP request, no 25 MB file limit and no OpenAI key (examples below)

What you can rely on:

  • Files, podcast feeds, YouTube, TikTok videos, Instagram Reels, Loom, Wistia, Streamable and Reddit (v.redd.it) videos. The Actor downloads media files, share links and RSS feeds. YouTube video links go through our own paced YouTube service (no login, no cookies); when YouTube pauses it, those rows are free and say to retry later. Loom and Wistia links use the file of the host's public player, only for public media. Public TikTok video links are transcribed from the video's original sound, and public Instagram Reels from the reel's video (no login, no cookies). Streamable videos are transcribed from their public player MP4, and Reddit's v.redd.it videos from the audio track of their public stream (requests carry our own user agent and only use paths the host's robots.txt allows; Reddit post pages are not read). It does not list TikTok or Instagram profiles, and it does not collect account data.
  • No start fee, no per-run or per-file fee. You pay per audio minute. Files that fail, have no speech or are skipped by your limits are free, and every row says charged: true/false.
  • Stable output. New fields may be added; existing fields are not renamed or removed, so your parser or automation keeps working.

Cost control and price comparison

Control your cost

  • What is charged: the minutes of each transcribed file (rounded up per file) and, with summarize on, one AI summary per file. Minutes are charged only after the transcript row has been saved.
  • What is free: lines that are not a URL, duplicate links (also the same YouTube video in two link forms), Spotify / Vimeo / SoundCloud page links, TikTok and Instagram profile links, private Loom and Wistia media, private, removed and licensed-music-only TikTok videos, Instagram photo posts and private or removed reels, Streamable videos that are still uploading or processing, Reddit post links (not read: pass the video's v.redd.it link instead), YouTube playlist and channel links, YouTube videos that could not be transcribed, web pages without exactly one media file, files that cannot be downloaded or decoded, files without speech, files skipped by your limits, and publisher transcripts (billedMinutes: 0). Every row has charged: true/false, and failed rows say "(not charged)".
  • Plan at the start: the run's status message and log start with the cost plan (audio minutes known from podcast feeds, summaries, and how many files are measured when downloaded); it is also saved as SUMMARY.costPlan.
  • Caps: Max minutes per file and Max total minutes per run (Advanced settings) skip files before they are transcribed, using the duration read from the file (or from the podcast feed, before downloading).
  • Max charge per run: set Maximum cost per run in the run options (or maxTotalChargeUsd in the API). A file is only started when the limit still covers all its minutes; when it does not, the run stops cleanly: SUMMARY.status is LIMIT_REACHED and SUMMARY.notProcessed lists the files that were not started (count and up to 100 inputs). The status message and SUMMARY.limitReached say how many files were processed and how many are left; SUMMARY.remainingInputs lists the remaining links and the REMAINING_INPUT record is your input with only those. To continue, raise the maximum cost per run and run that input: finished files are not in it, so they are not charged again (running the same full input again would transcribe and charge them again, unless newEpisodesOnly or resumeStore is on). The AI summary is only made when the limit also covers it.
  • If Apify restarts the run (server migration or Resurrect), items already finished are skipped and not charged again (SUMMARY.resumedSkipped).
  • Time limit per file (fileTimeoutSecs, default 1,800 seconds): a file whose download, conversion and transcription take longer gets a row with errorType: "timeout" and is not charged, and the run goes on with the next file. Raise it for recordings of several hours. YouTube videos get at least their length x 15 seconds + 20 minutes.
  • Files in parallel (fileConcurrency, default 3, up to 10): several files are downloaded and transcribed at the same time, so podcast batches finish sooner. Rows are saved in the order files finish; inputIndex is each file's position in the input. Your max charge per run and Max total minutes per run still hold: before a file is transcribed, its cost is reserved together with the files already in progress, so files running side by side can never go over the limit. With little run memory fewer files run at once (about 3 at the default 1,024 MB); the time a file waits for budget held by other files does not count against fileTimeoutSecs.

Price comparison (checked 2 October 2026)

Per-minute prices of other transcription Actors on Apify Store, Free plan unless noted; "not stated" means we did not find it in that Actor's input or README:

ActorPriceSpeaker labels
This Actor$0.006 per minute, no start fee (Gold+ $0.0048)$0.015 per minute instead of $0.006
steadyfetch / media-transcriber$0.003 per minutenot stated
amanatools / whisper-transcriber$0.008 per minute, plus $0.005 per filenot stated
kaz_kakyo / audio-transcriber$0.01 per minute; chapters $0.01 per fileyes (Deepgram nova-3)
viralanalyzer / video-transcriber$0.015 per minutenot stated
sauliusautomatesit / media-transcriber$0.035 to $0.12 per minutenot stated
hgservices / speech-to-text$0.042 per minute (Gold $0.024), plus $0.09 per YouTube videoyes
memo23 / video-audio-transcriber$0.048 per minute (billed per second, $0.0008 per second), plus $0.005 per runyes
tictechid / vanzi-universal-transcriber$0.0025 per second ($0.15 per minute), plus $0.01 per runnot stated
sian.agency / INCREDIBLY-FAST-audio-transcriber$0.30 per minute ($0.005 per second) on the Free plan (Bronze $0.015, Gold $0.009), plus $0.005 per runextra $0.001 per second on the Free plan, $0.0001 per second on paid plans
parseforge / audio-transcriber$0.44 per file, plus $0.012 per runnot stated

This is not the lowest per-minute price: steadyfetch charges half as much. What the $0.006 includes: no start fee and no per-file fee; failed, silent and skipped files free; SRT/VTT subtitles and TXT/Markdown files; podcast RSS feeds with date and title filters, publisher transcripts (0 audio minutes) and only-new-episode schedules; Google Drive, Dropbox and OneDrive share links; files up to 2 GB. Speaker diarization, translated subtitles and AI summaries are optional. YouTube video links, public TikTok video links, public Instagram Reels, Loom, Wistia, Streamable and Reddit (v.redd.it) video links are transcribed at the same per-minute price, with no per-video fee; keyword search (searchTerms) is included.

Switching from another transcription Actor

You can paste the input you already use: field names of the most used transcription Actors are accepted and mapped to this Actor's fields (the run log lists each one under "Input compatibility"). Options that have no equivalent here are listed in the log too, never silently dropped.

Comparison with the two most used audio/video file transcribers on Apify Store, checked on 2 October 2026 from each Actor's public pricing and README (Free plan; prices can change, check their pages):

This Actorsian.agency / INCREDIBLY-FAST-audio-transcribermemo23 / video-audio-transcriber
Price per 1,000 audio minutes$6 (Gold+ $4.80)$300 on the Free plan ($0.005 per second); $15 Bronze, $9 Gold+$48 ($0.0008 per second)
Start feenone$0.005 per GB of run memory$0.005 per GB of run memory ($0.01 at the default 2 GB)
Billing unitstarted minute per filesecondsecond
Failed or silent files free?yes, every row has chargedfiles over the Free-plan cap are not charged; other failures not statedyes, only delivered transcripts are charged
Files per runup to 1,0001 file of up to 5 MB or 60 seconds on the Free plan; unlimited on paid plansup to 50 URLs
Speaker labels$0.015 per minute instead of $0.006extra $0.001 per second on the Free planincluded
AI summary and chapters$0.01 per filenot offeredincluded
Podcast RSS feedsyes, with date/title filters and publisher transcriptsnot statedyes, with publisher transcripts
YouTube / TikTok / Instagram linksYouTube, public TikTok video links and public Instagram Reels yes, same per-minute price (no speaker labels on YouTube)yes (paid plans)yes
ModelWhisper large-v3-turbonot statedWhisper tiny, base or small
Max file size2 GB1 GB on paid plansnot stated

If you transcribe files, recordings, podcast feeds, YouTube, TikTok or Instagram Reels, this one costs less per minute. For YouTube videos that already have captions, our YouTube Transcript Scraper is cheaper still.

Paste your existing input. Both of these work unchanged:

{
"audioUrls": ["https://example.com/episode.mp3"],
"language": "english",
"speakerDiarization": true
}
{
"mediaUrls": ["https://example.com/meeting.mp4", "https://feeds.npr.org/510289/podcast.xml"],
"maxEpisodesPerFeed": 1,
"maxMinutesPerItem": 120,
"publishedAfter": "2026-09-01",
"newItemsOnly": true,
"watchlistId": "my-show"
}
Field from another ActorRead here as
audioUrls, startUrls (strings or { "url": ... }), mediaUrls, media_urls, videoUrls, fileUrlsurls (podcast feed links in these lists go to podcastFeeds)
podcastUrls, feedUrls, rssUrlspodcastFeeds
maxEpisodesPerShow, rss_episodesmaxEpisodesPerFeed
maxMinutesPerItem, max_minutes_per_filemaxMinutesPerFile (0 = no limit)
publishedAfter / episodeTitleContainsepisodesSince / titleIncludes
newItemsOnly / watchlistIdnewEpisodesOnly / monitorName
speakerDiarization, diarizespeakerLabels (the speaker-label price applies)
includeWords, word_timestampswordTimestamps
keytermsvocabulary
outputFormats without srt or vttsaveSubtitles: false
language: "auto", "english", "en-US"auto-detect, "en", "en"

Not used here (noted in the log): translateToEnglish (the transcript stays in the spoken language; for English subtitles set "subtitleLanguages": ["English"]), useEuServers, model, cookies, deepgramApiKey. When both a field of this Actor and another Actor's name for it are set, this Actor's field wins.

Supported input

InputDetails
Audio filesMP3, WAV, M4A, AAC, OGG, OPUS, FLAC, AIFF, WMA, AMR and other formats ffmpeg can read
Video filesMP4, MOV, MKV, WEBM, AVI and more. Only the audio track is used
SizeUp to 2 GB per file, any length
Share linksGoogle Drive files and public folders (every audio/video file in the folder; large files without the virus-scan page), Dropbox shared links, OneDrive / SharePoint, Box shared links, WeTransfer and iCloud Drive links. The file must open without a sign-in ("Anyone with the link")
Temporary and presigned linksDropbox temporary links (files/get_temporary_link, 4 hours), presigned URLs of Amazon S3 and S3-compatible storage (Cloudflare R2, Backblaze B2, Wasabi, MinIO, DigitalOcean Spaces), Google Cloud Storage signed URLs, Azure SAS URLs, Oracle pre-authenticated requests, signed Apify key-value store links. An expired link fails at once with errorType: "link_expired" (free)
UploadsaudioFiles: files uploaded in Apify Console (stored in a key-value store of your account). In API calls, pass file URLs in urls
Web pagesA page with exactly one <audio> / <video> file, or one og:audio / og:video / JSON-LD contentUrl file link; the found file is in mediaUrl
YouTube videosyoutube.com/watch?v=, youtu.be/, /shorts/, /live/, /embed/ links of public videos; the audio is transcribed, billed per minute like files (details). Playlist and channel links are not expanded
Loom, WistiaLoom share and embed links (loom.com/share/<id>), Wistia media links (<account>.wistia.com/medias/<id>, fast.wistia.com/embed/medias/<id>, fast.wistia.net/embed/iframe/<id>): public media only, billed per minute like files (details)
TikTok videostiktok.com/@<user>/video/<id> links of public videos and short links (vm.tiktok.com/..., tiktok.com/t/...): the video's original sound is transcribed, billed per minute like files (details). Profile links are not expanded
Instagram Reelsinstagram.com/reel/<code>/, /reels/<code>/, /p/<code>/, /tv/<code>/ and /<user>/reel/<code>/ links of public reels and video posts: the reel's sound is transcribed, billed per minute like files (details). Photo and carousel posts are free rows; profile and story links are not expanded
Streamable videosstreamable.com/<code> links of public videos (also the /s/<code> and /e/<code> forms): the MP4 of the host's public player is transcribed, billed per minute like files (details). A video that is still uploading or processing is a free row saying to run it again later
Reddit videosv.redd.it video links (v.redd.it/<id>, or the video's HLS playlist such as v.redd.it/<id>/HLS_PLAYLIST.m3u8, the hls_url of the post): the audio track of the video is transcribed, billed per minute like files (details). Reddit post and profile pages are not read (Reddit's robots.txt does not allow it): pass the video's v.redd.it link, or a Reddit scraper Actor's dataset via datasetId
Podcast feedsAny podcast RSS feed, or an Apple Podcasts show or episode link. Publisher transcripts are used when the feed has them; date and title filters are optional
DatasetThe datasetId of another Actor run, or its rows pasted into datasetItems: the media URL field is detected per row (or set with datasetField, dot paths work); rows without a usable link are free invalid_input rows that name their index

Links must be downloadable without logging in. Facebook, X, Vimeo and Spotify page links are web pages, not files: each comes back as a free row with errorType: "unsupported_platform" and a hint. Download the media first (for example with a downloader Actor from Apify Store) and pass the file URL, or that Actor's dataset via datasetId. Vimeo streams its videos encrypted, so for Vimeo use the file behind the video's Download button when the owner allows downloads; direct file links, such as a Vimeo "video file link" (player.vimeo.com/external/... or .../progressive_redirect/...), are transcribed normally. Reddit post pages are not read either (Reddit's robots.txt does not allow it): pass the video's v.redd.it link or its direct audio file URL instead.

Web pages: for any other web page, the page is read and its media file is looked up: the one <audio> or <video> element (its src or its first playable <source>; several sources of one element are one file), or else one direct file named by og:audio, og:video, twitter:player:stream or JSON-LD contentUrl. Only direct files count: streaming playlists (HLS .m3u8, DASH .mpd) and player pages are not used. When the page has no such file (errorType: "no_media") or several ("multiple_media", listed in mediaCandidates), the row is free; pass the file you want as a direct URL.

A line that is not a URL does not stop the run: it becomes one free row with errorType: "invalid_input" and the other files are processed. Use urls (a plain list of strings) in API calls; the request-list field audioUrls from earlier versions still works.

How to use it

  1. Paste audio or video file URLs (the most used input; Google Drive, Dropbox and OneDrive share links work, or pages with one player), upload files, and/or add YouTube links and podcast feeds (optionally with date and title filters).
  2. Optional: set the language (e.g. en, es, ja), vocabulary hints, and turn on AI summary and chapters, speaker labels or word-level timestamps.
  3. Optional (Advanced settings): cap the cost with Max minutes per file and Max total minutes per run; for schedules, turn on Only new episodes with a monitor name.
  4. Click Start. Each file becomes one result with the text, segments, paragraphs and links to its SRT/VTT files.

Input example

File links first (the most common input), with a language, vocabulary hints, an AI summary and cost caps:

{
"urls": ["https://example.com/meeting-recording.mp4", "https://drive.google.com/file/d/FILE_ID/view?usp=sharing"],
"language": "en",
"vocabulary": "Apify, Cloudflare, TidyTools",
"summarize": true,
"maxMinutesPerFile": 90,
"maxTotalMinutes": 300
}

Add a podcast feed (the newest 3 episodes) and a YouTube video to the same run:

{
"urls": ["https://www.youtube.com/watch?v=CKRxRE7qRzc"],
"podcastFeeds": ["https://feeds.npr.org/510289/podcast.xml"],
"maxEpisodesPerFeed": 3
}

Output example (real result, shortened)

An 8-minute MP4 video with "summarize": true:

{
"url": "https://archive.org/download/gerald-ford-inaugural-address-august-9-1974-720p/Gerald%20Ford%20inaugural%20address_%20August%209%2C%201974%20%28720p%29.mp4",
"success": true,
"format": "mp4",
"fileSizeBytes": 48964530,
"durationSeconds": 500.1,
"billedMinutes": 9,
"language": "en",
"wordCount": 876,
"text": "Mr. Chief Justice, my dear friends, my fellow Americans, the oath that I have taken is the same oath that was taken by George Washington...",
"segments": [
{ "start": 1.36, "end": 20.4, "text": "Mr. Chief Justice, my dear friends, my fellow Americans, the oath that I have taken is the same oath that was taken by George Washington and by every president under the Constitution." },
{ "start": 20.4, "end": 31.32, "text": "But I assume the presidency under extraordinary circumstances never before experienced by Americans." }
],
"paragraphs": [
{ "start": 1.36, "end": 39.68, "text": "Mr. Chief Justice, my dear friends, ... This is an hour of history that troubles our minds and hurts our hearts." },
{ "start": 41.44, "end": 73.64, "text": "Therefore, I feel it is my first duty to make an unprecedented compact with my countrymen. ..." }
],
"summary": "The president assumes office under extraordinary circumstances ... and asks for prayers for Richard Nixon and his family.",
"chapters": [
{ "startSeconds": 0, "start": "0:00", "title": "Introduction and Compact with the Nation" },
{ "startSeconds": 304, "start": "5:04", "title": "Message of Hope and Unity" }
],
"srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.srt",
"vttUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.vtt",
"txtUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.txt",
"mdUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-Gerald-20Ford-...mp4.md",
"processingSeconds": 33
}

With "speakerLabels": true (a real 74-minute Changelog & Friends episode: 3 speakers found, 13,069 words, 195 seconds of processing, 74 minutes billed at $0.015):

{
"success": true,
"model": "nova-3",
"durationSeconds": 4390.7,
"billedMinutes": 74,
"speakers": 3,
"segments": [
{ "start": 16.14, "end": 23.34, "speaker": 1, "text": "Welcome to Changelog and Friends, a weekly talk show about thinking outside the Dropbox." }
],
"paragraphs": [
{ "start": 16.14, "end": 34.87, "speaker": 1, "text": "Welcome to Changelog and Friends, a weekly talk show about thinking outside the Dropbox. Thanks as always to our partners at fly.io, ..." },
{ "start": 43.38, "end": 69.23, "speaker": 2, "text": "This is the year we almost break the database. Let me explain. Where do agents actually store their stuff? ..." }
],
"speakerTranscript": "Speaker 1 [0:16]: Welcome to Changelog and Friends, ...\n\nSpeaker 2 [0:43]: This is the year we almost break the database. ..."
}

With "wordTimestamps": true, every segment also gets its words (real result, a 5-minute news episode):

{ "start": 4.16, "end": 7.52, "speaker": 1, "text": "What's up, friends? Adam here. Big week here at ChangeLog.",
"words": [{ "word": "What's", "start": 4.16, "end": 4.4, "speaker": 1 }, { "word": "up,", "start": 4.4, "end": 4.56, "speaker": 1 }, { "word": "friends?", "start": 4.56, "end": 4.96, "speaker": 1 }] }

In the SRT file a line starts with Speaker 2: when the speaker changes; the VTT file uses <v Speaker 2> voice tags. Files longer than 50 minutes are sent in overlapping pieces, and the speakers of each piece are matched by the words in the overlap, so Speaker 1 stays Speaker 1 for the whole file.

Transcript files (TXT and Markdown)

Every transcribed file also gets two download links (no extra charge; turn off with "saveTranscriptFiles": false):

  • txtUrl: plain text, one paragraph per block. With speaker labels: Speaker 1 [0:16]: ....
  • mdUrl: Markdown with the title (episode title or file name), source link, duration, language, the AI summary and chapters when summarize is on, then the transcript with a [m:ss] timestamp per paragraph.

When a run has two or more transcripts, all of them are also joined in input order into transcripts.txt and transcripts.md in the run's key-value store; the links are in SUMMARY.combinedTranscript and in the run log.

A podcast episode from an RSS feed also carries the episode details:

{
"url": "https://tracking.swap.fm/track/.../default.mp3?...",
"podcastTitle": "Planet Money",
"episodeTitle": "Middlegarchs are the new Oligarchs",
"pubDate": "2026-09-25T21:46:44.000Z",
"episodeUrl": "https://www.npr.org/2026/09/25/nx-s1-5981194/stealthy-wealthy-everywhere-millionaires-pass-through",
"feedUrl": "https://feeds.npr.org/510289/podcast.xml",
"success": true,
"format": "mp3",
"durationSeconds": 2065.2,
"billedMinutes": 35,
"wordCount": 5505
}

Meeting notes

Turn on "meetingNotes": true to get structured notes for meetings, calls and interviews (no extra charge):

  • meetingNotes.summary, meetingNotes.decisions and meetingNotes.actionItems (task, plus owner and due when they are said in the recording). Only decisions and tasks that are actually said are listed; the lists are empty when there are none.
  • With speakerLabels on: meetingNotes.speakerStats (talk time, share of talk time, words and turns per speaker, computed from the timings, not by AI) and meetingNotes.speakerHighlights (each speaker's main points).
  • meetingNotesUrl: the same notes as a Markdown file with a checklist of action items. The notes are also added to the mdUrl transcript.

For long recordings, the AI notes prompt samples the beginning, evenly spaced passages, and the final spoken paragraph in time order. If the final paragraph itself is too long, its beginning and end are kept so a closing commitment can reach the notes model. The text transcript and saved transcript files remain complete; sampling applies only to the AI notes prompt.

{
"meetingNotes": {
"summary": "The team reviewed the launch plan and agreed on the date.",
"decisions": ["Ship version 2 on Friday"],
"actionItems": [{ "task": "Update the user guide", "owner": "Speaker 2", "due": "Thursday" }],
"speakerStats": [{ "speaker": 1, "talkTime": "12:40", "talkShare": 61.2, "words": 1830, "turns": 24 }],
"speakerHighlights": [{ "speaker": 1, "points": ["Wants to launch before the conference"] }]
},
"meetingNotesUrl": "https://api.apify.com/v2/key-value-stores/.../records/0000-meeting.notes.md"
}

The notes are written by an AI model from the transcript and can miss or misread a point: check them against the transcript before you send them on. Episodes that use the publisher's transcript (no audio minutes) get the speaker statistics only, unless summarize is on.

Publisher transcripts (no audio minutes)

Many podcasts put their own transcript in the feed (<podcast:transcript>, Podcasting 2.0). With usePublisherTranscripts on (the default), such an episode is not transcribed: the publisher's file is downloaded and converted to the same output. Timed formats (VTT, SRT, JSON) give segments with timestamps, paragraphs and our SRT/VTT files; HTML and plain text give the text and paragraphs only (timestamps: false, no subtitle files). Speaker names from the transcript are kept as speakerName on each segment. No audio minutes are charged (billedMinutes: 0); the AI summary, if you turn it on, is charged as usual.

The transcript is checked first: it must have at least 20 words, cover at least half of the episode's duration (from the feed) without running far past it, and have a plausible number of words per minute. A transcript that fails the check, or cannot be downloaded, is ignored and the episode is transcribed normally; the row then says why in publisherTranscriptError. Set "usePublisherTranscripts": false to always transcribe the audio yourself.

Real result (Podnews Daily, whose feed has a VTT transcript per episode; with "summarize": true, so only the $0.01 summary was charged):

{
"podcastTitle": "Podnews Daily - podcast industry and podcasting news",
"episodeTitle": "Was Inception Point AI just a PR stunt?",
"pubDate": "2026-09-29T10:30:00.000Z",
"success": true,
"transcriptSource": "publisher",
"transcriptUrl": "https://podnews.net/audio/podnews260929.mp3.vtt",
"transcriptFormat": "vtt",
"timestamps": true,
"model": "publisher",
"language": "en",
"durationSeconds": 273,
"billedMinutes": 0,
"wordCount": 642,
"segments": [
{ "start": 0.56, "end": 4.96, "text": "From Singapore Airport, the latest from podnews.net with The Podglomerate.", "speakerName": "James Cridland" }
],
"summary": "Inception Point AI's CEO Jeanine Wright has suggested that the company's thousands of AI-made podcasts may have been perceived as a publicity stunt, ...",
"summaryCharged": true
}

In the same test, a 63-minute Buzzcast episode (12,067 words, 810 segments, 10 chapters) was also taken from the publisher's transcript: 0 audio minutes instead of 64.

Feed filters

{
"podcastFeeds": ["https://podnews.net/rss"],
"episodesSince": "2026-09-20",
"episodesUntil": "2026-09-28",
"titleIncludes": ["patreon", "spotify*video"],
"titleExcludes": ["weekly"],
"maxEpisodesPerFeed": 1
}
  • episodesSince: a date (YYYY-MM-DD) or a relative time such as 30 days, 2 weeks, 6 months. episodesUntil: a date; the whole day counts.
  • titleIncludes: keep an episode when its title contains one of the texts; titleExcludes: drop it when its title contains one. Case does not matter; * matches anything (spotify*video).
  • Filters are applied first, then newEpisodesOnly, then maxEpisodesPerFeed. With a date filter, episodes without a publish date are dropped. A link to one Apple Podcasts episode is not filtered.
  • Filtered episodes get no row and are not charged; SUMMARY.episodesFiltered counts them. In our test above, 150 of 151 episodes were filtered and the one match ("Patreon removes per-creation memberships", 4.6 minutes) was transcribed.

Web page with one player

{ "urls": ["https://archive.org/details/nasa_tv-ScienceCast_-_Record-Setting_Asteroid_Flyby"] }

Real result (shortened): the page's og:video file was found and transcribed, 262 seconds, 5 minutes billed:

{
"url": "https://archive.org/details/nasa_tv-ScienceCast_-_Record-Setting_Asteroid_Flyby",
"mediaUrl": "https://archive.org/download/nasa_tv-ScienceCast_-_Record-Setting_Asteroid_Flyby/ScienceCast_-_Record-Setting_Asteroid_Flyby.mp4",
"success": true,
"transcriptSource": "asr",
"format": "mp4",
"billedMinutes": 5,
"segments": [{ "start": 3.7, "end": 8.48, "text": "Record-setting asteroid flyby, presented by Science at NASA." }]
}
{ "urls": ["https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b", "https://fast.wistia.com/embed/medias/j38ihh83m5"] }

Paste the link you would share with a colleague. The Actor asks the host for the file its own public player uses (Loom's video file, or for newer Loom videos that are only streamed, the audio track of the stream; Wistia's smallest MP4 or audio file, never an audio-description track), downloads it and transcribes it like any file, billed per audio minute, no per-link fee. The row adds mediaTitle (the title on Loom or Wistia), mediaUrl (the file that was transcribed) and sourceKind (loom or wistia); sourceFileId is the host's id (loom:<id>), so resumeStore recognises the same video in another link form.

Real result (shortened; 53-second Loom video, 1 minute billed, 7 seconds end to end):

{
"url": "https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b",
"mediaUrl": "https://cdn.loom.com/sessions/transcoded/3690d29d5e3c426eb0f7ea00f9d3ae7b.mp4?Policy=...",
"mediaTitle": "Sell Faster and Smarter with Loom",
"sourceKind": "loom",
"success": true,
"durationSeconds": 53.4,
"billedMinutes": 1,
"text": "Ready to prospect more efficiently, close more pipeline, and create loyal champions? Loom helps you stand out in a sea of text. ..."
}

Only public media is read: a private, password-protected or workspace-only Loom or Wistia video and a removed link each come back as a free row (private_media or not_found) that says why. Encrypted streams are not read (free row, unsupported_platform). Requests carry our own user agent and only use paths that the hosts' robots.txt allows.

TikTok videos

Paste public TikTok video links (https://www.tiktok.com/@<user>/video/<id>, the m.tiktok.com form, or a short link from the app's Share button such as https://vm.tiktok.com/...), one per line. The Actor reads the public video page, takes the video's sound track and transcribes it like any file, billed per audio minute, no per-video fee. The row adds mediaTitle (the video's caption), mediaUrl (the sound file that was transcribed) and sourceKind: "tiktok"; sourceFileId is tiktok:<video id>, so resumeStore recognises the same video in another link form.

  • Only the creator's original sound is transcribed. A video whose sound is licensed music or another creator's sound has no voice track of its own to transcribe: it is a free row (errorType: "unsupported") that says so.
  • Private and removed videos are free rows (private_media, not_found). When TikTok answers a verification page instead of the video (this can happen from data-centre networks), the row is free (blocked) and worth running again later.
  • No login and no cookies are used, and the video file itself is not downloaded. Profile, sound, tag and photo links are not expanded: pass the link of each video.

Instagram Reels

Paste links of public Instagram Reels or video posts (https://www.instagram.com/reel/<code>/, /reels/<code>/, /p/<code>/, /tv/<code>/ or /<user>/reel/<code>/), one per line. The Actor reads the reel's public embed player, downloads its video right away and transcribes the sound like any file, billed per audio minute, no per-reel fee. The row adds mediaTitle (the reel's caption) and sourceKind: "instagram"; sourceFileId is instagram:<code>, so resumeStore recognises the same reel in another link form. The video file link that Instagram signs for the player expires, so it is not saved in the row.

  • Only the reel itself is used (its sound, caption and length). The owner's account, likes, comments and view counts are not read into the output.
  • Photo and carousel posts are free rows (errorType: "no_media", "this post is not a video"). A video Instagram has blocked for copyright is a free row (unsupported).
  • A reel whose sound is music from Instagram's library is still transcribed; when no speech is heard, the row is free (no_text) and says the sound is library music.
  • Private and removed reels are free rows (private_media, not_found). When Instagram refuses the request (this can happen from data-centre networks), the row is free (blocked) and worth running again later.
  • No login and no cookies are used. Profile, story, highlight and share links (instagram.com/share/...) are not expanded: pass the link of each reel.

Streamable and Reddit videos

{ "urls": ["https://streamable.com/dnd1", "https://v.redd.it/zv89llsvexdz/HLSPlaylist.m3u8"] }

Paste a public Streamable link (streamable.com/<code>, the share, /s/<code> or embed form) or the link of a Reddit-hosted video (https://v.redd.it/<id>, or the video's HLS playlist such as https://v.redd.it/<id>/HLS_PLAYLIST.m3u8 — the hls_url of its post). Streamable videos are transcribed from the MP4 of their public player, Reddit videos from the audio track of their public HLS stream, billed per audio minute like files, no per-video fee. The row adds sourceKind (streamable / reddit); sourceFileId is streamable:<code> / reddit:<video id>, so resumeStore recognises the same video in another link form. A Streamable row never contains the file's CDN link (mediaUrl / downloadUrl): Streamable signs that link for a short time and it expires, so the row keeps your original link and the stable fields instead, and the signed link is only used to download the file right away. A Reddit row keeps mediaUrl (the audio playlist that was transcribed) as before.

  • A Streamable video that is still uploading or processing is a free service_busy row: run that link again later; it is only transcribed (and charged) when it is ready. A video that failed on Streamable's side is a free not_found row, and one whose file link is not a usable HTTPS URL (a malformed CDN link on Streamable's side) is a free unsupported_platform row.
  • Reddit post and profile links are not read: Reddit's robots.txt does not allow reading them with our user agent, and no cookies are used. Pass the video's v.redd.it link or HLS playlist instead, or a Reddit scraper Actor's dataset via datasetId (its media URL fields are detected automatically). Direct video and audio files on v.redd.it (for example DASH_AUDIO_128.mp4) are transcribed as plain files too.
  • Requests carry our own user agent, use no cookies and only touch paths that the host's robots.txt allows (Streamable's API host; Reddit's video host v.redd.it). A video that was removed, or that our network is refused to read, is a free row (not_found, blocked) that says so.

Keyword search (brand and topic mentions)

{
"podcastFeeds": ["https://feeds.npr.org/510289/podcast.xml"],
"maxEpisodesPerFeed": 5,
"searchTerms": ["inflation", "Federal Reserve", "tariff*"]
}

Add searchTerms to any run (files, feeds, YouTube, Loom...). Each transcript gets every mention with its time, the sentence it was said in, the speaker (with speaker labels or a publisher transcript that names them) and a link that opens the recording at that moment, plus a count per term. No extra charge: it runs on the transcript you already pay for.

Real result (shortened, "searchTerms": ["Loom", "prospect*", "pipeline", "video"] on the Loom video above):

{
"keywordsFound": ["Loom", "prospect*", "pipeline", "video"],
"keywordCounts": { "Loom": 7, "prospect*": 2, "pipeline": 1, "video": 2 },
"keywordMatches": [
{ "term": "prospect*", "matched": "prospect", "start": 0.5, "end": 5.7, "time": "0:00", "link": "https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b?t=0", "text": "Ready to prospect more efficiently, close more pipeline, and create loyal champions?" },
{ "term": "Loom", "matched": "loom", "start": 6.86, "end": 9.7, "time": "0:06", "link": "https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b?t=6", "text": "Loom helps you stand out in a sea of text." },
{ "term": "prospect*", "matched": "prospects", "start": 18.3, "end": 20.26, "time": "0:18", "link": "https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b?t=18", "text": "Prospects can book a meeting instantly." }
]
}
  • Matching: case and accents are ignored (cafe finds "café"); whole words only, so AI does not match "said" (Chinese, Japanese, Korean and Thai terms match anywhere, as those languages have no spaces); a phrase may run across two segments; a trailing * matches word endings (tariff* finds "tariffs"). Up to 50 terms, up to 500 listed mentions per file (counts stay exact; keywordMatchesTruncated: true when more).
  • Links to the moment: YouTube &t=, Loom ?t=, Wistia ?wtime=, and #t= on the media file for files and podcast episodes (browsers' own players start there).
  • One list for the whole run: KEYWORD_MATCHES.csv (opens in Excel and Google Sheets) and KEYWORD_MATCHES.json in the run's key-value store, one line per mention with the episode or video title; totals per term in SUMMARY.keywords; and the Keyword mentions view of the dataset.
  • Brand monitoring on a schedule: combine with newEpisodesOnly and a podcast feed list, and each run searches only the new episodes. With resumeStore, transcripts done before are searched again with new terms without paying again (reused: true).

YouTube videos

{ "urls": ["https://www.youtube.com/watch?v=CKRxRE7qRzc", "https://youtu.be/...", "https://www.youtube.com/shorts/..."] }

Paste YouTube video links like any other file: youtube.com/watch?v=, youtu.be/, /shorts/, /live/ and /embed/ links all work (a watch link with &list= is that one video). The audio of the video is transcribed with the same Whisper large-v3-turbo model and billed exactly like a file: $0.006 per started audio minute, no per-video fee. Only transcribed minutes are charged; a video that cannot be transcribed is a free row.

Real result (shortened; 89-second video, 2 minutes billed, 30 seconds end to end):

{
"url": "https://www.youtube.com/watch?v=CKRxRE7qRzc",
"sourceKind": "youtube",
"youtubeVideoId": "CKRxRE7qRzc",
"videoTitle": "特朗普與習近平在美國會面:有哪些關鍵議題?- BBC News 中文",
"success": true,
"transcriptSource": "asr",
"asrBackend": "whisper-local",
"durationSeconds": 89.4,
"billedMinutes": 2,
"language": "en",
"text": "Presidents Trump and Xi are about to meet here in the US. So what's at stake? ..."
}

How YouTube links differ from files:

  • Captions are not used: the spoken audio is always transcribed (Whisper quality, your language settings). If the video already has captions and you only need the text, our YouTube Transcript Scraper is cheaper (one small fee per video instead of per minute), and it also lists whole channels and playlists.
  • Playlist and channel links are not expanded: each comes back as a free row (errorType: "unsupported_platform") with a pointer to the YouTube Transcript Scraper. Pass the video links you want, one per line.
  • Per-video limit: maxMinutesPerFile (default and maximum for YouTube: 240 minutes, so a 3-hour podcast video works without changing anything). Longer videos are a free too_large row. Your max charge per run and maxTotalMinutes limit each video the same way as files. A long video gets at least its length x 15 seconds + 20 minutes of fileTimeoutSecs (a 4-hour video: 80 minutes), because the YouTube queue on our side decides how long it takes.
  • Speaker labels are not available for YouTube links: with speakerLabels on, a YouTube link is a free unsupported row (turn speaker labels off, or pass a downloaded file). wordTimestamps (segment timings only) and vocabulary are not applied; the row lists them in optionsNotApplied. Subtitles (SRT/VTT), paragraphs, transcript files, AI summary, meeting notes and translated subtitles work as for files.
  • language: the spoken language is always detected and the video is transcribed in it. When you set language and the video is spoken in another language, you still get the transcript (charged as usual) and the row says so in languageNote; for a transcript in your language, add it to subtitleLanguages. A Chinese language (zh, zh-TW, zh-CN) also picks the script (Traditional or Simplified).
  • Paced access, retry later: YouTube is accessed at a steady pace from our own service, without login or cookies. When YouTube challenges it, YouTube access pauses for a few hours; videos in that time get a free row (errorType: "service_busy", "please try again later"). Private, removed, members-only and age-restricted videos are free rows too. Videos are transcribed one at a time on our side, so a busy queue can make a run wait; the wait counts toward fileTimeoutSecs.
  • Automatic retries: when YouTube refuses an audio download for a moment (HTTP 403), the video is tried again in the same run (up to 2 more times, 20 to 40 seconds apart); only a video that still fails is a free download_failed row that says to run the link again later. A video skipped only because other videos running in parallel held your max charge is tried again with its real length once that budget is free. A video with only music or background sound is a free "no speech" row (noSpeech: true).
  • Extra fields on YouTube rows: sourceKind: "youtube", youtubeVideoId, videoTitle, channel, publishDate, videoDurationSeconds; sourceFileId is youtube:<video id>.

Results that are not charged

Every row has success: true or false. Rows with success: false are free and carry an errorType and retryable (whether running them again later may work, see Retry only what may work later):

errorTypeMeaning
no_textNo speech in the audio (silence or music only); the row also has noSpeech: true. This is a free, valid answer, not a transcript or a download failure: it does not make the run PARTIAL_RESULTS and is counted in SUMMARY.noSpeech. If every file has no_text, check the spoken audio track or use another file or link with speech; the run status and SUMMARY.nextStep say so.
too_largeLonger than maxMinutesPerFile, or larger than 2 GB
limit_reachedWould go over maxTotalMinutes or your Apify spending limit
unsupportedNot an audio or video file (e.g. a web page), no audio track, a TikTok video whose sound is licensed music (no original voice track), an Instagram video blocked for copyright, a language that speaker labels do not support (e.g. Chinese), or speaker labels on a YouTube link
unsupported_platformA Facebook, X, Vimeo or Spotify page link (not a file), a TikTok or Instagram profile, story or other non-video page, a YouTube playlist, channel or other non-video page, a SoundCloud link (SoundCloud is not supported: pass the podcast RSS feed or a direct audio file link), or a Reddit post or other Reddit page (not read: Reddit's robots.txt does not allow it; pass the video's v.redd.it link); the error says what to do instead
private_mediaA Loom, Wistia, TikTok or Instagram link to private, password-protected or workspace-only media; ask the owner to share it publicly, or pass a downloaded file
service_busyYouTube links: YouTube access is paused after a YouTube challenge, the daily YouTube limit is reached, or speech-to-text is busy. Streamable videos that are still uploading or processing (run the link again later). Please try again later
no_mediaA web page without an audio or video file we can use (no player, or only a streaming playlist or player page), or an Instagram photo or carousel post
multiple_mediaA web page with several audio or video files; they are listed in mediaCandidates
invalid_inputA line that is not a URL, or a setting that cannot be used (an unknown language or subtitle language, a wrong episode filter, no input at all): then the run ends with this one free row and says what to change
not_found, blocked, network, timeout, http_error, download_failedThe file could not be downloaded (for YouTube: private, removed, members-only or age-restricted video, or its audio could not be fetched). A blocked row was refused by the file host on every route we tried; downloadAttempts lists them (see Files the host refuses)
rate_limitedThe file host asked us to wait more than 2 minutes before the next download (HTTP 429 with Retry-After); run that file again later

A batch never fails as a whole because some files could not be downloaded: the other files are transcribed and charged, the failed ones are free rows, and RETRY_INPUT holds the links worth running again.

Files the host refuses

Some file hosts refuse downloads from data-center networks, refuse non-browser clients, or stop answering after many files in a row (HTTP 401, 403, 429 or a bot-check page). With the defaults, a refused file is tried again:

  1. on Apify's network with a standard desktop browser User-Agent instead of ours (downloadUserAgent: "auto"; set "tidytools" to never switch);
  2. through our backend (Cloudflare, any file size), our Oracle server in the US (files up to 15 MB) and our home line in Taiwan (files up to 10 MB) (downloadVia: "auto"; pick one route to use only that one).

Each row says how the file came through (downloadRoute: direct, backend, vm or residential; downloadUserAgent: tidytools or browser), and a file that was refused at first also lists every attempt in downloadAttempts. SUMMARY.downloads counts them. There is no extra charge for any route. We never send cookies or log in, never solve CAPTCHAs or use browser automation to get past a bot check, and when a host sends Retry-After we wait that long before asking it again from any route. Files on the same host in one run start with the route that worked for that host; a host that refused everything for two files is asked only once for each later file.

If at least 10 files in a run are blocked and every result row is blocked, the status suggests trying fewer simultaneous batches later when several batches came from the same host. Retry only the blocked links with RETRY_INPUT when that record was saved. In a mixed batch, check each other row separately; its outcome is not implied by the blocked status note.

The run's key-value store also has a SUMMARY record with status (SUCCESS, PARTIAL_RESULTS, FAILED, NO_RESULTS or LIMIT_REACHED), files transcribed, files without speech (noSpeech, counted as successes), minutes billed and more. When files failed, the same record also says what to do with them: failuresByReason counts the failed files by errorType (e.g. { "unsupported": 2, "blocked": 1 }), filesNeedNewInput is how many of them will not work until the input changes, and failureHint is the same one-line next step as in the run's status message. Files without speech are not in these counts (still a valid answer, counted in noSpeech), and neither are limit_reached rows (the run's stop, not a file failure: SUMMARY.remainingInputs and the REMAINING_INPUT record say how to continue).

Use in n8n, Make or Zapier (no 25 MB limit)

OpenAI's Whisper API, and the Whisper nodes in n8n and Make, reject files over 25 MB, so long recordings have to be compressed or split first. Here you only send the file link: the Actor downloads the file (up to 2 GB, any length), cuts it at pauses and returns the whole transcript. No OpenAI key and no ffmpeg step.

One HTTP request. run-sync-get-dataset-items starts the run, waits for it and returns the results (one item per file):

POST https://api.apify.com/v2/acts/tidytools~audio-transcriber/run-sync-get-dataset-items
Authorization: Bearer <your Apify API token>
Content-Type: application/json
{ "urls": ["https://drive.google.com/file/d/FILE_ID/view?usp=sharing"] }

Use text, paragraphs, srtUrl, txtUrl or mdUrl from the response. Google Drive, Dropbox and OneDrive files must be shared as "anyone with the link".

n8n: paste this node into a workflow (Ctrl+V), then add a Header Auth credential with name Authorization and value Bearer <your Apify API token>. It reads the file link from the previous node's webViewLink (Google Drive trigger); change that expression for other sources.

{
"nodes": [
{
"name": "Transcribe (Apify)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [0, 0],
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/tidytools~audio-transcriber/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ urls: [$json.webViewLink] }) }}",
"options": { "timeout": 300000 }
}
}
],
"connections": {}
}

You can also use the official Apify node (Run actor and get dataset, Actor tidytools/audio-transcriber) with the same JSON input; it waits for long runs without the 300-second limit below.

Make: add an HTTP > Make a request module:

FieldValue
URLhttps://api.apify.com/v2/acts/tidytools~audio-transcriber/run-sync-get-dataset-items
MethodPOST
HeadersAuthorization: Bearer <your Apify API token>
Body typeRaw, content type JSON (application/json)
Request content{ "urls": ["{{1.webContentLink}}"] } (the file link from your trigger module)
Parse responseYes

Or use Make's Apify app: Run an Actor (with Run synchronously on), then Get Dataset Items. Zapier works the same way with Webhooks by Zapier > Custom Request or the Apify app.

Large files (200 MB and more) and safe retries. The file never passes through n8n or Make: send its link and the Actor streams it to disk (no memory limit in your workflow), continues an interrupted download where it stopped, and explains Drive or storage refusals (drive_not_shared, drive_quota, link_expired, link_invalid) instead of transcribing an error page. Measured on 2 October 2026 with NASA press-conference videos behind signed links, at the default 1 GB memory: 100 MB / 40 min in 2.4 minutes, 250 MB / 55 min in 4.3 minutes, 500 MB / 43 min in 2.6 minutes, from start of the run to the finished transcript. Every row has sourceFileId (yours, or derived from the link) and runId. Set resumeStore (any name) and a retried workflow gets the finished transcript back without paying again (reused: true); if the first run is still going, the retry waits for it.

Retry only what may work later

Every free failure row has retryable: true when the same input may work if run again later (YouTube or the host was busy, a network error, a time limit, a Drive download quota, your spending limit), false when it will not until the input changes (no speech, private, removed, not a media file, too long for your maxMinutesPerFile). When a run has retryable failures, it saves RETRY_INPUT in its key-value store: your input with urls set to just those links (feeds, dataset and uploads removed, so nothing done is transcribed twice), and SUMMARY.retry lists them. In n8n or Make, read https://api.apify.com/v2/key-value-stores/<defaultKeyValueStoreId>/records/RETRY_INPUT and start a new run with it as the input, e.g. an hour later.

In a mixed batch, SUMMARY also says which failed files need new input and which may work later: failuresByReason counts the failed files by errorType, filesNeedNewInput is how many of them will not work until the input changes, and failureHint is the same one-line next step as in the run's status message. For the files that need new input, read each row's error and change the input (a web page instead of a media file, a private or removed file, a folder or sign-in link); they are not put into RETRY_INPUT, so a retry run only gets the links that may work later. A file without speech (no_text) is not a failure: it is counted on its own in SUMMARY.noSpeech (filesWithoutSpeech), never in these counts and never in RETRY_INPUT. A limit_reached row is the run's stop, not a file failure: continue with SUMMARY.remainingInputs and the REMAINING_INPUT record.

Long recordings and batches: the synchronous endpoint waits at most 300 seconds. In our tests a 26-minute MP3 took 109 seconds and a 74-minute episode with speaker labels 195 seconds. For longer files or many files, start the run with POST https://api.apify.com/v2/acts/tidytools~audio-transcriber/runs, check GET https://api.apify.com/v2/actor-runs/<run id>?waitForFinish=60 until status is SUCCEEDED, then read GET https://api.apify.com/v2/datasets/<defaultDatasetId>/items. If a synchronous request times out, the run keeps going and its results stay in your Apify account.

Use with AI agents (MCP)

Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/audio-transcriber) to Claude, Cursor or any MCP client, then ask e.g. "Transcribe the last 2 episodes of this podcast feed and give me the chapters".

Minimal input:

{ "urls": ["https://example.com/episode.mp3"] }

Failed or skipped items are not charged and carry an errorType, so an agent can see at a glance what worked.

Scheduled podcast transcription (only new episodes)

{
"podcastFeeds": ["https://changelog.com/news/feed"],
"maxEpisodesPerFeed": 1,
"newEpisodesOnly": true,
"monitorName": "changelog-news"
}

Run it on an Apify schedule (e.g. weekly). The first run transcribes the newest episode; each later run transcribes only episodes it has not transcribed before (in our test, the second run skipped "Bitwarden CLI compromised" and took the next one). Runs with the same monitorName share the list, which is kept in a named key-value store (audio-transcriber-<monitorName>). When there is nothing new, the run ends without charges. Failed files are not remembered, so they are tried again next time.

Chaining with other Actors

Set datasetId to the dataset of another run (for example a podcast or video scraper). The media URL field is found automatically (audioUrl, mediaUrl, videoUrl, url, ...), or set it with datasetField, e.g. media.audioUrl (a dot path, for nested fields).

Or paste the rows into datasetItems — the array a dataset's API or its Export button gives — when you have the data but not the dataset ID:

{
"datasetItems": [
{ "episodeTitle": "Interview", "audioUrl": "https://example.com/ep1.mp3" },
{ "name": "Clip", "videoUrl": "https://example.com/clip.mp4" },
{ "note": "no media here" }
]
}

Every row is read on its own: the same field detection as datasetId finds the media link (audioUrl, videoUrl, or any field whose value is a media file link), or datasetField names the field for all rows (dot paths such as media.url work; a row that is itself a link works too). The links are billed per audio minute like any file — no new price. Two things to know:

  • A row without a usable link is one free invalid_input row that names its index, e.g. datasetItems[2] — the other rows are transcribed as usual.
  • Duplicate media is transcribed once (a link already in urls or the dataset, or the same link in two rows), and the other fields of the pasted rows (titles, ids, ...) are not kept in the results: match rows back by their url.

Subtitles in other languages: pass the srtUrl or vttUrl of a result to our Bulk Text & JSON Translator (subtitleUrls). It translates the subtitles cue by cue, keeps every timestamp, and returns new SRT/VTT files in any language, at $1.50 per million characters. Speech has about 1,000 characters per minute, so that is roughly $0.0015 per audio minute and language (in our test, 20 minutes of subtitles into Spanish and Traditional Chinese cost $0.059).

Limitations

  • The transcript stays in the spoken language: the turbo model does not translate. Without a language setting, each file's language is identified from short samples (the middle of the recording, then its start) before it is transcribed, and Whisper is guided in that language. For a recording that switches between languages, set language to the main one.
  • Chinese characters follow the audio: in our tests a mainland Mandarin podcast came out in Simplified characters and a Taiwanese one mostly in Traditional, with some Simplified mixed in. Podcast feeds that declare Traditional Chinese (zh-TW, zh-HK) and a vocabulary written in Traditional characters steer the output to Traditional; the text is not converted between the two.
  • Download speed depends on the host. When a host sends a large file slowly, it is downloaded in 4 parts at once (if the host allows it); some podcast ad-insertion services are still slow (in our test a 46 MB episode needed about 3 minutes to download, before the transcription). For subtitles in other languages set subtitleLanguages (translated SRT/VTT, $0.002 per minute per language); for the text itself, use our Bulk Text & JSON Translator.
  • Speaker labels are numbers (Speaker 1, 2…), not names. Short interjections ("Yeah.") are sometimes given to the wrong speaker, and speaker labels are not available for every language (Chinese is not). When a speaker change is detected a few words late ("…Welcome to | the podcast. Thank you"), those words are moved back to the end of the previous speaker's sentence.
  • Segments that Whisper marks as probably not speech (its no-speech probability) are dropped, together with typical filler it invents over music or silence ("Thanks for watching!"); the count is in segmentsFiltered.
  • Podcast hosts often insert ads when the file is downloaded; those minutes are part of the file and are billed. maxMinutesPerFile uses the duration from the feed for podcast episodes.
  • Long recordings are cut into pieces of about 90 seconds at the quietest moment nearby; a word at a cut can occasionally be lost. Whisper sometimes skips several seconds of speech inside a piece: every stretch of 5 seconds or more without text is transcribed again on its own, and what is found there is added (SUMMARY.segmentsRecovered; no extra charge).
  • Publisher transcripts are the publisher's own text: their wording, timing and speaker names are used as they are (only checked for being complete and matching the episode length). They describe the publisher's version of the file, which may differ slightly from the file you download when ads are inserted.
  • Google Drive allows a limited number of downloads per file per day; when it is reached the row says so (errorType: "drive_quota", free). Dropbox temporary links expire after 4 hours and presigned URLs at the time set when they were made: create them right before the run (2+ hours for large files).
  • Uploaded files are read from your key-value store by the Actor; if a record cannot be read (errorType blocked), upload it again with the file upload field or pass a public or signed link to the file.
  • YouTube links: no speaker labels or word timings, no playlist or channel expansion, at most 240 minutes per video, and YouTube access can pause for a few hours after a YouTube challenge (those rows are free; retry later). See YouTube videos.
  • Loom and Wistia links: public media only (no sign-in, no passwords). SoundCloud links are not supported. If a host changes its player, those links return a free row until we update the Actor.
  • TikTok links: public videos only, and only the creator's original sound (videos with licensed music are a free row). Profile links are not expanded. If TikTok changes its page or shows a verification page, those links return a free row. See TikTok videos.
  • Instagram links: public reels and video posts only; photo and carousel posts, profiles and stories are not transcribed (free rows). If Instagram changes its embed page or refuses the request, those links return a free row. See Instagram Reels.
  • Streamable and Reddit (v.redd.it) video links: public videos only. A Streamable video that is not ready yet is a free service_busy row; Reddit post pages are not read (pass the video's v.redd.it link). If either host changes its player, those links return a free row until the Actor is updated. See Streamable and Reddit videos.
  • Keyword search finds the words as transcribed: a name that Whisper spells differently is not found (add it to vocabulary so it is spelled as you search it, and use * for word endings).
  • Accuracy depends on audio quality, accents and background noise.

What's new (October 2026)

  • Paste another Actor's dataset rows directly (datasetItems): each row is read on its own (its media link found automatically, or named with datasetField, dot paths work), rows without a link are free error rows that name their index, and duplicate media is transcribed once.
  • Public TikTok video links can now be transcribed: paste the video URL.
  • Public Instagram Reels and video posts (/reel/, /p/, /tv/) can now be transcribed. Photo and carousel posts are free no_media rows, private or removed reels free private_media or not_found rows, and profile, story and share links free unsupported_platform rows.
  • A reel with no speech whose sound is Instagram library music is a free no_text row that says so.
  • Streamable and Reddit video links can now be transcribed.
  • Silence, music and background noise no longer turn into invented text: both engines now use stricter decoding settings.
  • Price unchanged: $0.006 per audio minute; failed, blocked and empty files are free.

FAQ

What if a voice-note URL expires or requires authorization headers? Generate a fresh direct download URL in your n8n / uazapi / Evolution API workflow immediately before starting the Actor, with enough validity for the download. If the URL has expired, generate a new one and run that input again; the failed row is free. urls cannot send custom Authorization headers or cookies to the media host. If the host only serves authenticated requests, first put the audio in storage that provides a direct, time-limited download URL, or upload the file through Or upload audio / video files (audioFiles) in Apify Console. Sending an authenticated API endpoint alone will not make the Actor use your n8n credentials.

Why did my Google Drive, Dropbox or OneDrive link fail? The file must be shared as "anyone with the link" (Drive: Share, General access, Anyone with the link). A link that asks for a sign-in comes back as a free row with errorType: "drive_not_shared" and says so; share the file and run that link again. Drive also limits downloads per file per day (drive_quota, free, retry later). The same run can mix Drive links with other files.

Why did my YouTube link come back without a transcript? Every such row is free and says why: no speech in the video (no_text), YouTube access paused for a few hours or the audio could not be fetched (download_failed / service_busy, retry later), or the video is longer than maxMinutesPerFile (240 minutes unless you set it lower; too_large). A video in another language than the language you set is transcribed anyway, with a languageNote. Videos that already have captions are cheaper with the YouTube Transcript Scraper.

Does the Actor collect usage data? The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool. For file links it also counts the kind of host (podcast host, cloud storage, CDN...), the host's main domain (for example buzzsprout.com, never the full address, path or query) and which download route worked, so we can see which hosts refuse downloads. No URLs, file names, content or account data.

Why was my file blocked? The file host refused the download: from Apify's network, with a browser User-Agent and from our own servers (the row's downloadAttempts lists each answer). Check the link opens in a private browser window without signing in. Many hosts limit how many files one network may download in a short time: if earlier files of the same host worked, run the RETRY_INPUT record later, or run fewer batches at the same time. Files that need a sign-in or cookies cannot be downloaded.

Which speech to text model does it use? OpenAI's open Whisper large-v3-turbo model, with automatic language detection and 90+ languages. Speaker labels, when turned on, come from nova-3.

Fast or accurate: which transcription engine should I pick? Both run OpenAI's Whisper large-v3-turbo and cost the same $0.006 per minute.

  • "transcriptionEngine": "fast" (default): Cloudflare Workers AI. The quickest results, about twice as fast per piece as Accurate.
  • "transcriptionEngine": "accurate": Whisper on our own server with more thorough decoding. In our English test it made fewer errors (word error rate 3.5% against 9.9%) and none of the repeated phrases that Fast sometimes produces, but it takes about twice as long per piece. When it is busy, pieces fall back to Fast automatically; each row's asrBackend (whisper-local, workers-ai or mixed) shows which one was used.
  • Pick Accurate for interviews, lectures or anything you will publish or quote; keep Fast for search, monitoring and quick drafts. Speaker labels always use nova-3, and YouTube links always use our YouTube service's Whisper.

How much does audio to text cost? $0.006 per minute ($0.36 per hour), no start fee. SRT and VTT subtitles, paragraphs and timestamps are included; files with no speech are free.

Can it transcribe new podcast episodes automatically? Yes. Paste the podcast RSS feed, turn on newEpisodesOnly and run it on a schedule: only episodes released since the last run are transcribed, so a day without a new episode costs nothing.

Can I transcribe files over 25 MB in n8n or Make? Yes. Send the file link instead of the file: files up to 2 GB and any length work, with no OpenAI key. See Use in n8n, Make or Zapier.

Can I turn a video into text and subtitles? Yes. MP4, MOV, MKV, WEBM and more: the audio track is extracted automatically, and every file gets text, timestamps and SRT/VTT subtitle files.

Can it transcribe YouTube videos? Yes. Paste the video link: the audio is transcribed at $0.006 per minute, with timestamps and SRT/VTT subtitles. For videos that already have captions, the YouTube Transcript Scraper is cheaper.

Can it transcribe Loom or Wistia links? Yes, public ones: paste the share link and the file of the host's public player is transcribed at $0.006 per minute. Private or password-protected videos are free rows that say so. SoundCloud and Vimeo page links are not supported.

Can it transcribe TikTok videos? Yes, public ones: paste the video link (or the short link from the Share button) and the video's original sound is transcribed at $0.006 per minute. Videos whose sound is licensed music, private and removed videos are free rows that say why. Profile links are not expanded.

Can it transcribe Streamable or Reddit videos? Streamable: yes, paste the share link (streamable.com/...) and the public player's MP4 is transcribed at $0.006 per minute; a video that is still uploading or processing is a free row saying to run it again later. Reddit: v.redd.it video links and their HLS playlists are transcribed from the video's audio track; Reddit post pages are not read (Reddit's robots.txt does not allow it), so pass the video's v.redd.it link, its direct audio file URL, or a Reddit scraper Actor's dataset.

Can it transcribe Instagram Reels? Yes, public ones: paste the reel link (instagram.com/reel/...) and its sound is transcribed at $0.006 per minute, with the caption in mediaTitle. Photo posts, private and removed reels are free rows that say why. Profile and story links are not expanded, and no account data is collected.

Do Google Drive / Dropbox links work? Yes, when the file opens without signing in. Google Drive: Share > General access > "Anyone with the link"; file links in any form work (/file/d/.../view, open?id=, uc?id=, with or without resourcekey=), files over 100 MB too, and a public folder link transcribes every audio and video file directly in it (subfolders are not opened). Dropbox: Share > "Copy link" with "Anyone with the link can view"; pass the whole link including rlkey= (?dl=0 is fine). OneDrive / SharePoint: "Anyone with the link can view" with "Block download" off. Box: shared link for "People with the link". WeTransfer and iCloud Drive share links work too. When a link cannot be read, the row is free and says exactly what to change: drive_not_shared / not_shared (set the sharing as above), folder_link (a Dropbox or OneDrive folder, or a ZIP: pass each recording), drive_quota / share_quota (too many downloads today: run again later), not_found (deleted or incomplete link). A Google Docs file or a "My Drive" page address is not a recording. Files from a company account that does not allow public links: upload them with audioFiles.

Can I find where my brand or a topic is mentioned? Yes. Add searchTerms (e.g. ["Apify", "web scraping"]): every mention comes with its timestamp, sentence, speaker and a link to that moment, and the whole run's mentions are in KEYWORD_MATCHES.csv. No extra charge.

What are the limits? Up to 2 GB per file, any length, and up to 1,000 files per run. You can cap the cost with Max minutes per file, Max total minutes per run and Apify's Maximum cost per run; files over a cap are skipped for free.

My run stopped with limit_reached rows. What now? The run reached your Maximum cost per run or your Max total minutes per run. Those rows and every file that was not started are free: nothing is charged for a file that was not transcribed. The status message and SUMMARY.limitReached (filesProcessed, filesRemaining, message) say how many files are left; their links are in SUMMARY.remainingInputs, and the REMAINING_INPUT record in the run's key-value store is your input with only those links. To finish them, raise Maximum cost per run or Max total minutes per run, or upgrade your Apify plan (or wait for the monthly credit reset), then start a run with REMAINING_INPUT as the input. Do not re-run the full original input: finished files would be transcribed and charged again, unless newEpisodesOnly or resumeStore is on. See How far does the free plan go?.

How fast is it? In our tests an 8-minute MP4 took 33 seconds, a 26-minute MP3 109 seconds and a 74-minute episode with speaker labels 195 seconds. In a field test of public podcasts (October 2026), 68- to 102-minute episodes took 5 to 7 minutes each, about 12 to 15 times faster than real time; a slow podcast host can add minutes of download time. Three files are processed at the same time by default (up to 10 with fileConcurrency).

Is it legal to transcribe audio? Transcribe recordings you own or have permission to use, and follow the source's terms and copyright. The Actor only downloads links you give it that open without logging in; it does not get past logins or paywalls. This is not legal advice.

Does it work with the API, webhooks, Make, n8n or Zapier? Yes. Every run can be started from the Apify API, a schedule, a webhook or the Apify apps for Make, n8n and Zapier, and from AI agents through MCP. One HTTP request is enough; see the examples.

Quick fixes for common first-run results

Why is my row no_text? The downloaded file has no recognizable speech (for example, silence or music). Try a recording with clearly spoken words. The row is free.

Why do I see blocked or drive_not_shared? Open the full link in a signed-out browser window. For Drive, allow "Anyone with the link"; if your organization forbids that, upload the file using audioFiles. We do not sign in, use cookies or bypass access checks. These rows are free.

Why do I see too_large or download_failed? Check maxMinutesPerFile and use a current, directly downloadable media link. A host that temporarily refuses downloads may work when retried later. A file that was not transcribed is free.

Why did I get limit_reached? Your run cost cap or maxTotalMinutes stopped new files. The unprocessed rows are free; use REMAINING_INPUT after raising the limit, rather than rerunning files already charged.

When am I not charged? Failed, blocked, silent, skipped and unprocessed files have no audio-minute charge. A successful transcript is billed by started audio minute; optional speaker labels replace that rate, while summaries and translated subtitles add their listed charges only when enabled and successful.

Support

Open an issue in the Issues tab with the audio URL. Issues are checked regularly.

Found this useful? If the transcript saved you time, a short review on the Store helps other users find it.