Speech to Text · Any Link or File avatar

Speech to Text · Any Link or File

Pricing

from $3.00 / 1,000 audio minutes

Go to Apify Store
Speech to Text · Any Link or File

Speech to Text · Any Link or File

Never charged for a link we can't reach, can't decode, or that has no speech. Any audio or video URL to text, SRT and VTT with timestamped segments — direct file links from any host, plus 11 tested sites. About 90 languages, no API key of your own.

Pricing

from $3.00 / 1,000 audio minutes

Rating

0.0

(0)

Developer

Steadyfetch Team

Steadyfetch Team

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a minute ago

Last modified

Share

Any media URL to text, SRT and VTT. Unreachable, silent and unsupported items are never charged. Direct file links always work; sites only where listed. Paste a link to an .mp3, .m4a, .wav, .mp4, .mov — or a podcast, SoundCloud, Loom, Twitch VOD, Archive.org or Wistia page — and get back the transcript, the timestamps, and ready-made subtitle files. No account, no API key of your own, no subscription.

You give itYou get back
A direct audio or video file link, from any hosttext — the full transcript, in the language it was spoken
…or a page link on one of the 11 tested sites belowsrt and vtt — subtitle files, ready to upload
…or a whole list of them in one runsegments — start/end timestamps for every line
…or the Dataset ID of any scraper run you already havelanguage, durationSeconds, wordCount, status, chargedMinutes

Pricing: from $3.00/1,000 audio minutes. You are charged per audio minute actually transcribed, rounded up to the next whole minute (a 90-second clip bills 2 minutes). Nothing else — no start fee, no subscription.

What can fail, and what it costs you: nothing. The two most common non-deliveries are no_speech (the audio decoded fine but it is music, silence or a tone) and unsupported_site (a page link on a site that is not on the tested list below). Both come back as a row with charged: false and a note saying what happened — as do unreachable, not_media, no_audio_stream, too_large, drm_or_paywall and budget_stop. You are billed for decoded audio minutes and nothing else.

Output

One JSON row per URL. Delivered rows carry the transcript and charged: true; anything that could not be delivered carries a status saying why, and charged: false. Real rows from a verified run (long text trimmed with … for this page):

statuschargedchargedMinutessiteNametitledurationSecondslanguagewordCounttext
oktrue1LoomSell Faster and Smarter with Loom53.45English118Ready to prospect more efficiently, close more pipeline, and create loyal champions? Loom …
oktrue9Archive.org1 Laying Plans - 2 Waging War506.78English1133Part 1. Laying Plans. Sun Tzu said, 1. The Moral Law 2. Heaven 3. Earth 4. The Commander …
no_speechfalse0WistiaWistia Product Page - Looping Header15.07nullnullnull

The last row is a music-only clip with no voice-over: it comes back with its metadata and is not charged.

Browse a full live example dataset → — one real run, three rows: a 3-minute public-domain recording transcribed and charged for 4 audio minutes, a music-only clip returned no_speech, and a dead link returned unreachable. The run charged 4 audio minutes in total — exactly the one row that carries a transcript.

A delivered row in full:

{
"url": "https://www.loom.com/share/3690d29d5e3c426eb0f7ea00f9d3ae7b",
"resolvedMediaUrl": "https://cdn.loom.com/sessions/transcoded/3690d29d5e3c426eb0f7ea00f9d3ae7b.mp4",
"sourceType": "site",
"siteName": "Loom",
"title": "Sell Faster and Smarter with Loom",
"durationSeconds": 53.45,
"language": "English",
"languageConfidence": null,
"text": "Ready to prospect more efficiently, close more pipeline, and create loyal champions? …",
"segments": [{ "start": 0.88, "end": 7.12, "text": "Ready to prospect more efficiently…" }],
"srt": "1\n00:00:00,880 --> 00:00:07,120\nReady to prospect more efficiently…",
"vtt": "WEBVTT\n\n00:00:00.880 --> 00:00:07.120\nReady to prospect more efficiently…",
"wordCount": 118,
"status": "ok",
"retryable": false,
"charged": true,
"chargedMinutes": 1,
"note": null
}

Every field is always present — explicit null over silent omission. Non-delivered rows carry a status and a note instead, plus retryable: true means the host refused us this time (a block, a throttle, a bot page) and running the same input again is worth it; false means the answer will not change.

