Media URL Transcriber - Video, Podcast RSS, Vimeo, Loom to Text avatar

Media URL Transcriber - Video, Podcast RSS, Vimeo, Loom to Text

Pricing

from $12.00 / 1,000 stt minute (zero-setup)s

Go to Apify Store
Media URL Transcriber - Video, Podcast RSS, Vimeo, Loom to Text

Media URL Transcriber - Video, Podcast RSS, Vimeo, Loom to Text

Transcribe any media URL via API, MCP, or schedule — direct audio/video files, HLS/m3u8, podcast RSS feeds, Vimeo, Loom. Deepgram Nova-3 STT plus free caption reuse when available. Timestamped segments, SRT/VTT subtitles, summaries. Zero setup from $0.005/item; BYOK discount. One JSON row per item.

Pricing

from $12.00 / 1,000 stt minute (zero-setup)s

Rating

0.0

(0)

Developer

Heim AI

Heim AI

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

a day ago

Last modified

Share

Media URL Transcriber — Video, Podcast RSS, Vimeo, Loom to Text

Any cooperative media URL → transcript. Pass direct files, HLS VOD playlists, Vimeo videos, Loom shares, or podcast RSS feeds; get one JSON dataset row per media item. Zero setup for captioned Vimeo; Deepgram Nova-3 for everything else. Built for MCP agents, API clients, and scheduled pipelines.

Actor idkaz_kakyo/media-url-transcriber
Minimal input{ "mediaUrls": ["https://vimeo.com/76979871"] }
Cost$0.012/min STT zero-setup · $0.005/min BYOK · $0.005 caption item · $0.005/run start
OutputDataset rows with type: "transcript" or type: "error"

Supported inputs

InputHow it works
Direct audio/video URL (mp3, mp4, m4a, wav, flac, ogg, opus, aac, webm, mov, mkv)Deepgram fetches the file (STT)
HLS .m3u8 VOD playlistActor assembles audio, sends to Deepgram
Vimeo (vimeo.com/{id}, player, unlisted hash)Published captions ($0.005) when available; else STT
Loom share/embed (loom.com/share/{32hex})Signed mp4 → STT (no keyless captions)
Podcast RSS/Atom feedLatest N episode enclosures → STT

Use something else instead:

You have…Use instead
YouTube watch/shorts/youtu.bekaz_kakyo/youtube-transcripts
TikTok / Instagram / Facebook / X pageA dedicated platform transcript actor from the Apify Store
Spotify / SoundCloud / Apple Podcasts pageThe podcast's RSS feed URL (this actor accepts feeds directly)
Google Drive / Dropbox share pageDirect-download / ?dl=1 / raw=1 file URL
Only a direct media file URLAlso fine here — or kaz_kakyo/audio-transcriber

Pricing

EventPriceWhen
Actor start$0.005Once per run
STT minute (zero-setup)$0.012No BYOK key — transcription included
STT minute (BYOK)$0.005deepgramApiKey set — you also pay Deepgram ~$0.0043/min
Caption item$0.005Vimeo delivered via published captions (no STT)

Minutes round up per item. Worked examples:

  • 30-min podcast episode (zero-setup) → 30 × $0.012 + $0.005 start ≈ $0.365.
  • 30-min podcast episode (BYOK)$0.15 = $0.005×30 min actor fee + ~$0.13 Deepgram wholesale (plus $0.005 start → ~$0.155 actor-side; ~$0.285 all-in with Deepgram).
  • Captioned Vimeo (preferCaptions) → $0.005 caption + $0.005 start = $0.01 total.

Call it (MCP / API / schedule)

MCP (agents)

{
"actor": "kaz_kakyo/media-url-transcriber",
"input": {
"mediaUrls": [
"https://dpgr.am/spacewalk.wav",
"https://vimeo.com/76979871"
]
}
}

Optional extras:

{
"mediaUrls": ["https://feeds.npr.org/510289/podcast.xml"],
"episodesPerFeed": 3,
"preferCaptions": true,
"includeSrt": true,
"diarize": true
}

After the run, read the default dataset. Filter type === "transcript"; treat type === "error" as per-item failure. Bad/unsupported URLs become error rows and the run still SUCCEEDS. The run fails on Deepgram auth/credit errors, post-charge delivery failure, or when every STT item is stt-unavailable and nothing was delivered (no key configured).

API / apify-client

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('kaz_kakyo/media-url-transcriber').call(
{ mediaUrls: ['https://vimeo.com/76979871'], includeVtt: true },
{ maxTotalChargeUsd: 1.0 },
);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const transcripts = items.filter((i) => i.type === 'transcript');

