# Podcast & Audio Transcriber — Whisper Large-v3, SRT, RSS (`rezaba002/podcast-audio-transcriber`) Actor

Transcribe podcasts, audio and video to text with Whisper large-v3. Paste an RSS feed, Apple Podcasts link or file URL and get timestamped transcripts, SRT/VTT subtitles and the spoken language. Uses the publisher's own transcript when there is one, and monitors shows for new episodes.

- **URL**: https://apify.com/rezaba002/podcast-audio-transcriber.md
- **Developed by:** [Reza Baghestani](https://apify.com/rezaba002) (community)
- **Categories:** AI, Videos, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Podcast & Audio Transcriber

Transcribe podcasts, audio and video files to text with **Whisper large-v3**. Paste a podcast RSS feed, an Apple Podcasts link or a direct link to a file. You get the full transcript, timestamped segments, the spoken language and SRT/VTT subtitle files, one row per episode.

- **Podcast-aware:** give it a feed or an Apple Podcasts show and it picks the newest episodes, with real episode titles, show names and publish dates.
- **Publisher transcripts first:** many podcast hosts publish a timed transcript in the feed. When one exists, it is returned straight away, without transcribing the audio, at a small flat price.
- **Accurate model:** Whisper large-v3, the most accurate open Whisper model, or large-v3 turbo when speed matters more.
- **Long episodes:** audio is split at pauses into pieces of about 10 minutes and transcribed in parallel, so a 90-minute episode takes about a minute.
- **Monitoring:** turn on `onlyNew` and run it on a schedule. Each new episode is transcribed exactly once.
- **Subtitles:** SRT and WebVTT files for every transcript.
- **Built for AI agents:** flat, predictable rows that agents can use through Apify's MCP server or API.

### Use cases

- **Show notes, blog posts and SEO** from podcast episodes.
- **Search and RAG** over a podcast's back catalogue or a set of shows.
- **Media monitoring:** follow shows in your industry and get a transcript of each new episode.
- **Research and analysis** of interviews, lectures and talks.
- **Subtitles and accessibility** for audio and video you publish.

You can run it on a schedule, call it from the Apify API (Python, JavaScript or plain HTTP), or connect it to n8n, Make, Zapier and other Apify integrations.

### Input

| Field | Default | What it does |
|---|---|---|
| `mediaUrls` | required | Podcast RSS feeds, Apple Podcasts show or episode links, and direct links to audio/video files, in any mix |
| `maxEpisodesPerFeed` | 1 | Newest episodes to take from each feed or Apple show (up to 100) |
| `publishedAfter` | – | Only episodes published after a date (`2026-10-01`) or a period back from now (`30 days`, `12 hours`) |
| `onlyNew` | false | Skip episodes already transcribed by this monitor; only episodes newer than the newest one already done count as new |
| `stateName` | `default` | Name of the monitor, so separate monitors don't interfere |
| `usePublisherTranscripts` | true | Use the feed's own timed transcript (VTT, SRT or JSON) when there is one |
| `language` | auto | ISO 639-1 code (`en`, `de`, `fa`, …) if you already know the language |
| `quality` | `accurate` | `accurate` = Whisper large-v3, `fast` = large-v3 turbo |
| `vocabulary` | – | Names and terms to expect, comma-separated, so they are spelled right more often |
| `maxMinutesPerItem` | 120 | Only the first N minutes of each episode are transcribed and billed (up to 600) |
| `subtitles` | true | Save SRT and VTT files and link them from each row |

#### Example input

```json
{
  "mediaUrls": [
    "https://feeds.npr.org/510289/podcast.xml",
    "https://podcasts.apple.com/us/podcast/the-daily/id1200361736",
    "https://example.com/interview.mp3"
  ],
  "maxEpisodesPerFeed": 2,
  "onlyNew": true,
  "stateName": "weekly-shows",
  "vocabulary": "Lex Fridman, Kubernetes, Tehran"
}
```

### Output

Every row has a `row_type`:

| `row_type` | Meaning | Charged |
|---|---|---|
| `transcript` | One episode or file | yes |
| `error` | Bad link, unsupported site, unreadable feed or file, transcription failure | no |
| `notice` | Expected outcome, e.g. `no_new_episodes` in monitoring mode | no |

#### Example transcript row (shortened)

```json
{
  "row_type": "transcript",
  "title": "Should we all be getting tariff refunds right now?",
  "show_title": "Planet Money",
  "published_at": "2026-10-09T21:07:00+00:00",
  "feed_url": "https://feeds.npr.org/510289/podcast.xml",
  "media_url": "https://…/default.mp3",
  "source_duration_sec": 2011.66,
  "transcribed_sec": 2011.66,
  "truncated": false,
  "chunks": 4,
  "language": "en",
  "transcript_source": "whisper",
  "model": "whisper-large-v3",
  "text": "Support comes from … This is Planet Money …",
  "segments": [
    {"start": 0.0, "end": 6.2, "text": "Support comes from our 2026 lead sponsor …", "speaker": null}
  ],
  "srt_url": "https://api.apify.com/v2/key-value-stores/…/records/subtitles-….srt",
  "vtt_url": "https://api.apify.com/v2/key-value-stores/…/records/subtitles-….vtt"
}
```

Rows from a publisher transcript have `transcript_source: "publisher"`, the transcript's link in `publisher_transcript_url`, and speaker names in `segments[].speaker` when the publisher labels them.

Error codes: `invalid_input`, `invalid_url`, `unsupported_source`, `not_media`, `download_failed`, `file_too_large`, `feed_unavailable`, `invalid_feed`, `episode_not_found`, `stt_busy`, `transcription_failed`. Notice codes: `no_new_episodes`, `no_matching_episodes`, `no_episodes`, `too_many_episodes`, `charge_limit_reached`.

### Pricing

Free during early access: you only pay Apify's usual platform usage for your own runs. Pay-per-event pricing (per second of audio transcribed, and a small flat fee per publisher transcript) will be introduced later. Error and notice rows will always be free.

### Limits, stated plainly

- **Not supported:** YouTube, Spotify, TikTok, Instagram, Facebook, X and SoundCloud links. Use the show's RSS feed or Apple Podcasts link, or a direct file link.
- **Accuracy depends on the audio and the language.** English is very good. Some languages, Persian for example, come back with more spelling mistakes. The `vocabulary` field helps with names, but does not guarantee them.
- **No speaker labels for transcribed audio.** Speaker names appear only when the publisher's transcript has them.
- **Apple episode links** work for the 200 newest episodes Apple lists for a show.
- **Busy service:** when the speech-to-text service is at capacity, the episode gets a free `stt_busy` error row. Try again later.

### Privacy

To transcribe it, the audio (converted to compressed mono speech) is sent to [Groq](https://groq.com)'s speech-to-text API. Groq's own data policy applies to the audio it receives. Publisher transcripts are fetched from the publisher. This Actor keeps nothing beyond the run's own dataset and key-value store. Only transcribe audio you have the right to use.

### FAQ

**How do I transcribe a podcast episode?**
Paste the show's RSS feed or Apple Podcasts link into `mediaUrls`. The newest episode is transcribed. Raise `maxEpisodesPerFeed` for more, or paste an Apple episode link for one specific episode.

**How do I get a transcript of every new episode automatically?**
Turn on `onlyNew`, give the monitor a `stateName`, and run the Actor on an Apify schedule (for example daily). Each run transcribes only episodes published since the last one.

**Can I get subtitles?**
Yes. Every transcript row links to an SRT and a WebVTT file.

**Which languages are supported?**
Whisper detects and transcribes about 100 languages. Set `language` if you know it, to skip detection.

**Why did an episode come back so fast?**
The feed had a publisher transcript, so no audio was transcribed. Set `usePublisherTranscripts` to false to transcribe the audio anyway.

### Development

```bash
python -m venv .venv && .venv/Scripts/pip install -r requirements-dev.txt   # or .venv/bin/pip
.venv/Scripts/python -m pytest              # offline tests; ffmpeg comes from imageio-ffmpeg
```

The speech-to-text client speaks the OpenAI transcription API, so the provider is chosen by env vars: `GROQ_API_KEY` or `STT_API_KEY` (**secret**), and `STT_BASE_URL` (default `https://api.groq.com/openai/v1`). `scripts/deploy_source.py <actorId>` uploads the source to Apify and builds it.

# Actor input Schema

## `mediaUrls` (type: `array`):

Any mix of podcast RSS feeds, Apple Podcasts show or episode links, and direct links to audio or video files (mp3, m4a, wav, flac, ogg, opus, mp4, webm, mov). YouTube and Spotify links are not supported.

## `maxEpisodesPerFeed` (type: `integer`):

How many of the newest episodes to take from each feed or Apple Podcasts show (after the filters below).

## `publishedAfter` (type: `string`):

A date such as 2026-10-01, or a period back from now such as 30 days or 12 hours. Applies to feeds and Apple Podcasts shows.

## `onlyNew` (type: `boolean`):

Skip episodes this monitor has already transcribed. Run it on a schedule to transcribe each new episode exactly once.

## `stateName` (type: `string`):

Name of the list of already-transcribed episodes, so separate monitors don't interfere. Letters, digits and \_ . - only.

## `usePublisherTranscripts` (type: `boolean`):

Many podcast hosts publish a timed transcript (VTT, SRT or JSON) in the feed. It is returned as is, in seconds, without transcribing the audio, at a small flat price. Turn off to always transcribe the audio.

## `language` (type: `string`):

ISO 639-1 code such as en, fa, ar, de. Leave empty to detect it automatically.

## `quality` (type: `string`):

accurate = Whisper large-v3 (best accuracy). fast = Whisper large-v3 turbo.

## `vocabulary` (type: `string`):

People, brands, places and jargon the audio contains, separated by commas (for example: Lex Fridman, Kubernetes, Tehran). They are spelled correctly more often. Only the first 800 characters are used.

## `maxMinutesPerItem` (type: `integer`):

Only the first N minutes of each episode or file are transcribed and billed.

## `subtitles` (type: `boolean`):

Also save SRT and WebVTT subtitle files for each transcript and link them from the row.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://github.com/openai/whisper/raw/main/tests/jfk.flac"
  ],
  "maxEpisodesPerFeed": 1,
  "onlyNew": false,
  "stateName": "default",
  "usePublisherTranscripts": true,
  "language": "",
  "quality": "accurate",
  "maxMinutesPerItem": 120,
  "subtitles": true
}
```

# Actor output Schema

## `transcripts` (type: `string`):

All rows of the run. 'transcript' rows have the text and timestamped segments; 'error' and 'notice' rows carry error_code and error_message.

## `summary` (type: `string`):

JSON with per-source and per-episode results, total seconds transcribed, timings, and whether the run stopped at the charge limit.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mediaUrls": [
        "https://github.com/openai/whisper/raw/main/tests/jfk.flac"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rezaba002/podcast-audio-transcriber").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "mediaUrls": ["https://github.com/openai/whisper/raw/main/tests/jfk.flac"] }

# Run the Actor and wait for it to finish
run = client.actor("rezaba002/podcast-audio-transcriber").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mediaUrls": [
    "https://github.com/openai/whisper/raw/main/tests/jfk.flac"
  ]
}' |
apify call rezaba002/podcast-audio-transcriber --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rezaba002/podcast-audio-transcriber"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5eQla5jlxN0IGDhqR/builds/T9J3gwB1UWiasqiaF/openapi.json
