# Audio & Video Transcription (Whisper) for AI Agents (`tinplatelabs/transcriber`) Actor

Transcribe your audio and video files with Whisper: text, timestamped segments, optional word timings, language detection, translation to English, and SRT/VTT subtitle files. MP3, M4A, WAV, MP4, WebM and more from URLs or key-value stores. Priced per audio minute.

- **URL**: https://apify.com/tinplatelabs/transcriber.md
- **Developed by:** [tinplatelabs](https://apify.com/tinplatelabs) (community)
- **Categories:** AI, Developer tools, Automation
- **Stats:** 11 total users, 10 monthly users, 93.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Transcription (Whisper) for AI Agents

Turn your **audio and video files** into text the way an AI agent or pipeline can use it: the full **transcript**,
**timestamped segments** (and word timings if you want them), the **detected language with a confidence score**,
the duration, and ready-made **SRT and WebVTT subtitle files**. Send a batch of file URLs or key-value store
records; get one result row per file.

Works on interviews, meetings, podcasts, lectures, voice notes, webinars, customer calls and videos you own. Built
for people and AI agents (Claude, ChatGPT, Cursor and others through the [Apify MCP server](https://mcp.apify.com)).

> **Your files only.** This Actor transcribes media files you supply. It does **not** download from YouTube,
> TikTok, Instagram, Facebook, X, Vimeo, SoundCloud, Spotify or other platforms: links to their pages get a
> `PLATFORM_URL_NOT_SUPPORTED` error (free). Upload the file you have the rights to into a key-value store, or give
> a direct link to it on your own storage.

### Why this one

- **Whisper, three sizes.** OpenAI's Whisper (MIT) via faster-whisper on CPU: `base` (fast, clear speech),
  `small` (accents, noise, non-English), `medium` (most accurate). Each has its own per-minute price.
- **99 languages.** Automatic language detection with a confidence score, or set the language yourself.
  Optional **translation to English**.
- **Subtitles included.** SRT, WebVTT and plain-text files are saved to the run's key-value store, with download
  links in the result.
- **Clean output.** Silero voice activity detection skips silence and music, which avoids invented text in
  quiet parts. The plain text starts a new paragraph after long pauses.
- **Any format.** MP3, M4A/AAC, WAV, FLAC, OGG/Opus, WebM, MP4, MOV, MKV, AVI and most other audio and video
  formats (decoded by ffmpeg). Video files are transcribed from their audio track.
- **Long files.** Up to 5 hours per file (default limit 3 hours). Long recordings are cut at quiet moments into
  10-minute pieces and stitched back on one timeline.
- **Predictable.** Pay per started audio minute, only for files that were transcribed. Every failure is an error
  item that says what to change, and it costs nothing.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `media` | array of strings | required | Direct `http(s)` URLs of audio/video files, key-value store records as `kvs://KEY` (the store in `keyValueStoreId`, else this run's store) or `kvs://STORE_ID_OR_NAME/KEY`, or signed Apify record URLs (`?signature=`). Up to 200 per run. |
| `keyValueStoreId` | string | | Your key-value store holding the files (pick it in Console, or pass its ID). The Actor runs with limited permissions and can read only this store and its own. |
| `model` | `base` | `small` | `medium` | `base` | Whisper model size. `medium` needs 4 GB of memory; with less, `small` is used instead (and charged at the small price). |
| `language` | string | auto | ISO 639-1 code such as `en`, `es`, `de`, `ja`. Empty: detect. |
| `task` | `transcribe` | `translate` | `transcribe` | `translate` outputs English. |
| `wordTimestamps` | boolean | `false` | Add words with start, end and probability to each segment. |
| `vadFilter` | boolean | `true` | Skip silence and music (Silero VAD). |
| `initialPrompt` | string | | Names and terms in the recording, to guide spelling. |
| `includeSegments` | boolean | `true` | Add `segments` to each result. |
| `saveSubtitleFiles` | boolean | `true` | Save SRT, VTT and TXT files and link them in `files`. |
| `maxDurationMinutes` | integer 1-300 | `180` | Longer files get a `TOO_LONG` item (not charged). |
| `fileTimeoutSecs` | integer 60-14400 | `3600` | Slower files get a `TIMEOUT` item (not charged). |

```json
{
  "media": [
    "https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg",
    "kvs://team-call-2026-10-01.m4a"
  ],
  "keyValueStoreId": "my-recordings",
  "model": "small",
  "wordTimestamps": true
}
```

To transcribe a file that isn't online, upload it to a key-value store, pick that store as `keyValueStoreId` and
pass `kvs://KEY`.

### Output

One dataset item per file:

```json
{
  "source": "https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg",
  "status": "ok",
  "text": "So first of all, let me assert my firm belief that the only thing we have to fear is fear itself ...",
  "language": "en",
  "languageProbability": 0.99,
  "languageDetected": true,
  "task": "transcribe",
  "model": "base",
  "durationSeconds": 46.959,
  "speechSeconds": 44.1,
  "billedMinutes": 1,
  "chargedEvent": "minute-transcribed-base",
  "segmentCount": 9,
  "wordCount": 96,
  "files": {
    "srt": {"key": "001-First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.srt", "url": "https://api.apify.com/v2/key-value-stores/.../records/001-...srt?signature=..."},
    "vtt": {"key": "001-First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.vtt", "url": "https://..."},
    "txt": {"key": "001-First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.txt", "url": "https://..."}
  },
  "media": {"format": "ogg", "audioCodec": "vorbis", "hasVideo": false, "sizeBytes": 995439},
  "timingMs": {"download": 310, "decode": 120, "transcribe": 4200, "total": 4700},
  "realtimeFactor": 0.089,
  "warnings": [],
  "segments": [
    {"id": 0, "start": 0.0, "end": 6.2, "text": "So first of all, let me assert my firm belief", "avgLogprob": -0.21, "noSpeechProb": 0.01}
  ]
}
```

- `languageProbability` is Whisper's confidence in the detected language (null when you set `language`).
- `speechSeconds` is the speech found by voice activity detection; billing uses `durationSeconds`.
- With `wordTimestamps`, each segment has `words: [{"start", "end", "word", "probability"}]`.
- The `files` links are signed and work without an Apify token.

A file that can't be transcribed gives an error item, and the run carries on:

```json
{"source": "https://www.youtube.com/watch?v=...", "status": "error",
 "error": {"code": "PLATFORM_URL_NOT_SUPPORTED", "message": "Links to youtube.com pages are not supported: this Actor transcribes media files you supply ..."}}
```

Error codes: `INVALID_SOURCE`, `PLATFORM_URL_NOT_SUPPORTED`, `ACCESS_DENIED`, `DOWNLOAD_FAILED`, `FILE_TOO_LARGE`,
`NOT_MEDIA`, `NO_AUDIO_STREAM`, `UNSUPPORTED_MEDIA`, `EMPTY_AUDIO`, `TOO_LONG`, `TIMEOUT`, `SPENDING_LIMIT_REACHED`,
`INTERNAL_ERROR`.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `minute-transcribed-base` | **$0.007** | Each started minute of audio transcribed with `base` |
| `minute-transcribed-small` | **$0.016** | Each started minute with `small` |
| `minute-transcribed-medium` | **$0.055** | Each started minute with `medium` |
| `apify-actor-start` | **$0.0025** per GB | Once per run, per GB of memory: $0.01 at the default 4 GB (loading the speech model) |

A 1-hour podcast costs $0.43 with `base` or $0.97 with `small` (including the run start). A 61-second clip counts
as 2 minutes. Send many files in one run to pay the start fee once. Platform
usage is included in the price. Failed files are never charged; a file with no speech in it is charged like any
other. Before each file the run checks your maximum total charge; a file that does not fit is marked
`SPENDING_LIMIT_REACHED` and not transcribed.

### Speed and memory

It runs on CPU. The default 4 GB run has one CPU core: `base` transcribes about 10 minutes of audio per minute,
`small` about 4, `medium` a little over 1 (measured on Apify). 8 GB (two cores) is faster at the same price.
`medium` needs 4 GB; a run with less memory uses `small` instead and says so in its status and warnings.
At 2 GB, `small` decodes in smaller batches to stay within memory (a little slower). Audio is decoded to disk,
so long files do not need extra memory. A failed file gets an error item and is not charged; the run itself only
fails for invalid input.

### Limits

- 1 GB per file, 200 files per run, up to 300 minutes per file (`maxDurationMinutes`, default 180).
- One audio track per file (the first). No speaker labels (diarization).
- Platform page links (YouTube, TikTok, Instagram, Facebook, X, Vimeo, SoundCloud, Spotify, Twitch and similar)
  are refused.
- Downloads follow up to 5 redirects; only public addresses are fetched.

### Privacy

Files are downloaded into your run and processed inside it; results go only to the run's dataset and key-value
store. Nothing is sent to any third party (no speech-to-text API), there is no telemetry, and only the exact URLs
you give are fetched.

### Use from an AI agent (MCP)

Add the Apify MCP server to your agent and enable this Actor. Call it with `{"media": ["<file url>"]}` and read
`text` (or `segments` for timestamps) from the dataset item; use `files.srt.url` for subtitles.

### Models and licenses

- **Models:** OpenAI [Whisper](https://github.com/openai/whisper) base, small and medium (**MIT**), as CTranslate2
  conversions by SYSTRAN ([faster-whisper-base](https://huggingface.co/Systran/faster-whisper-base),
  [-small](https://huggingface.co/Systran/faster-whisper-small),
  [-medium](https://huggingface.co/Systran/faster-whisper-medium), MIT), pinned to a revision and checked against
  SHA256 sums at build time, run with int8 weights. Silero VAD (MIT) ships with faster-whisper. No endorsement by
  OpenAI or SYSTRAN is implied.
- **ffmpeg** (LGPL/GPL) is the unmodified Debian package, run as a separate program to decode media. PyAV is not
  used.

| Component | License | Role |
|---|---|---|
| Whisper base/small/medium weights (SYSTRAN CTranslate2 conversions) | MIT | Speech recognition |
| faster-whisper 1.2.1 (incl. Silero VAD model) | MIT | Transcription |
| CTranslate2 4.8.2 | MIT | Inference |
| onnxruntime 1.31.0 | MIT | Voice activity detection |
| tokenizers, huggingface-hub | Apache-2.0 | Tokenizer, model loading |
| numpy 2.4.6 | BSD-3-Clause | Audio arrays |
| httpx 0.28.1, httpcore, h11, anyio, idna | BSD-3-Clause / MIT | Downloads |
| apify 4.1.0, apify-client, crawlee and their dependencies | Apache-2.0 / MIT / BSD | Apify SDK |
| tqdm, certifi | MPL-2.0 + MIT / MPL-2.0 (used unmodified) | Progress helper, CA certificates |
| ffmpeg (Debian package, separate process) | LGPL-2.1+ / GPL | Decoding |

Test-only: pytest (MIT). CI fails on any copyleft Python dependency.

***

Made by Tinplate Labs. This Actor is maintained by an AI; there is no support desk, so every error message is
written to tell you exactly what to change.

# Actor input Schema

## `media` (type: `array`):

Files to transcribe, one per line: direct <b>http(s) URLs</b> of audio or video files, files in a key-value store as <code>kvs://KEY</code> (the store picked below, or this run's store) or <code>kvs://STORE_ID_OR_NAME/KEY</code>, or signed Apify record URLs (with <code>?signature=</code>). MP3, M4A/AAC, WAV, FLAC, OGG/Opus, WebM, MP4, MOV, MKV and more. Links to YouTube, TikTok, Instagram, Vimeo, Spotify and other platform pages are <b>not supported</b>. Up to 200 files per run, 1 GB each.

## `keyValueStoreId` (type: `string`):

Your key-value store that holds the media files. Pick it (or paste its ID) and list its records as <code>kvs://KEY</code>. The Actor runs with limited permissions: besides public URLs it can read only this store and its own run's store.

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

Whisper model size. <code>base</code> is fast and good for clear speech; <code>small</code> is more accurate on accents, noise and non-English speech; <code>medium</code> is the most accurate and slowest (needs 4 GB memory). Each has its own per-minute price.

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

Spoken language as an ISO 639-1 code (e.g. <code>en</code>, <code>es</code>, <code>de</code>, <code>ja</code>). Leave empty to detect it automatically (reported with a confidence). Setting it avoids misdetection on short or noisy clips.

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

<code>transcribe</code> writes what is said in its own language; <code>translate</code> writes an English translation.

## `wordTimestamps` (type: `boolean`):

Add each word with its start, end and probability to every segment. Slightly slower.

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

Detect speech with Silero VAD and skip silence and music. Faster and avoids invented text in silent parts. Turn off only if quiet speech is being dropped.

## `initialPrompt` (type: `string`):

Optional text that guides spelling and style: names, product terms, acronyms that appear in the recording (up to 800 characters).

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

Add <code>segments</code> (start, end, text) to each result. Turn off for long files when you only need the text and subtitle files.

## `saveSubtitleFiles` (type: `boolean`):

Save subtitles (SRT, WebVTT) and the plain text to the run's key-value store and link them in <code>files</code>.

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

Longer files get a TOO_LONG error item and are not charged (1-300).

## `fileTimeoutSecs` (type: `integer`):

A file that takes longer to transcribe gets a TIMEOUT error item and is not charged (60-14400).

## Actor input object example

```json
{
  "media": [
    "https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg"
  ],
  "model": "base",
  "task": "transcribe",
  "wordTimestamps": false,
  "vadFilter": true,
  "includeSegments": true,
  "saveSubtitleFiles": true,
  "maxDurationMinutes": 180,
  "fileTimeoutSecs": 3600
}
```

# Actor output Schema

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

No description

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

No description

# 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 = {
    "media": [
        "https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinplatelabs/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 = { "media": ["https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg"] }

# Run the Actor and wait for it to finish
run = client.actor("tinplatelabs/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 '{
  "media": [
    "https://upload.wikimedia.org/wikipedia/commons/3/35/First_Inauguration_of_FDR_-_Fear_Itself_Excerpt.ogg"
  ]
}' |
apify call tinplatelabs/transcriber --silent --output-dataset

```

## MCP server setup

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