Speech to Text API: Audio to Text & Video to Text, Whisper avatar

Speech to Text API: Audio to Text & Video to Text, Whisper

Pricing

from $8.50 / 1,000 basic audio minutes

Go to Apify Store
Speech to Text API: Audio to Text & Video to Text, Whisper

Speech to Text API: Audio to Text & Video to Text, Whisper

Audio transcription and video transcription API: transcribe audio, video, MP3, MP4, podcasts to text with Whisper speech to text. Podcast transcription from RSS feeds, meeting and interview transcription, voice to text, SRT/VTT subtitles, RAG chunks. From $0.01 per audio minute; silence is free.

Pricing

from $8.50 / 1,000 basic audio minutes

Rating

0.0

(0)

Developer

Saulius AutomatesIT

Saulius AutomatesIT

Maintained by Community

Actor stats

0

Bookmarked

64

Total users

13

Monthly active users

5 days ago

Last modified

Share

Audio transcription, audio to text and video to text with Whisper. Paste MP3, WAV, MP4 or video links, or a podcast RSS feed, and get transcripts, SRT/VTT subtitles, Markdown and RAG chunks in 90+ languages. From $0.01 per audio minute ($0.60 per hour). Silent, broken or unreachable files cost nothing.

  • Pay only for speech delivered. Each recording is billed by its length, rounded up to the minute, and only after its transcript is in your dataset. No speech, failed download or failed recognition: no audio charge.
  • Podcasts on autopilot. Point it at an RSS or Atom feed, switch on onlyNewEpisodes, save as a Task and schedule it. New episodes are transcribed once; old ones are skipped for free.
  • Six output formats. Plain text, timestamped segments, SRT, VTT, Markdown and source-linked RAG JSONL, optionally saved as downloadable files.
  • 90+ languages, auto-detected, plus optional translation of speech to English.
  • No API key and no third-party transcription service. Recognition runs inside the Actor.

Quick start

  1. Paste one recording URL into Media URLs (or a feed into Podcast RSS / Atom feeds).
  2. Leave Processing tier on Basic.
  3. Click Start. The transcript lands in the dataset; subtitles and files follow the formats you picked.

Try it on an 11-second public speech sample (costs one audio minute, $0.01):

{
"mediaUrls": ["https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"],
"model": "base",
"outputFormats": ["text", "segments", "srt", "vtt", "markdown", "rag"],
"downloadFiles": true
}

Ready-made starting points: Audio to text, Video to subtitles, Podcast RSS transcription, Audio to RAG chunks.

Pricing

Pay per audio minute. No subscription, no format or download fees.

TiermodelPer audio minutePer hour of audioBest for
Basic (default)base$0.01$0.60Clear speech: podcasts, interviews, lectures, meetings
Qualitysmall$0.02$1.20Accents, background noise, or when Basic misses too much
Maxmedium$0.04$2.40Difficult recordings where your own test shows it helps
  • Paid Apify plans get the Store discount on every tier: Bronze 5%, Silver 10%, Gold and above 15%.
  • Each recording is rounded up to a whole minute separately. A 10-second clip bills one minute.
  • Actor start: $0.00005 per GB of run memory (4 GB by default, so $0.0002 a run).
  • Not charged: silence (NO_SPEECH), failed downloads, expired links, failed recognition, and recordings over your own duration or size limit.
  • Cap spending with maxDurationMinutes (per recording), maxTotalMinutes (per run) or the run's Maximum total charge. The Actor stops before a recording would exceed the cap and keeps everything already delivered.
JobBasic tier cost
One 45-minute podcast episode$1.58
Four 60-minute episodes (a month of a weekly show)$8.40
100 customer calls of 10 minutes$35.00

What you can transcribe

SourceHow well it works
Direct audio/video files over HTTP(S) (MP3, WAV, MP4 and other common formats)Most reliable route
Podcast RSS 2.0 / Atom feeds with audio or video enclosuresReliable; up to 10 feeds, 25 newest episodes each
YouTubeUsually blocked: YouTube asks Apify servers to sign in. Each blocked link returns a free YOUTUBE_BLOCKED row naming YouTube Transcript Scraper, and the run still succeeds
Other sites supported by yt-dlpBest effort: site restrictions, geo blocks and expiry can stop a download. Use a proxy where needed

