Audio & Video Transcriber — Speech to Text API
Pricing
from $9.00 / 1,000 audio minutes
Audio & Video Transcriber — Speech to Text API
Convert speech to text from any public audio or video URL: podcast episodes, MP3, WAV, M4A or MP4 files and video pages on other sites. Get timestamps, SRT/VTT subtitles, speaker labels and RAG-ready JSONL with source times. Up to 4 hours per file and 1,000 URLs per run. No speech API key needed.
Pricing
from $9.00 / 1,000 audio minutes
Rating
0.0
(0)
Developer
Sergey Andronik
Maintained by CommunityActor stats
0
Bookmarked
20
Total users
8
Monthly active users
13 hours ago
Last modified
Categories
Share
Convert speech to text from any public audio or video URL. Audio & Video Transcriber is a speech-to-text API for podcast episodes, MP3, WAV, M4A and MP4 files, and video pages on other sites. It transcribes the audio itself with AI speech-to-text, so it works on recordings without captions. Each URL becomes one result with the full text, timestamps, SRT and VTT subtitles, optional speaker labels and optional RAG-ready passages that keep the source URL and original timestamps. Send one URL or up to 1,000 per run, with recordings of up to four hours. No speech-provider API key is needed.
Which Actor fits your link?
This Actor accepts any public HTTPS audio or video URL. For the three big video platforms, the dedicated Actors below return the same transcript output and cost less:
| Your links | Best Actor | Why |
|---|---|---|
| Podcast episodes, MP3/WAV/M4A/MP4 files, other sites | This Actor | Direct file links skip the download fee. |
| YouTube videos | YouTube Transcript | By default returns the video's caption track for $0.005 per video, and uses AI speech-to-text only when there is none. |
| TikTok videos | TikTok Video Transcript | $0.005 download and $0.008 per minute, against $0.02 and $0.01 here. |
| Instagram Reels | Instagram Reel Transcript | $0.005 download and $0.005 per minute. |
YouTube, TikTok and Instagram links still work here, at this Actor's prices.
What you get
- Transcript text in
text, plustranscript_llmwith one line per segment for LLM prompts. - Timestamps per segment, or per word with
timestamps: "word". - SRT and VTT subtitles in the result and as downloads in the run's key-value store,
with an optional subtitle layout and QA report (
subtitleProfile). - Readable paragraphs in
paragraphs(start_s,end_s,speaker,text) and astranscript-000.txtandtranscript-000.mddownloads, at no extra charge. See Readable output. - Speaker labels with
diarize: true. - RAG passages with
exportRag: true: transcript passages with the source URL, original start and end seconds and versioned IDs, inline asrag_chunksand as atranscript-000.rag.jsonldownload. - Intervals: transcribe only part of a recording with
startTimeandendTime; timestamps stay relative to the original recording. - Names and terminology: up to 100
glossaryphrases to guide a compatible engine. - Billing per item: every row shows which events were charged.
How to transcribe audio or video to text
- Paste your URLs. Use public HTTPS links: a direct media file, a podcast episode page, a video page on another site, or a Google Drive or Dropbox share link to an audio or video file.
- Choose the output. Keep segment timestamps for subtitles. Turn on speaker labels or RAG passages if you need them.
- Set a run budget. In the run options, set a maximum charge for the run.
maxTotalChargeUsdis a run option, not an input field. The run stops before work it cannot pay for. - Start the run and open the Dataset. Each URL becomes one row. Download SRT, VTT and JSONL files from the run's key-value store.
Try it with a short recording
Open the RAG Task or paste this into the Input JSON editor:
{"urls": ["https://storage.googleapis.com/cloud-samples-data/speech/commercial_mono.wav"],"timestamps": "segment","exportRag": true}
This is a 45-second public speech sample. Set the run's maximum charge to $0.10 for a
first try. In the finished run, open the Dataset and look at text, segments and
rag_chunks, then download transcript-000.srt and transcript-000.rag.jsonl from
Storage; 000 is the URL's position in the input, starting at zero.
You can also inspect the RAG input, the sample passages and an earlier hosted transcript JSON, SRT and VTT without starting a run. The Task guide covers transcripts, speakers, intervals and subtitle presets.
Input
| Field | What it does |
|---|---|
urls | Up to 1,000 public HTTPS audio or video URLs, up to 8,192 characters each. Required unless you set datasetId. |
datasetId | Read URLs from another run's dataset. See Chain from another Actor. |
datasetUrlField, maxItems | The dataset field that holds the URL (detected when empty), and how many rows to read (default 100, at most 1,000). |
exportRag | Adds rag_chunks and a .rag.jsonl download. Needs segment or word timestamps. |
language | Optional language hint such as en, ru or pt-BR. Omit it for automatic detection. |
timestamps | none (text only: no segments, words, SRT or VTT), segment (default) or word. |
diarize | Speaker labels, billed at the speaker-label rate. Labels from separately processed chunks of a long recording do not identify the same person; check speaker_scope. |
subtitleProfile | standard (42 characters per line, 1–7 s cues) or short (28 characters per line, 0.5–4 s cues), with a subtitle QA report. Longer segments are split into cues within their time range. Needs segment or word timestamps. Leave it out for the plain layout without a report. |
startTime, endTime | Transcribe only this interval, in seconds. The whole source is still downloaded. |
glossary | Up to 100 names or terms, 1–80 characters each and 500 bytes in total. Glossary requests use Deepgram Nova-3. |
provider | Pin one speech engine instead of automatic routing: groq/whisper-large-v3, groq/whisper-large-v3-turbo, openai/gpt-transcribe, openai/whisper-1, openai/gpt-4o-mini-transcribe, openai/gpt-4o-transcribe-diarize or deepgram/nova-3. A pin never switches engines; combinations it cannot serve fail with an error. |
The advanced reference covers engine compatibility, subtitle QA and recovery in detail.
Start from a podcast feed
Put RSS or Atom feed URLs, or Apple Podcasts show pages, in Podcast feeds (feedUrls) to transcribe the newest episodes:
{"feedUrls": ["https://feeds.simplecast.com/Sl5CSM3S", "https://podcasts.apple.com/us/podcast/the-daily/id1200361736"],"maxItemsPerSource": 3,"publishedAfter": "2026-10-01"}
- An Apple Podcasts show page is resolved to its public feed through Apple's lookup API. An episode link (
?i=…) is rejected: pass that episode's audio URL inurls. - Episodes are taken newest first by publication date. Each episode's audio or video file is transcribed like a direct media URL, so there is no platform download fee. Each row adds
source_url,source_type,source_title,episode_title,episode_guidandpublished_at. publishedAfter(YYYY-MM-DD, UTC) leaves out older episodes; episodes without a date are left out too when it is set.- Feeds are downloaded with the same safety checks as media links (public addresses only, 32 MB at most). Feed URLs are shown without their query, and long token-like parts of their path (20 or more URL-safe characters before any file extension, unless they are lowercase words joined by hyphens or underscores) appear as
***, so a private subscriber token stays out of the results and error messages. Episode media URLs are shown as the feed lists them. maxItemsPerSource(default 20, at most 200) limits how many of the newest items each source contributes. A run holds at most 1,000 items in total, countingurlsand dataset rows.- Each listed item is processed and charged exactly like a URL you submit. Listing itself is free.
- The example link in the URL list is processed and charged too: remove it when you want only listed items.
- Listed items run after
urlsand dataset rows, source by source in input order; an item already in the run is skipped. - A source that cannot be listed becomes one error row with
source_urland anerrornaming it (for examplefeedUrls[1]: …), and it is not charged. The other sources continue. If no source lists anything, the run fails before any charge. - The listing is saved when the run starts, so a restarted run keeps the same items even if the source changed meanwhile.
Scheduled runs: only new items
Turn on Skip items processed by earlier runs (skipPreviouslyProcessed) and run the
Actor on a schedule to get only what is new
since the last run.
- The Actor keeps a key-value store named
polyglot-processed-transcriberin your Apify account, orpolyglot-processed-transcriber--<memoryKey>when you set Memory name (memoryKey), so separate schedules can keep separate memories. Other Actors keep their own stores, even with the samememoryKey. It records each item after the item is delivered and charged; failed items are tried again next time. - It applies to every URL in the run: listed ones, dataset rows and the items listed from sources.
- When nothing is new, the run ends without any charge. Only error rows appear then, for sources or dataset rows that could not be used.
- If the store cannot be opened or read, the run stops before any charge, and the next scheduled run tries again. If an item's record cannot be written, the item is still delivered and the log says so; a later run may process and charge it again.
- Delete the store in Apify Console (Storage → Key-value stores) to start over. Do not run two runs with the same memory at the same time: both would process the same new items.
Chain from another Actor
Run a podcast, TikTok or Instagram scraper first, then paste the dataset ID of that run into Dataset ID
(datasetId) to transcribe every one of its audio or video links:
{ "datasetId": "<dataset ID from the other run>", "maxItems": 200 }
- The Actor reads up to
maxItemsrows (default 100) with your own run's Apify token and takes each row's URL fromwebVideoUrl,url,postUrl,videoUrl,inputUrl,link,audioUrl,mediaUrl,downloadUrlor an InstagramshortCode, or from the field you name indatasetUrlField. - Dataset URLs run after any
urlsyou list, in dataset order; a dataset URL that is already in the run is skipped. A run takes at most 1,000 URLs in total. - A row without a usable URL becomes an error item with its
dataset_rowindex, and it is not charged. Items from the dataset also carrydataset_row, so you can join the results back to the source rows. - The example link in the URL list is processed and charged too: remove it when you want only the dataset's items.
Output example
A real hosted result for the speech sample above, trimmed to 2 of 8 segments, with the text, SRT and VTT shortened:
{"url": "https://storage.googleapis.com/cloud-samples-data/speech/commercial_mono.wav","text": "Okay, I'm here. Hi, I'd like to buy a Chromecast and I was wondering whether you could help me with that. …","language": "en","duration_s": 45.3,"engine": "groq/whisper-large-v3","segments": [{ "t0": 0, "t1": 3, "text": "Okay, I'm here." },{ "t0": 3, "t1": 9, "text": "Hi, I'd like to buy a Chromecast and I was wondering whether you could help me with that." }],"srt": "1\n00:00:00,000 --> 00:00:03,000\nOkay, I'm here.\n\n…","usage": { "minutes": 1, "diarized": false, "platform_fetch": false },"billing": {"status": "paid","events": [{ "event": "audio-minute", "requested_count": 1, "charged_count": 1, "state": "confirmed" }]}}
With exportRag: true, each item also has rag_chunks. Each passage looks like this
(identity hashes shortened):
{"id": "p1","text": "Okay, I'm here. Hi, I'd like to buy a Chromecast …","start_s": 0,"end_s": 42.66,"source_url": "https://storage.googleapis.com/cloud-samples-data/speech/commercial_mono.wav","document_id": "doc_<sha256>","transcript_version": "transcript_<sha256>","chunker_version": "rag-v2","timing_basis": "segment"}
A URL that fails returns a row with url and error. Very large results may carry
result_record_key instead of inline text; read that key from the run's key-value store
and use its value. artifact_errors lists any download that could not be saved.
Readable output
Every transcript row has paragraphs: the transcript in order, grouped into blocks you can
read. A paragraph starts at a speaker change, after a pause of 2 seconds or more, and
before it would pass 800 characters or 90 seconds. Once it holds 400 characters, the next
sentence end closes it. No text is dropped or reordered, and a segment is never split in
timed output. Each paragraph is { "start_s", "end_s", "speaker", "text" }; speaker appears
only with diarize: true, and with timestamps: "none" there are no times and paragraphs
are cut at sentence ends by length alone. Rows without speech have no paragraphs.
The same paragraphs are saved to the run's key-value store, numbered by input position:
transcript-000.txt: paragraphs separated by blank lines, withS1:style speaker labels.transcript-000.md: a title (the video title when known), a list with the source URL, channel, language and duration, then each paragraph with its[mm:ss](or[h:mm:ss]) start time and bold speaker label.transcript-000.translated.txtand.mdwhen translated segments exist.
When a row would pass the Dataset size limit, paragraphs is left out of the row first
(the text stays) and the downloads still hold it. Both downloads are free, like SRT and VTT.
Use the transcripts for RAG and search
- Embed or index each passage's
textin your own system, and keepsource_url,start_sandend_swith it so answers can cite the recording. - Use
document_id:transcript_version:chunker_version:idas the index key. When you index a new version of a document, replace all its old passages. - Passages follow sentence boundaries, are at most 1,200 characters, and can merge
nearby segments of the same speaker.
timing_basissays whether a passage's times come from segments, matched words or an approximate segment range. Times are never invented from text length. - Check every item's
error,stop_processing,billingandartifact_errorsbefore indexing. ASUCCEEDEDrun alone does not mean every item is usable.
The Actor does the transcription and passage step. Embeddings, storage, retrieval and answer generation stay in your stack. The RAG tutorial walks through the handoff.
How much does speech to text cost?
Pay per event, with no subscription. These are the Free-plan prices; paid Apify plans get lower per-minute prices. The Pricing tab shows the current prices for your plan.
| Event | Price | When |
|---|---|---|
| Run setup | $0.005 | Once per run. |
| Platform download | $0.02 | Per page URL whose media was downloaded, for example a podcast page, a video page, an extensionless link or an HLS stream (.m3u8). Direct file links ending in .mp3, .wav, .m4a, .mp4 and other media file extensions skip it. |
| Audio minute | $0.01 | Per started minute of the selected interval, after transcription succeeds. |
| Diarized audio minute | $0.02 | Per started minute with speaker labels, instead of the audio minute. |
Worked examples, without speaker labels:
| Recording length | Direct file, 1 URL | Direct files, 100 URLs | Page link, 1 URL | Page links, 100 URLs |
|---|---|---|---|---|
| 1 minute | $0.015 | $1.005 | $0.035 | $3.005 |
| 3 minutes | $0.035 | $3.005 | $0.055 | $5.005 |
| 10 minutes | $0.105 | $10.005 | $0.125 | $12.005 |
For example, 100 direct files of 10 minutes cost $0.005 + 100 × 10 × $0.01 = $10.005. A 60-minute podcast MP3 costs $0.005 + 60 × $0.01 = $0.605, or $1.205 with speaker labels.
- Minutes are rounded up once per file, and silence counts.
- A recording with no detected speech (only music, silence or noise) returns
no_speech: truewith empty text and is not charged minutes, up to 30 such minutes per run; after that its minutes are charged. A page link still pays the platform download fee. - With
startTimeandendTime, only the selected minutes are charged; the platform download fee still applies to page links. - A successful platform download stays charged if the transcription fails afterwards. A download that is not a playable audio or video file, or is longer than four hours, is not charged.
- RAG passages, subtitles and the QA report cost nothing extra.
- Optional AI text add-ons, generated by Anthropic's Claude from the transcript:
analysis (summary, chapters and action items together) $0.015 per URL,
translation $0.015 per URL, keywords $0.008 per URL. Each is charged only after it
succeeds. A transcript too long for an add-on's cost limit (about an hour for
analysis, about 15 minutes for timed translation) returns an
_errorfield instead and is not charged. - Apify's own small run-start event is separate and is shown on the Pricing tab.
maxTotalChargeUsd caps the whole run, not each recording. If a start request gets no
answer, check your existing runs before you start another one.
Use it from the API, n8n or an AI agent
Start a run with the Apify API client for JavaScript and read the results:
import { ApifyClient } from 'apify-client'const client = new ApifyClient({ token: process.env.APIFY_TOKEN })const run = await client.actor('andronixmd/speech-to-text-transcriber').call({ urls: ['https://storage.googleapis.com/cloud-samples-data/speech/commercial_mono.wav'], timestamps: 'segment' },{ maxTotalChargeUsd: 0.1 },)const { items } = await client.dataset(run.defaultDatasetId).listItems()for (const item of items) console.log(item.url, item.error ?? item.text)
- API: the API guide shows how to start once, poll the status, read every Dataset row and fetch saved files.
- n8n: import the media-to-RAG workflow. It starts one transcription and emits one n8n item per passage. See the setup guide.
Use it from an AI agent (MCP)
Connect your agent to https://mcp.apify.com. It can find this Actor with search-actors, or
call it by name, andronixmd/speech-to-text-transcriber, with call-actor. Use fetch-actor-details first for the
input schema and pricing. Every call starts a new paid run, so always set
callOptions.maxTotalChargeUsd and keep the urls list short:
{ "actor": "andronixmd/speech-to-text-transcriber", "input": { "urls": ["https://storage.googleapis.com/cloud-samples-data/speech/commercial_mono.wav"], "timestamps": "segment" }, "callOptions": { "maxTotalChargeUsd": 0.1 } }
call-actor returns the run status and storage IDs, not the results. Read the rows with
get-dataset-items and the run's dataset ID. The fields to use are text, paragraphs and error.
With an Apify account, use your API token or MCP OAuth. Without one, an agent can buy a prepaid token from Apify AGI over x402 or MPP and use it as the Bearer token. It starts at $1, the balance is a hard spending cap, and the token expires after 14 days. This is experimental; see agentic payments.
Limitations
- Public recordings only. Private, login-only, DRM-protected and region-blocked media is not supported. The Actor uses no accounts or cookies and does not try to get around access checks.
- Podcast feeds, not channels.
feedUrlslists RSS, Atom and Apple Podcasts shows. YouTube channels and playlists and TikTok profiles are listed by the YouTube and TikTok Actors in Related Actors; here, pass their video links. - Up to four hours per recording. That is a processing limit, not an accuracy promise for long recordings.
- Not every page downloads. Sites change and some refuse automated downloads, so
some URLs return an error row. Check each row's
errorandbillingfields. - Speaker labels are per chunk on recordings that are processed in parts.
FAQ
Which audio and video formats work?
Direct links to common media files, including MP3, WAV, M4A, AAC, OGG, OPUS, FLAC, MP4,
MOV, MKV and WEBM, and public pages the downloader supports, such as podcast episode
pages and X posts. HLS stream links (.m3u8) work too and are billed as page links.
Can I use Google Drive or Dropbox links? Yes, for a single file shared with "Anyone with the link". The Actor turns the share link into the provider's direct download link and bills it as a direct file, without the download fee. Folders are not supported. Google Drive shows a virus-scan page instead of the file for large files it cannot scan; those rows fail with a clear error, so use a direct link for them.
Which languages are supported?
The language is detected automatically, and support depends on the engine. Pass a hint
such as en, ru or pt-BR when you know it.
Can I transcribe a whole podcast feed?
Yes. Put the feed URL or Apple Podcasts show page in feedUrls and set
maxItemsPerSource. With skipPreviouslyProcessed on a schedule, each run transcribes
only the new episodes.
Should I use this Actor for YouTube, TikTok or Instagram? It works, but the dedicated Actors in the table at the top are cheaper for those links.
Do you store my recordings? Results stay in your Apify run storage, under your account's access and retention settings. The audio is sent to the speech-to-text provider that transcribes it. Local working files are removed, but saved outputs and processing journals stay in the run storage. Only submit recordings you are allowed to process.
Related Actors
- YouTube Transcript: YouTube captions, with AI speech-to-text when a video has none.
- TikTok Video Transcript and Instagram Reel Transcript: the same transcripts for short vertical video, at lower prices.
- YouTube Video Scraper, TikTok Video Scraper and Instagram Reel Scraper: views, likes, hashtags and other video data without a transcript.