statusWhat happenedCharged
okSpeech transcribed✅ per audio minute
no_speechAudio decoded, but it is music, silence or a tone
no_audio_streamThe file is video with no audio track at all
not_mediaThe link returns an image, a feed or a live stream — not a file. If a host served a web page where the file should be, that is a block: the row comes back retryable: true
no_mediaThe page resolved but exposes no audio or video we can fetch
unsupported_siteA page link on a site that is not on the tested list (the note names the actor that does handle it, when one exists)
unreachable404 / 410 / DNS failure — permanent. A 401, 403, 451, throttle or timeout is a block, not a missing file: same status, retryable: true
drm_or_paywallThe media needs a signed-in account
too_largeOver the per-item size limit, or over your maxMinutesPerItem
asr_failed / failed_download / failed_resolveDid not complete after all attempts (also listed in the run's ERRORS record)
asr_unavailableOur speech-recognition service refused this actor's access mid-run — that is on us, not you. Remaining items were answered instantly without being started; try again later
budget_stopThe run hit your charge cap, your minute cap, or the run timeout before reaching this item
input_errorThe entry is not a usable link — the note says what to pass

This actor may fail when the platform changes things — failed items are never charged.

For AI agents & LLMs — copy this block

Actor: steadyfetch/media-transcriber (Apify Store)
Does: any audio/video URL -> transcript + SRT + VTT + timestamped segments.
One JSON row per URL. No login, no cookies, no third-party API key.
Run: POST https://api.apify.com/v2/acts/steadyfetch~media-transcriber/run-sync-get-dataset-items?token=APIFY_TOKEN
Input:
{
"urls": ["https://example.com/episode.mp3",
"https://archive.org/details/some_item",
"https://soundcloud.com/user/track"],
"datasetId": "aBcD1234efGh5678i", // optional, chain a scraper run
"datasetItems": [{"videoUrl": "https://cdn/clip.mp4"}],// optional, paste rows instead
"outputFormats": ["text", "segments", "srt", "vtt"], // optional, default ["text"]
"language": "auto", // optional, or an ISO-639-1 code
"maxMinutesPerItem": 0, // optional, 0 = no limit
"maxTotalMinutes": 0 // optional, 0 = no limit
}
Omit a field rather than sending null — the platform rejects an explicit null
before the run starts.
Output one row per URL: url, resolvedMediaUrl, sourceType, siteName, title,
durationSeconds, language, text, segments[], srt, vtt, wordCount,
status, retryable, charged, chargedMinutes, note
retryable=true on a non-ok row means the host blocked/throttled us —
re-run the same input. retryable=false means the answer will not change.
Chain datasetId takes the default dataset of ANY finished actor run. Each row is
deep-scanned for one audio/video link (videoUrl, audioUrl, mediaUrl,
playAddr, downloadAddr, a bare file link — at any depth); thumbnails,
covers and profile pictures are ignored. One media link per row, and a
link already in `urls` is never transcribed twice. Rows with no media
link are counted on the run's status line, never charged.
Pricing pay per event, platform usage INCLUDED, no start fee:
audio-minute-transcribed $0.012 -> $0.003 per audio minute (falls with your Apify plan tier)
Billed per started minute, on decoded audio. Unreachable, silent, oversized and
unsupported items charge nothing at all.
Cap any run with maxTotalChargeUsd (minimum $0.05) or with maxTotalMinutes.
MCP: reachable through Apify's MCP server; ask for "speech to text from a URL".

What this does not do

  • No speaker labels. This returns one transcript per file with timestamps, not a who-said-what breakdown. If you need speaker separation, this is not the right actor.
  • No translation. Speech is transcribed in the language it was spoken. About 90 languages are detected automatically.
  • No downloading. You get text and subtitles, not a media file.

Any direct media file link, from any host. .mp3 .m4a .wav .flac .ogg .opus .aac .aiff · .mp4 .m4v .mov .webm .mkv .avi — signed CDN links and links with no file extension work too; the file is identified by its actual bytes, not by its name.

Page links, on these 11 tested sites only:

Podcast hostsLibsyn · Megaphone · Buzzsprout · Acast · Spotify for Podcasters (Anchor)
Storage & archivesS3 / CloudFront links · Archive.org
Audio & videoSoundCloud · Loom · Twitch VODs · Wistia

Everything else comes back as an uncharged unsupported_site row that says so. We do not claim "1,000+ sites" — this list is what was actually measured.

Sites we deliberately send elsewhere. YouTube, Instagram, TikTok, Facebook, LinkedIn and the Google Ads Transparency Center each have a dedicated steadyfetch actor that does the job better and cheaper than a general transcriber can. Paste one of those page links here and the row tells you which actor to use — and if you already hold the direct media file link, paste that instead: it works.

Known limits, stated plainly. Vimeo only serves video to a signed-in account, so it cannot be transcribed from a public link. Live streams have no end and are refused before anything is spent — both a live page and a raw ICY/SHOUTcast radio URL are caught on the first few kilobytes, not after a download. Files over 256 MB come back as too_large with their measured size — point us at an audio-only version instead.

How much does it cost to transcribe audio?

One result = one audio minute actually transcribed. Billed per started minute, measured from the decoded audio, so a 90-second clip bills 2 minutes. The per-minute price falls with your Apify plan tier — see the Pricing tab.

JobApprox. cost at the headline price
A 45-minute podcast episode≈ $0.14
20 podcast episodes (~15 hours)≈ $2.70
A 3-hour recorded session≈ $0.54
Apify's $5 starter credit1,600 audio minutes

Platform usage (compute + transfer) is included in the event price — the per-minute price you see is the whole price. Unreachable links, music-only audio, oversized files and unsupported pages carry no result fee.

How to transcribe an mp3 URL (no code)

  1. Open the actor and paste your links into Media URLs, one per line.
  2. Optional: tick SRT subtitles and VTT subtitles under Formats to return — they cost nothing extra.
  3. Optional: set Max total minutes if you want a hard ceiling on the run.
  4. Click Start. Each link comes back as one JSON row. Export as JSON/CSV, or read it over the API.

Leave the list empty and the actor returns a single uncharged demo row showing the output shape.

Chain it after any scraper

You do not have to paste links by hand. Run whatever scraper you already use, then put its Dataset ID into this actor — with Apify's Connect actor integration the field fills itself, so the two runs become one workflow.

Every row is deep-scanned for a single audio or video link, whatever the scraper calls it: videoUrl, audioUrl, mediaUrl, playAddr, downloadAddr, a bare file link, nested or top-level. Thumbnails, covers and profile pictures are never mistaken for media, a row's video and its audio track count as one item (never two charges), and a link you also listed in Media URLs is transcribed once. Rows carrying no media link are counted on the run's status line and cost nothing. If you would rather not chain by ID, paste the rows straight into Dataset items.

Page links belonging to YouTube, Instagram, TikTok, Facebook, LinkedIn or the Google Ads Transparency Center behave the same way here as anywhere else in this actor — an uncharged row naming the dedicated actor for that platform.

FAQ

How do I transcribe an mp3 URL? Paste the link into Media URLs and start the run. Any host works — the file is identified by its bytes, so signed CDN links and extension-less links are fine.

Speech to text API without a subscription? That is this actor. You pay per audio minute transcribed, with no monthly fee and no start fee, through your existing Apify account.

How do I transcribe a podcast episode to SRT? Paste the episode's audio URL (or its page on Libsyn, Megaphone, Buzzsprout, Acast or Spotify for Podcasters), tick SRT subtitles, and the srt field comes back ready to save as a .srt file.

What happens if the link is wrong? The actor reads about 4 KB of the response and checks the actual bytes before downloading anything. A web page, an image or a dead link comes back as an uncharged row telling you what it found.

Music-only audio, or a video with no voice-over? Speech models hallucinate filler like "Thank you." over music. This actor detects that in any language and returns an honest, uncharged no_speech row instead of selling you a fake transcript.

How long can a file be? There is no duration limit. Long recordings are transcribed in overlapping windows and stitched back together with continuous timestamps; the row says when that happened. The only size limit is 256 MB per file.

Which languages? Whisper-class multilingual recognition — English, Spanish, German, Japanese, Arabic, Portuguese, Indonesian and about 90 more, detected automatically. The detected language ships on every row.

Do I need cookies, a login, or my own API key? No. The actor fetches public media only.

Can I feed it the output of another actor? Yes — put that run's Dataset ID in, or paste its rows into Dataset items. The actor finds the media link in each row itself, so you do not have to know which column your scraper used. See Chain it after any scraper above.

Why did some chained rows come back with nothing? Rows that carry no audio or video link are skipped, counted on the run's status line, and never charged — an image post or a comment row has nothing to transcribe.

Can I cap what a run spends? Two ways: maxTotalMinutes stops the run after that many charged audio minutes, and Apify's own Maximum cost per run caps the charge in dollars. Either way the run stops cleanly and the items it did not reach come back as uncharged budget_stop rows.

Also from steadyfetch

Speech to Text · Any Link or File is the general-purpose transcriber: any direct audio or video link, or a file you host. For the platforms below, use the platform's own actor — it reads the platform's listing, carries its metadata, and costs less per row.

The rest of the steadyfetch shelf — same contract everywhere: all-inclusive pay per event, no start fee, charged only on delivery.

FamilyActors
Ad creative intelligenceFacebook · Google Ads video · TikTok · LinkedIn · Google Ads text & OCR
Trends & keywordsGoogle Trends · Trends Now · Breakout keywords · Autocomplete keywords · Keyword volume & CPC · Social trends
YouTube transcriptsYouTube videos · YouTube channels
InstagramReel transcripts · Profile posts
JobsIndeed · Career sites by domain · Glassdoor · Multi-board · Google Jobs
AmazonProducts · Search · Bestsellers · Sellers
Any media fileSpeech to Text · any link or file

Unlinked names are publishing shortly on the same account — search steadyfetch on Apify Store.

Ready-made n8n templates for the suite: github.com/steadyfetch/n8n-templates — no community nodes needed.

Feedback & support

Found an issue? Open it on the Issues tab — issues are answered in about 3 hours, and always within one business day. Feature requests welcome, especially a site you would like added to the tested list.