Already have YouTube captions? The YouTube Transcript Scraper reads them for $2.50 per 1,000 videos. Use this Actor when there are no captions or you need real speech recognition.

Output

One dataset row per recording. Formats appear only when selected:

{
"url": "https://example.com/episode-42.mp3",
"title": "Episode 42: Interview with ...",
"language": "en",
"languageProbability": 0.99,
"durationSeconds": 612.3,
"durationMinutes": 10.21,
"model": "base",
"wordCount": 1580,
"segmentCount": 142,
"text": "Full transcript text…",
"segments": [{ "start": 0.0, "end": 4.2, "text": "Hello and welcome…" }],
"srt": "1\n00:00:00,000 --> 00:00:04,200\nHello and welcome…\n\n..."
}

Feed transcripts also carry the podcast title, episode title and ID, feed URL and publication date. Recordings that fail get an error row with an errorCode, the processing phase and a recommendedAction. A run report (SUMMARY) in the key-value store counts what was requested, transcribed, skipped and charged.

What it looks like

Real Basic-tier output from a 33-second public test recording, recognition mistakes left in:

Actual Basic transcript, with recognition mistakes preserved

Timestamped SRT subtitle excerpt from the same recording

More: Markdown output, RAG JSONL output, and a 37-second walkthrough video.

Use cases

You are a…You use it to…
Podcaster or creatorTranscribe every new episode automatically for show notes, blog posts and clips
Video teamProduce SRT/VTT captions for accessibility and SEO
Researcher or journalistTranscribe interviews, lectures, briefings and calls
AI / RAG builderTurn audio and video into timestamped, source-linked chunks for search
Localisation teamTranslate foreign-language speech to English text

Input

FieldTypeDescription
mediaUrlsarrayAudio/video URLs. Provide these, rssFeedUrls, or both.
rssFeedUrlsarrayUp to 10 public RSS 2.0 or Atom feeds with audio/video enclosures.
maxEpisodesPerFeedintegerNewest matching episodes to inspect per feed: 1 (default) to 25.
publishedAfterstringOptional date, e.g. 2026-09-01. Undated episodes are excluded when set.
episodeTitleContainsstringOptional case-insensitive episode-title filter.
onlyNewEpisodesbooleanSkip feed episodes already delivered in earlier runs. Default false.
monitorNamestringRequired with onlyNewEpisodes; a stable name of 1–80 characters. Older inputs sending monitorKey keep working and resume the same checkpoint.
modelstringbase (Basic, default), small (Quality) or medium (Max). Legacy tiny is still accepted and bills as Basic.
languagestringTwo-letter code (e.g. en, es); blank = auto-detect.
translatebooleanTranslate speech to English instead of transcribing.
outputFormatsarraytext, segments, srt, vtt, markdown, rag. Default: text + segments.
downloadFilesbooleanSave the selected formats as files in the run's key-value store. Default false.
ragChunkWordsintegerMaximum words per RAG chunk: 50–1,000; default 250.
ragStrategystringsegments (default, keeps existing IDs) or sentences for sentence-aware grouping.
ragOverlapWordsinteger0–100 words of repeated context, sentence mode only. Default 0.
paragraphsbooleanAdd paragraphText and paragraph breaks in TXT. Default false.
shareDownloadLinksbooleanCreate signed single-file links. Anyone holding a link can read that file. Default false.
wordTimestampsbooleanAdd per-word timestamps.
maxDurationMinutesintegerSkip media longer than this (cost guard).
maxTotalMinutesintegerOptional run-wide cap on billed minutes.
maxFailedItemsintegerStop after this many failed items (default 3, maximum 20).
maxDownloadMegabytesintegerPer-item download limit in MiB (default 512).
beamSizeinteger1 = fastest; higher = slightly more accurate.
proxyConfigurationobjectProxy for downloads (helps with geo limits). With the default Apify Proxy a download is tried direct first and falls back to the proxy; pick a proxy group or your own proxy to always use it.

Transcribe new podcast episodes automatically

{
"rssFeedUrls": ["https://example.com/your-podcast.rss"],
"maxEpisodesPerFeed": 1,
"onlyNewEpisodes": true,
"monitorName": "my-podcast-transcripts",
"model": "base",
"maxDurationMinutes": 60,
"outputFormats": ["text", "markdown", "rag"],
"downloadFiles": true
}

