# Audio & Video Transcriber (Whisper) - MP3/MP4 to Text, SRT, VTT (`tinyrex/audio-video-transcriber`) Actor

Whisper speech-to-text transcriber for audio, video and podcast RSS feeds: MP3, M4A, WAV, MP4 to text, SRT and VTT, with speaker labels, timestamps and 99 languages. $0.005 per audio minute; failed links and silent files are free. No API key.

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

## Pricing

from $4.00 / 1,000 audio minute (base model)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## 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

## Whisper Speech to Text: transcribe MP3, MP4 and podcasts to text, SRT and VTT

**Whisper speech-to-text: turn a list of audio or video links into text and subtitles.** The Actor runs OpenAI's open-source Whisper model (faster-whisper) inside its own container, so there is no API key, no OpenAI account and no outside speech service. You get one row per file with the full transcript, detected language, timestamped segments and ready-made `.srt` and `.vtt` subtitle files. **$0.005 per audio minute with the base model, $0.01 with the more accurate small model. Dead links, web pages, files without audio and silent files are free.**

### What you get from the Audio & Video Transcriber

- **Speech to text for any common format.** MP3, M4A, WAV, OGG, OPUS, FLAC, AAC, MP4, MOV, MKV, WEBM and anything else ffmpeg can read. Video files are fine: only the audio track is used.
- **99 languages, auto-detected.** Or set the language yourself for short or noisy clips. Choose **Translate** to get an English transcript of non-English speech (Whisper's built-in translation, same price).
- **Timestamps and subtitles.** `segments` with start and end seconds for every sentence, plus links to `.srt` and `.vtt` files you can upload to YouTube, Vimeo, video editors or players.
- **Speaker labels (who spoke when).** Turn on **Speaker labels** and every segment gets `Speaker 1`, `Speaker 2`, ... You also get `speakerText` (the transcript split into speaker turns), talk time per speaker, and speaker names in the SRT and VTT files. Great for interviews, podcasts, meetings and calls. Runs locally (speaker diarization, no API key) for +$0.004 per audio minute.
- **Podcast RSS feeds and follow mode.** Paste a podcast's RSS feed and get the newest episodes transcribed, with podcast title, episode title, publish date and GUID in every row. Turn on **Only new episodes** and schedule the Actor: it remembers what it already did and you pay only for new episodes.
- **Bulk and pipeline friendly.** Paste hundreds of links or read them from another Actor's dataset. One clean row per file, including a clear `error` for every file that failed (free).

### Sample output (JSON)

Real row from a run on a 77-second spoken Wikipedia recording (segments shortened):

```json
{
  "url": "https://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
  "status": "ok",
  "language": "en",
  "languageProbability": 0.999,
  "durationSeconds": 76.7,
  "billedMinutes": 2,
  "words": 167,
  "text": "Pope Simpliceus, from Wikipedia, the free encyclopedia. Pope Simpliceus died March 10, 483, was the head of the Catholic Church from 468 to his death in 483. ...",
  "segments": [
    { "start": 0.24, "end": 5.24, "text": "Pope Simpliceus, from Wikipedia, the free encyclopedia." },
    { "start": 5.24, "end": 9.24, "text": "Pope Simpliceus died March 10, 483," }
  ],
  "srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/srt-0143153b17b9df8e",
  "vttUrl": "https://api.apify.com/v2/key-value-stores/.../records/vtt-0143153b17b9df8e",
  "model": "base",
  "task": "transcribe",
  "format": "ogg",
  "audioCodec": "vorbis",
  "hasVideo": false,
  "truncated": false,
  "transcribeSeconds": 4.5
}
```

With **Speaker labels** on, each segment also has `"speaker": "Speaker 1"`, and the row gets fields like these (from a test run on two spoken Wikipedia recordings by different narrators, joined into one file):

```json
{
  "speakersCount": 2,
  "speakers": [
    { "speaker": "Speaker 1", "seconds": 93, "segments": 16 },
    { "speaker": "Speaker 2", "seconds": 41.7, "segments": 7 }
  ],
  "speakerText": "Speaker 1: Pope Simpliceus from Wikipedia, the free encyclopedia. ...\n\nSpeaker 2: Nabiya, from Wikipedia, the free encyclopedia. ...",
  "speakerBilledMinutes": 3
}
```

A failed link looks like `"status": "failed", "error": "HTTP 404", "billedMinutes": 0`. Export as **CSV, Excel, JSON or XML**, or send results to Google Sheets, Make, Zapier, n8n, webhooks or the Apify API. A `SUMMARY` record in the key-value store has run totals.

### How to transcribe audio or video files

1. Paste **audio or video file URLs**, one per line. They must be direct links that download the file (a podcast episode's MP3 link, a file in cloud storage, a CDN link).
2. Or paste **podcast RSS feeds**: the newest episodes of each feed are transcribed (3 by default).
3. Or pick a **dataset** from another Actor run: every link ending in .mp3/.m4a/.wav/.mp4/... is collected, or set **URL field** to the column that holds your links.
4. Pick the **Whisper model** and, if you know it, the **spoken language**. Run.

#### Example input

```json
{
  "mediaUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
    "https://upload.wikimedia.org/wikipedia/commons/4/48/En-Nabia-article.oga"
  ],
  "model": "base",
  "language": "auto",
  "task": "transcribe",
  "includeSubtitles": true
}
```

| Setting | Default | Notes |
|---|---|---|
| mediaUrls | none | Direct links to audio or video files; duplicates removed |
| podcastFeeds | none | Podcast RSS/Atom feed URLs; newest episodes are transcribed |
| maxEpisodesPerFeed | 3 | Newest N episodes per feed |
| onlyNewEpisodes | false | Follow mode: skip episodes transcribed in earlier runs (free) |
| datasetId / urlField | none | Read links from another run's dataset |
| model | base | `base` ($0.005/min, fast) or `small` ($0.01/min, better on accents, noise and non-English) |
| language | auto | Auto-detect or one of 29 common languages |
| task | transcribe | `translate` = English transcript of any language |
| vadFilter | true | Skips long silences and music-only parts, which reduces made-up text |
| speakerLabels | false | Speaker labels on every segment, `speakerText`, per-speaker talk time (+$0.004/min) |
| numSpeakers | 0 | Known number of speakers (e.g. 2 for an interview); 0 = detect automatically |
| includeSegments | true | Timestamped segments in each row |
| includeSubtitles | true | `.srt` and `.vtt` files plus `srtUrl` / `vttUrl` |
| maxMinutesPerFile | 120 | Only the first N minutes are transcribed and billed (up to 600) |
| maxFileSizeMb | 500 | Bigger files are skipped (free) |
| maxFiles | 100 | Unique URLs per run (up to 10,000) |

**Speed:** at the default 4 GB memory (1 CPU core) the base model transcribes about 10 to 12 minutes of audio per minute, the small model about 4. More memory gives more CPU cores and faster runs; the price per audio minute stays the same.

### Pricing

Pay per event, with Bronze/Silver/Gold discounts:

| Event | Price | When |
|---|---|---|
| Audio minute (base model) | **$0.005** | Per minute of audio transcribed, rounded up per file |
| Audio minute (small model) | **$0.01** | Same, with the more accurate small model |
| Speaker labels minute | **$0.004** | Only with Speaker labels on, per transcribed audio minute; not charged if labelling fails |
| Free | $0 | Dead links, HTTP errors, web pages, files without an audio track, silent files, files over your limits, files skipped by the spending limit or run timeout |

Example: a 45-minute podcast episode costs $0.225 with base, or $0.405 with speaker labels. 100 short 30-second clips cost $0.50. A tiny Actor-start fee applies per run. Set a max charge per run and the Actor transcribes only as many minutes as fit, then stops cleanly.

### FAQ

**Can I transcribe YouTube, TikTok or Instagram videos?** No. Links to platform pages are rejected (free) because downloading from those sites needs their own players and is against their terms. Use files you own or have the rights to: your own recordings, podcast MP3s from an RSS feed, files in cloud storage.

**How accurate is it?** It is the same open-source Whisper model many paid tools use. Clear speech in English and other major languages comes out very well with base; for strong accents, background noise, phone calls or less common languages pick `small`. Names and rare words can be misspelled, as in any speech recognition.

**Can I transcribe a whole podcast and keep up with new episodes?** Yes. Put the podcast's public RSS feed in **Podcast RSS feeds**, set **Newest episodes per feed**, turn on **Only new episodes** and add a daily or weekly schedule in Apify. Each run transcribes only episodes it has not done before; already-done episodes are skipped for free. Spotify and Apple Podcasts page links are not feeds; use the RSS link the podcast host publishes.

**Does it add speaker labels (diarization)?** Yes. Turn on **Speaker labels**. Speakers are numbered in the order they first speak (`Speaker 1`, `Speaker 2`, ...); the Actor cannot know their real names. If you know how many people talk, set **Number of speakers** for the best split. Overlapping speech gets the dominant speaker. Labelling roughly doubles to triples the run time. If it fails for a file you still get the transcript and the speaker minutes are not charged.

**How do I make subtitles for a video?** Keep *Create SRT and VTT subtitle files* on. Each row has `srtUrl` and `vttUrl` links to download the subtitle files.

**Is my audio sent to OpenAI or another API?** No. Download, decoding (ffmpeg) and transcription (faster-whisper) all happen inside the Actor's container, and results stay in your own Apify storage.

**What about very long files?** Files up to 10 hours work. By default only the first 120 minutes are transcribed (`maxMinutesPerFile`); rows show `truncated: true` when a file was cut. Long batches need a long enough run timeout; files that would not finish in time are skipped for free.

📘 **Step-by-step guide with Python, JavaScript, curl and MCP examples:** [How to transcribe hundreds of audio and video files to text and subtitles with Whisper](https://emirmrkaljevic.github.io/tinyrex-data-tools/transcribe-audio-video-to-text-srt-whisper-api/)

### Related actors

- [PDF Text Extractor & OCR](https://apify.com/tinyrex/pdf-ocr-text-extractor): text from PDFs and scanned documents, the same bulk workflow for documents.
- [Bulk Website Screenshot](https://apify.com/tinyrex/bulk-website-screenshot): full-page screenshots of many URLs.
- [Contact Details Extractor](https://apify.com/tinyrex/contact-details-extractor): emails, phones and social links from websites.

### Missing a field?

If a field you need is missing or wrong, please open an issue on the Issues tab. I read every issue and usually reply the same day.

# Actor input Schema

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

Direct links to audio or video files you have the rights to transcribe: MP3, M4A, WAV, OGG, OPUS, FLAC, AAC, MP4, MOV, MKV, WEBM and more (anything ffmpeg reads). Podcast episode enclosure URLs from an RSS feed work. YouTube/TikTok/Instagram and other platform page links are not supported. Failed links are listed with the reason and are free.

## `podcastFeeds` (type: `array`):

Public podcast RSS or Atom feed URLs. The Actor reads each feed and transcribes the newest episodes (audio or video enclosures). Each row gets podcastTitle, episodeTitle, publishedAt and episodeGuid. Use feeds you have the rights to transcribe. Feeds that fail are listed with the reason and are free.

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

How many of the newest episodes to take from each feed.

## `onlyNewEpisodes` (type: `boolean`):

Remembers transcribed episodes in a named key-value store in your account and skips them next time (free). Schedule the Actor daily or weekly to follow a podcast and pay only for new episodes.

## `datasetId` (type: `string`):

ID of an Apify dataset with media links, e.g. podcast episodes from an RSS scraper. Without a URL field, every value that looks like a link to an audio/video file is collected.

## `urlField` (type: `string`):

Dataset field that holds the media link (dot notation like enclosure.url works; arrays are expanded). Use it when your links have no file extension.

## `model` (type: `string`):

Both run OpenAI's open-source Whisper locally (faster-whisper, int8). Small is noticeably better for accents, noisy audio and non-English speech.

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

Auto-detect works for 99 languages. Setting the language avoids wrong detections on short or noisy clips.

## `task` (type: `string`):

translate = Whisper's built-in speech-to-English translation (same price).

## `vadFilter` (type: `boolean`):

Voice activity detection removes long silences and music-only parts before transcription. Reduces hallucinated text on silent parts. Billing is by audio length either way.

## `speakerLabels` (type: `boolean`):

Adds a speaker label (Speaker 1, Speaker 2, ...) to every segment, a speakerText transcript split by speaker, per-speaker talk time, and speaker names in SRT/VTT. Runs speaker diarization (pyannote segmentation + speaker embeddings) inside the container, no API key. Charged per audio minute as speaker-minute on top of transcription; if labelling fails, it is free and you still get the transcript.

## `numSpeakers` (type: `integer`):

Set it when you know it (e.g. 2 for an interview) for the best results. 0 = detect automatically.

## `includeSegments` (type: `boolean`):

Adds a segments array (start, end in seconds, text) to each row.

## `includeSubtitles` (type: `boolean`):

Saves .srt and .vtt subtitles to the key-value store and adds srtUrl / vttUrl to each row.

## `maxMinutesPerFile` (type: `integer`):

Only the first N minutes of each file are transcribed and billed (truncated = true in the row).

## `maxFileSizeMb` (type: `integer`):

Bigger files are skipped (free).

## `maxFiles` (type: `integer`):

Hard cap on unique URLs processed in this run.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
    "https://upload.wikimedia.org/wikipedia/commons/4/48/En-Nabia-article.oga"
  ],
  "maxEpisodesPerFeed": 3,
  "onlyNewEpisodes": false,
  "model": "base",
  "language": "auto",
  "task": "transcribe",
  "vadFilter": true,
  "speakerLabels": false,
  "numSpeakers": 0,
  "includeSegments": true,
  "includeSubtitles": true,
  "maxMinutesPerFile": 120,
  "maxFileSizeMb": 500,
  "maxFiles": 100
}
```

# Actor output Schema

## `results` (type: `string`):

One row per media URL.

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

Totals for the run.

# 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://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
        "https://upload.wikimedia.org/wikipedia/commons/4/48/En-Nabia-article.oga"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinyrex/audio-video-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://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
        "https://upload.wikimedia.org/wikipedia/commons/4/48/En-Nabia-article.oga",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tinyrex/audio-video-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://upload.wikimedia.org/wikipedia/commons/3/3c/Pope_Simplicius_Spoken_Version.ogg",
    "https://upload.wikimedia.org/wikipedia/commons/4/48/En-Nabia-article.oga"
  ]
}' |
apify call tinyrex/audio-video-transcriber --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tinyrex/audio-video-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/p2XJ2YgP36lTfbPcM/builds/c7PKANVE6u3xFW4wv/openapi.json
