# Audio & Video Transcriber: Whisper Speech to Text, SRT (`ctriolab/media-transcriber`) Actor

Transcribe direct audio and video file URLs (MP3, M4A, WAV, MP4, WebM, OGG) to text with open-source Whisper. Auto language detection, timestamped segments, SRT, VTT and TXT subtitles. Pay per audio minute, failed files are free.

- **URL**: https://apify.com/ctriolab/media-transcriber.md
- **Developed by:** [Ctrio Lab](https://apify.com/ctriolab) (community)
- **Categories:** AI, Videos, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 audio minute transcribeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Audio & Video Transcriber (Whisper speech to text, SRT, VTT)

Turn **direct audio and video file URLs** into text with timestamps. The Actor runs the open-source [Whisper](https://github.com/openai/whisper) model (through [faster-whisper](https://github.com/SYSTRAN/faster-whisper)) inside the container, so there is **no third-party API key** and your files are not sent to any other AI service.

- Works with MP3, M4A, AAC, WAV, FLAC, OGG, OPUS, MP4, MOV, WebM, MKV and most other formats FFmpeg can read.
- About 99 languages with **automatic language detection** per file, or set the language yourself.
- **Translate to English** from any language with one switch.
- One dataset row per file: full text, language, length, word count and **timestamped segments**.
- Optional **SRT, WebVTT and TXT** subtitle files with a link in each row.
- **Only new files** mode for scheduled runs over a list of podcast or meeting recording URLs.
- **Files that fail are never charged**: broken links, web pages instead of files, files without audio, files with no speech, or files above your size and length limits.

> **Direct file URLs only.** The URL must return the media file itself (for example `https://example.org/episode-12.mp3`). Pages of YouTube, TikTok, Instagram, Facebook, X, Vimeo, Spotify and similar platforms are rejected, because their terms do not allow downloading. Use podcast RSS enclosure links, your own cloud storage links, or files you uploaded to an Apify key-value store (pick the store and list the keys).

### How to use

1. Paste one or more direct file links into **Media file URLs**, or pick an Apify key-value store that holds your files and list the record keys.
2. Pick a **Whisper model**: `tiny` (fastest), `base` (balanced, default) or `small` (most accurate).
3. Optionally tick **SRT**, **WebVTT** or **Plain text** under **Subtitle files**.
4. Run. Download the transcripts as JSON, CSV or Excel from the dataset, and the subtitle files from the key-value store.

If you start the Actor with an empty input, it transcribes a 24-second public domain sample (Neil Armstrong on the Moon, NASA, via [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Armstrong_Small_Step.ogg)) so you can see the output format.

#### Input example

```json
{
  "mediaUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/3/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg"
  ],
  "model": "base",
  "subtitleFormats": ["srt"]
}
```

#### Output example

Real output for the input above (shortened):

```json
{
  "url": "https://upload.wikimedia.org/wikipedia/commons/3/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg",
  "fileName": "LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg",
  "language": "en",
  "languageProbability": 0.993,
  "task": "transcribe",
  "model": "base",
  "durationSeconds": 133.23,
  "billedMinutes": 3,
  "text": "This is a Libravox Recording. All Libravox recordings are in the public domain. ... Four score and seven years ago, our fathers brought forth upon this continent a new nation, conceived in liberty, ...",
  "wordCount": 302,
  "segmentCount": 27,
  "segments": [
    { "start": 1.62, "end": 6.62, "text": "This is a Libravox Recording. All Libravox recordings are in the public domain." },
    { "start": 6.62, "end": 11.62, "text": "For more information or to volunteer, please visit Libravox.org." }
  ],
  "srtUrl": "https://api.apify.com/v2/key-value-stores/<id>/records/001-LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.srt",
  "processingSeconds": 9.4,
  "transcribedAt": "2026-10-27T04:22:44+00:00"
}
```

Notice "Libravox" instead of "LibriVox": Whisper writes what it hears. The `small` model got the name right in the same test.

The `SUMMARY` record in the key-value store lists every skipped file with the reason.

### Pricing

Pay per event: **$0.0015 per audio minute transcribed** ($1.50 per 1,000 minutes), rounded up per file (a 40-second clip is 1 minute, a 12 minute 4 second file is 13 minutes). Store discounts: Bronze $0.00135, Silver $0.0012, Gold and above $0.00105 per minute. Skipped and failed files are free.

Platform usage (compute) is billed to your Apify account as for any Actor. Measured with the default 4 GB memory:

| Model | Speed (audio minutes per run minute) | Compute per audio minute |
|---|---|---|
| tiny | about 20 | about 0.003 CU |
| base (default) | about 7 | about 0.009 CU |
| small | about 3 | about 0.02 CU |

Each run also has about 10 seconds of start-up (loading the model). Example from our test: a 12 minute 4 second MP3 with `base` took 107 seconds and 0.12 CU, so the total is $0.02 for 13 minutes plus 0.12 CU of compute (about $0.04 to $0.05 at $0.3 to $0.4 per CU), about $0.005 per audio minute all in. With `tiny` it is cheaper, with `small` about twice as much.

### Tips

- Clear speech in a common language: `base` is usually enough. Accents, noise or less common languages: try `small`.
- Set **Language** if you already know it. This avoids rare wrong guesses on very short or music-heavy files.
- **Skip silence** is on by default. It speeds up long recordings with pauses and reduces made-up text in silent parts. Billing always uses the full file length.
- Use **Only new files** with a schedule to transcribe only new episodes from a list of URLs. The state is kept in a named key-value store (Monitor name).

### FAQ

**Can I transcribe a YouTube or TikTok link?** No. This Actor only accepts direct file URLs. Platform pages are rejected immediately and not charged.

**Does it identify speakers?** No, speaker labels (diarization) are not included.

**How long can a file be?** Up to 600 minutes per file and 2 GB, with defaults of 240 minutes and 500 MB that you can raise.

**Is my audio sent to OpenAI or another API?** No. The model runs inside the Actor container. Files are deleted from the container after each transcription.

**Can I call it from code or an AI agent?** Yes, like any Apify Actor: the Apify API, the JavaScript and Python clients, Make, Zapier, n8n or the Apify MCP server.

### Licenses

Whisper model weights and code: MIT (OpenAI). faster-whisper and the CTranslate2 model conversions: MIT (SYSTRAN). Sample audio: public domain (NASA). You are responsible for having the right to transcribe the files you submit.

Made by [Ctrio Lab](https://ctriolab.com). Questions or feature requests: open an issue on the Actor page or write to help@ctriolab.com.

# Actor input Schema

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

Direct links to audio or video files (MP3, M4A, WAV, FLAC, OGG, OPUS, MP4, MOV, WebM, MKV). The URL must return the file itself. Pages of YouTube, TikTok, Instagram and similar platforms are not supported. Leave empty to transcribe a short public domain sample.

## `keyValueStore` (type: `string`):

A key-value store in your Apify account that holds audio or video files. Pick it here and list the record keys below.

## `keyValueStoreKeys` (type: `array`):

Keys of the media records to transcribe, for example interview.mp3.

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

tiny is fastest, small is most accurate. base is a good balance for clear speech. All models detect the language automatically.

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

ISO 639-1 code such as en, de, es, ko, ja. Leave empty to detect the language automatically for each file.

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

transcribe keeps the original language. translate returns English text for speech in any language.

## `subtitleFormats` (type: `array`):

Also save SRT, VTT or plain TXT files to the run's key-value store. Each dataset item gets a link to its files.

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

Add the list of segments with start and end seconds to each dataset item.

## `skipSilence` (type: `boolean`):

Skip long silent parts. Faster and reduces made-up text in silence. Billing still uses the full file length.

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

Larger files are skipped and not charged.

## `maxDurationMinutes` (type: `integer`):

Longer files are skipped and not charged.

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

Skip URLs this Actor already transcribed in an earlier run with the same monitor name. Useful for scheduled runs over a podcast file list.

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

Name of the key-value store that remembers transcribed URLs when "Only new files" is on. Use a different name per list.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/3/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg"
  ],
  "model": "base",
  "task": "transcribe",
  "subtitleFormats": [],
  "includeSegments": true,
  "skipSilence": true,
  "maxFileSizeMb": 500,
  "maxDurationMinutes": 240,
  "onlyNew": false,
  "stateName": "media-transcriber-state"
}
```

# Actor output Schema

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

One item per file: text, language, length, billed minutes, segments and subtitle links.

## `files` (type: `string`):

SRT, VTT and TXT files in the run's key-value store.

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

Counts and the list of skipped files with reasons (skipped files are not charged).

# 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/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ctriolab/media-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/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg"] }

# Run the Actor and wait for it to finish
run = client.actor("ctriolab/media-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/30/LibriVox_-_Everrett_Copy_of_the_Gettysburg_Address_-_Michael_Scherer.ogg"
  ]
}' |
apify call ctriolab/media-transcriber --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ctriolab/media-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/ZvCCBx6i6OgOyQPK5/builds/f9l7BeaMaWxqfs0Ld/openapi.json