Save it as a Task and add a schedule. Each run checks the newest matching episodes; ones already delivered under the same monitorName and settings are skipped, and a run with nothing new charges no audio minutes. Raise maxEpisodesPerFeed if several episodes can appear between runs. A monitor remembers up to 5,000 delivered episodes. Changing transcription or export settings starts a separate checkpoint; use a new monitorName to reprocess on purpose.

Build an audio knowledge base

Choose outputFormats: ["text", "markdown", "rag"] and downloadFiles: true. Each RAG chunk has id, text, startSeconds, endSeconds, sourceUrl, sourceTitle, citationUrl and wordCount, ready to index in your own search or vector database. Chunk IDs are stable for the same source and text. YouTube citation links include a time offset. The Actor makes no embeddings, summaries or other AI calls.

Use it from code and automations

Python (pip install apify-client). Swap the sample URL for your own MP3, WAV, MP4 or video link:

from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("sauliusautomatesit/media-transcriber").call(run_input={
"mediaUrls": ["https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"],
"outputFormats": ["text", "srt"],
})
for item in client.dataset(run.default_dataset_id).iterate_items():
if item.get("errorCode"):
print("not transcribed (not charged):", item["url"], item["errorCode"])
else:
print(item["url"], item["durationSeconds"], "seconds:", item["text"])

run.default_dataset_id is for apify-client 3.x; on 2.x write run["defaultDatasetId"]. Pass max_total_charge_usd=1 to .call() to cap a run at $1.