REST: POST /v2/acts/kaz_kakyo~media-url-transcriber/runs with your token.

Schedule / chain

  1. Save a Task with fixed options (preferCaptions, episodesPerFeed, BYOK key).
  2. Schedule the Task for recurring podcast feeds or URL lists.
  3. Webhook on SUCCEEDED — process only type === "transcript" rows.
  4. Cap spend with maxTotalChargeUsd. Over-budget items become uncharged over-budget / skipped rows.
  5. Chain: RSS scraper or CMS export → this actor. YouTube URLs → youtube-transcripts instead.

Output contract

Success row:

{
"type": "transcript",
"url": "https://vimeo.com/76979871",
"source": "vimeo-captions",
"title": "The New Vimeo Player…",
"videoId": "76979871",
"transcript": "…",
"segments": [{ "start": 0.0, "end": 2.4, "speaker": null, "text": "…" }],
"srt": "1\n00:00:00,000 --> …",
"vtt": "WEBVTT\n\n…",
"durationSeconds": 62,
"language": "en",
"billedEvent": "caption-item",
"billedCount": 1
}
FieldNotes
sourcedirect | hls | vimeo-captions | vimeo-stt | loom | podcast-rss
segmentsPresent on success; if the row exceeds ~4 MB, segments (and/or srt/vtt) may be spilled to the key-value store and replaced by segmentsUrl / srtUrl / vttUrl
srt / vttPer includeSrt (default true) / includeVtt (default false); same KVS spill as above when oversized
summarySTT + summarize + English only; never on caption path
confidence, modelSTT only (model is always nova-3)
feedUrl, episodeTitle, episodeGuid, pubDatePodcast RSS rows
billedEvent, billedCountAlways present

Dataset views (Transcripts / Errors) select columns for display — they do not filter by row type. Both transcript and error rows appear in the underlying dataset; filter client-side on type.

Error row (never charged):

{
"type": "error",
"url": "https://…",
"errorCode": "unsupported-platform",
"error": "…pointed FIX…",
"billedEvent": null,
"billedCount": 0
}

errorCode values: unsupported-platform · not-media · not-found · private · too-long · too-large · live-stream · encrypted-hls · stt-unavailable · stt-upstream · no-audio · fetch-failed · feed-empty · invalid-url · over-budget · skipped

When the run itself fails vs. reports a row. Anything wrong with one input (not-found, too-long, no-audio, …) becomes an error row and the run still succeeds — check type per row. Anything that made transcription impossible for the whole run (stt-unavailable = no key available, stt-upstream = Deepgram throttling or down) fails the run when nothing at all was delivered, so an automated caller can retry on status instead of parsing rows. A run that delivered some transcripts still succeeds, with the blocked items recorded as rows.

Retrying after stt-upstream or stt-unavailable. Items blocked because speech-to-text could not run are not checkpointed, so resurrecting the run re-attempts them once the cause clears — you are not charged twice, because charges only ever land on delivery. A re-attempted item keeps its original error row and gains a new row, so deduplicate on url and prefer the row with type: "transcript".

Honest limits

  • Loom = STT only — no keyless caption endpoint.
  • HLS is beta: fMP4 and MPEG-TS/AAC (or MP3) covered; encrypted, live, and byte-range playlists are rejected. Assembly capped at 512 MB (sequential stream-to-disk).
  • No YouTube / TikTok / Instagram / Facebook / X — use dedicated actors.
  • Direct-file duration is not knowable pre-STT — clamped by file size (2048 MB) only.
  • Summaries are English-only (Deepgram summarize=v2).
  • Caption quality = whatever the Vimeo publisher uploaded.
  • Privacy: transcripts contain whatever is spoken (or captioned) in the media URLs you submit — that is the product. Treat outputs as sensitive if the source media is.
  • Caps: 100 URLs/run, 200 items after feed expansion, default maxDurationMinutes 180.

Input (agent-first)

  • mediaUrls (required) — see Supported inputs. Prefill demo: spacewalk.wav + public Vimeo (caption path works keyless).
  • episodesPerFeed — default 1 (max 25).
  • preferCaptions — default true (Vimeo caption path).
  • captionLanguage — BCP-47 prefix; fallback en, then first track.
  • deepgramApiKey — optional BYOK; encrypted; sent only to api.deepgram.com.
  • language / detectLanguage / diarize / smartFormat / paragraphs / summarize / includeSrt / includeVtt / maxDurationMinutes — see Input tab; every field states its default there.

See the Input tab for the full schema. See the API tab for run/dataset endpoints.