JavaScript (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('sauliusautomatesit/media-transcriber').call({
mediaUrls: ['https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav'],
outputFormats: ['text', 'vtt'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
console.log(item.errorCode ? `not transcribed: ${item.errorCode}` : `${item.language}: ${item.text}`);
}

HTTP, one call that waits and returns the rows:

curl -X POST "https://api.apify.com/v2/acts/sauliusautomatesit~media-transcriber/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "mediaUrls": ["https://example.com/episode.mp3"], "outputFormats": ["text", "srt"] }'

For recordings longer than a few minutes, start the run asynchronously and read the dataset when it finishes; the synchronous call waits up to 5 minutes.

Works with the Apify node in n8n, the Apify module in Make, Zapier, and AI agents through the Apify MCP server (https://mcp.apify.com?tools=sauliusautomatesit/media-transcriber).

Download the Python starter pack (ZIP): a short speech test, a repeat-run podcast example, an audio-to-RAG example, automatic file downloads and an HTTP recipe for n8n. Python 3.10+, no packages to install; the examples include charge and timeout limits.

OpenAI Whisper API or this Actor?

OpenAI's transcription endpoint is cheaper per minute ($0.003 to $0.006) and is the better choice when you already have small audio files in hand. It takes uploads only, up to 25 MB per file (OpenAI docs), so a URL, a podcast feed or a long episode means writing your own download, convert and split code first.

OpenAI transcription APIThis Actor
InputFile upload, 25 MB per fileLinks to audio or video, podcast RSS / Atom feeds, YouTube (best effort)
Long recordingsSplit them yourselfHour-long episodes in one go, timestamps kept across the whole file
New podcast episodesYour own scheduler and stateonlyNewEpisodes plus an Apify schedule
OutputText or JSON; SRT and VTT on whisper-1Text, segments, SRT, VTT, Markdown and RAG chunks with citation links
Where the audio goesOpenAIRecognised inside the Actor; no third-party service
Price$0.003 to $0.006 per minute$0.01 per minute (Basic); failed, silent and unreachable files free

FAQ

Is there a free speech-to-text API? Apify's free plan includes $5 of monthly credit, which covers about 140 minutes of audio on the Basic tier.

Can it transcribe from a URL instead of an upload? Yes, that is the main input: paste a direct link to an MP3, WAV, MP4 or other common format, or a podcast feed.

How accurate is it? It depends on the recording, the language and the tier. Basic handles clear speech well; on our small English reference sample the word error rate was 9.9% on Basic and 1.2% on Quality. Compare tiers on a sample of your own content before a large batch, and review transcripts you will publish.

Which languages? 90+ languages, auto-detected by default. Set language to force one, or translate: true to get English text from foreign-language speech.

How long can a recording be? Audio is processed in five-minute chunks with timestamps kept across the whole recording. On default settings one run takes recordings up to 5 hours on Basic (a 3 h 26 min Joe Rogan episode was tested end to end). For a batch, Quality or Max, set a longer run timeout; the Max tier needs at least 4 GB of memory.

Can I get subtitles? Yes. Add srt and/or vtt to outputFormats.

Does it identify speakers? No. There is no speaker diarisation.

What happens if a run is interrupted? Completed five-minute sections are saved. Use Resurrect on the original run (same build, input and storage) to continue without redoing finished sections. Only complete delivered recordings are ever charged.

Is my audio sent anywhere else? No. Recognition runs inside the Actor container. Media is downloaded to temporary storage and deleted after processing; transcripts stay in your Apify account. Only process recordings you have permission to use.

Limitations

  • Feeds must be public RSS 2.0 or Atom with downloadable enclosures, up to 4 MB. Private or authenticated feeds are not supported. The proxy setting applies to media downloads, not feed discovery.
  • Live streams are not supported; use a completed recording.
  • Very noisy or overlapping speech is harder; try Quality or Max on a sample.
  • Words exactly at a five-minute chunk boundary can be less accurate.
  • Markdown is a transcript, not generated show notes. RAG chunks do not identify speakers or include embeddings.

Reference: billing receipts, stop reasons and recovery

Each successful row's billing.receiptKey points to a BILLING-#### record in the run's store, with status charged, partial, unknown or not_monetized. SUMMARY separates minutes delivered, confirmed charges, unknown charges and unprocessed items, and records the billing event and effective unit price. Error rows and SUMMARY carry retryable, recommendedAction, charged and chargeScope (always audio_minutes_only; the Actor-start fee is separate).

Code / stop reasonWhat to do
CHARGE_LIMIT, MINUTE_LIMITCompleted results are kept. Raise the cap only if intended and submit the remaining items, not the whole batch.
RUN_TIME_LIMIT, WALL_TIME_LIMITUse a smaller batch or more run time for the chosen tier.
NO_SPEECHCheck that the recording contains clear speech. No audio-minute charge.
DOWNLOAD_FAILED, PROXY_UNAVAILABLECheck the source link, its expiry and proxy settings.
DURATION_LIMIT, DOWNLOAD_SIZE_LIMIT, LIVE_NOT_SUPPORTEDUse a shorter or completed recording, or raise the relevant limit.
FAILURE_LIMIT, FAILED_WORK_LIMITFix the earlier errors before retrying the remaining items.
ITEM_COST_LIMIT, RUN_COST_LIMIT, FEED_COST_LIMIT, TRANSFER_BUDGETA resource allowance was reached. Check SUMMARY; completed transcripts and checkpoints remain.
UNMETERED_PROTOCOLProvide a direct HTTP(S) file or a supported HTTP stream.
CHECKPOINT_MISMATCH, CHECKPOINT_INVALID, RESUME_RECONCILIATION_REQUIREDRecover only from the original run with identical input, settings and content.
MODEL_LOAD_FAILED, WORKER_EXITEDShare the failed run and its SUMMARY in an issue.
BILLING_UNAVAILABLE, BILLING_UNCERTAIN, PARTIAL_CHARGECheck the receipts before retrying. Never blindly repeat a delivered item.
DELIVERY_FAILED, DELIVERY_STATE_UNCERTAIN, CHECKPOINT_FAILEDCheck the dataset, downloads and receipts first.
TIMESTAMP_BOUNDS_ADJUSTED (warning)Text kept; times were bounded to the decoded audio, originals in originalTiming.

With downloadFiles: true, each row has a files map and the run's DOWNLOADS record lists every file. Fetch API URLs with your Apify token, or download from the Console. If an unsigned link returns HTTP 403, use its consoleUrl or send Authorization: Bearer YOUR_TOKEN. Never put your token in a shared URL. Signed links (shareDownloadLinks: true) can be read by anyone holding them, so leave that off for private audio.

Release notes are on the Changelog tab.

Support and reviews

For help, open an issue and share the affected run through Apify's debugging controls. Never paste tokens or sensitive recordings into a public issue. If it saves you time, an honest review helps other people choose.