# Transcribe Audio & Video to Text: Speech to Text, SRT, VTT (`phaux/audio-video-transcriber`) Actor

Transcribe audio or video to text with open Whisper: direct media links, uploads or podcast RSS episodes. Use for speech-to-text or SRT/VTT subtitles. Input: mediaUrls or podcastRssUrls, optional model, language, outputFormats. Output per file: transcript, timestamped segments, SRT, VTT, minutes.

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

## Pricing

from $5.00 / 1,000 file transcribeds

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

## Transcribe Audio & Video to Text: Speech to Text, SRT, VTT

**Audio to text** and **video transcription** in one Actor: **speech to text** for recordings, podcasts and videos you own, with subtitle files ready to use.

Give this Actor links to your own audio or video files, or a podcast RSS feed. It returns a clean transcript with timestamps, plus SRT and VTT subtitle files. It runs the open Whisper model on Apify, so you need no API key and no third-party account. You pay per minute of audio actually transcribed, and files that fail cost nothing. It does not download from YouTube, TikTok, Instagram, Spotify or other platforms; use your own files.

### Quick start for AI agents and API users

- **What it does:** Transcribe audio or video to text with open Whisper: direct media links, uploads or podcast RSS episodes.
- **When to use it:** For speech-to-text or SRT/VTT subtitles.
- **Example input** (the form's prefill; it finishes in under a minute):

```json
{
  "mediaUrls": [
    {
      "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"
    }
  ],
  "model": "base",
  "language": "en",
  "maxMinutesPerFile": 1,
  "outputFormats": [
    "text",
    "srt",
    "vtt"
  ]
}
```

- **Example output:** one real dataset row from run `xxzBALvRPT6T4waYD` (2026-10-23), with long fields shortened and empty fields left out. Fields not shown are listed in the output table below.

```json
{
  "source": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg",
  "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg",
  "inputType": "url",
  "status": "ok",
  "fileName": "Jfk_rice_university_we_choose_to_go_to_the_moon.ogg",
  "model": "base",
  "language": "en",
  "languageProbability": 1,
  "durationSecs": 1060.25,
  "transcribedSecs": 60.01,
  "minutesCharged": 1,
  "text": "Mr. Vice President, Governor, Congressman Thomas, Senator Wiley and Congressman Miller, Mr. Webb, Mr. Bell, scientist, distinguished gues...",
  "truncated": true,
  "srtUrl": "https://api.apify.com/v2/key-value-stores/aKcf0hTYL5ee6PzfN/records/transcript-0001.srt?signature=12ZAgDYRdtIlTUn8sozM6",
  "vttUrl": "https://api.apify.com/v2/key-value-stores/aKcf0hTYL5ee6PzfN/records/transcript-0001.vtt?signature=1gXqozGcBx12buiyOkTje"
}
```

- **Cost (pay per event, Free-plan prices):** File transcribed $0.005; Minute of audio transcribed $0.008. Failed items are not charged.
- **From an AI agent:** with the Apify MCP server, call `call-actor` with actor `phaux/audio-video-transcriber`, or load it as its own tool with `https://mcp.apify.com?tools=phaux/audio-video-transcriber`. Read results with `get-dataset-items`.

### What does Audio & Video Transcriber do?

- **Transcribes speech to text** from audio and video files: mp3, m4a/AAC, wav, ogg/opus, flac, mp4, mov, webm, mkv and anything else FFmpeg can read.
- **Three ways in:** direct file links (your server, S3/GCS signed URLs, Dropbox direct links, Apify storage), **file upload** in the input form, or **podcast RSS feeds** (the newest episodes' audio enclosures).
- **Outputs** plain text, timestamped segments, optional word-level timestamps, and **SRT / WebVTT subtitles** (inline and as downloadable files in the key-value store).
- **99 languages** with automatic language detection, or set the language for better accuracy.
- **Reads only what it needs:** with *Max minutes per file* it stops reading after the first N minutes, so long files stay cheap.
- **Skips silence** with voice-activity detection, which is faster and avoids made-up text in quiet parts.

### Why use it?

- **Predictable price:** a small fee per file plus a price per minute transcribed. Failed, refused, silent or unreadable files are free.
- **No API key, no extra account:** the open-source Whisper model ([faster-whisper](https://github.com/SYSTRAN/faster-whisper), MIT) runs inside the Actor.
- **Subtitles ready to use:** SRT and VTT files you can upload to a video editor or player.
- **Your data stays yours:** the Actor keeps no transcript logs; results are only in your run's storage.

Use cases: meeting and interview recordings, lecture and webinar captions, podcast show notes and search, voice notes, call recordings you own, video subtitles, and feeding transcripts into an LLM or RAG pipeline.

### What it does NOT do

It refuses links to **YouTube, TikTok, Spotify, Apple Music / Apple Podcasts pages, SoundCloud, Instagram, Facebook, X/Twitter**, Vimeo, Loom, Twitch and similar platforms (also when a link redirects there). Those platforms' terms forbid third-party downloading. Use a file you have the rights to. Web pages are refused too: the link must point to the media file itself.

### How to use it

1. Paste direct links into **Media file URLs**, upload files under **Upload files**, or add **Podcast RSS feeds**.
2. Pick the **Model**: `base` (fast, default), `small` (more accurate on accents, noise and names) or `tiny` (rough drafts). The price is the same.
3. Set the **Language** (e.g. `en`) or leave `auto`.
4. For subtitles, keep `srt` / `vtt` in **Output formats** and optionally set **Caption max characters per line** (e.g. 42).
5. Optionally set **Max minutes per file** to cap cost, then run. Open the **Transcripts** or **Subtitles (SRT / VTT)** view, or download SRT/VTT from the links in each row.

### Tutorial: make SRT and VTT captions for a video

This walk-through makes subtitle files for a real recording: the first minute of John F. Kennedy's 1962 Rice University speech (public domain, Wikimedia Commons). Everything below is copied from an actual run of this Actor (22 Oct 2026, `small` model, 54 s run time).

**1. Input.** Point the Actor at the file, ask for `srt` and `vtt`, and set a caption line length so each cue fits on screen:

```json
{
  "mediaUrls": [{"url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"}],
  "model": "small",
  "language": "en",
  "maxMinutesPerFile": 1,
  "outputFormats": ["text", "srt", "vtt"],
  "captionMaxCharsPerLine": 42,
  "captionMaxLines": 2
}
```

**2. Run it**, then open the **Subtitles (SRT / VTT)** view of the dataset. Each row has `srtUrl` and `vttUrl` download links (files `transcript-0001.srt` and `transcript-0001.vtt` in the run's key-value store) and the subtitle text inline in `srt` / `vtt`. This minute became **15 cues**.

**3. The SRT file** (first 6 cues as returned):

```srt
1
00:00:02,450 --> 00:00:06,290
President Pipps,
Mr. Vice President, Governor,

2
00:00:08,150 --> 00:00:11,450
Congressman Thomas,
Senator Wiley and Congressman

3
00:00:11,450 --> 00:00:16,430
Miller, Mr. Webb, Mr. Bell, scientists,

4
00:00:17,330 --> 00:00:18,830
distinguished guests,
ladies and gentlemen.

5
00:00:19,530 --> 00:00:25,810
I appreciate your President having made me
an honorary visiting professor and I will

6
00:00:25,810 --> 00:00:29,050
assure you that my first
lecture will be very brief.
```

(The speaker actually says "President Pitzer". Speech models often mishear names. Check names before you publish captions.)

**4. The same cues as WebVTT**, for HTML5 players and most web video tools:

```vtt
WEBVTT

00:00:02.450 --> 00:00:06.290
President Pipps,
Mr. Vice President, Governor,

00:00:08.150 --> 00:00:11.450
Congressman Thomas,
Senator Wiley and Congressman
```

**5. Use the files.**

- **YouTube Studio:** Subtitles → Add language → Upload file → "With timing" → pick the `.srt`.
- **Premiere Pro / DaVinci Resolve / Final Cut (via SRT import):** import the `.srt` as a captions track.
- **HTML5 video:** `<track kind="captions" src="transcript-0001.vtt" srclang="en" label="English" default>`.
- **Burn in with FFmpeg:** `ffmpeg -i video.mp4 -vf subtitles=transcript-0001.srt out.mp4`.

**Caption length: with and without `captionMaxCharsPerLine`.** If you leave it at `0` (the default), you get one cue per Whisper segment, as before. Those cues are fine for search and notes, but they are often too long to read on screen. Here is what the same speech gave on the default setting (prefill run, `base` model):

```srt
2
00:00:11,750 --> 00:00:19,910
Miller, Mr. Webb, Mr. Bell, scientists, distinguished guests and ladies and gentlemen.
```

With `captionMaxCharsPerLine: 42` the Actor turns on word timestamps and re-cuts every segment at word boundaries. Each line is at most 42 characters, there are at most `captionMaxLines` lines per cue, and each cue lasts about 7 seconds or less. It prefers to break after punctuation and never splits "Mr. Bell". Good values are **42** (the common TV/streaming guideline), **32** (phones and vertical video) and `captionMaxLines: 1` (single-line social clips). The cues are what change. `text` and `segments` keep the same format, though word timestamps can shift segment boundaries a little. The price is the same.

### Input example

```json
{
  "mediaUrls": [{"url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"}],
  "model": "base",
  "language": "en",
  "maxMinutesPerFile": 1,
  "outputFormats": ["text", "segments", "srt", "vtt"]
}
```

Empty input runs a small example: the first minute of John F. Kennedy's 1962 Rice University "We choose to go to the Moon" speech (public domain, Wikimedia Commons).

| Field | Default | Description |
|---|---|---|
| `mediaUrls` | — | Direct links to audio/video files. |
| `uploadedFiles` | — | Files uploaded through the form (stored in your key-value store). |
| `podcastRssUrls` | — | Podcast RSS/Atom feeds; newest episodes first. |
| `maxEpisodesPerFeed` | `1` | Episodes per feed (1–100). |
| `model` | `base` | `tiny`, `base` or `small`. |
| `language` | `auto` | 2-letter language code or `auto`. |
| `maxMinutesPerFile` | `120` | Transcribe and charge only the first N minutes (1–300). |
| `outputFormats` | text, segments, srt, vtt | Any of `text`, `segments`, `words`, `srt`, `vtt`. |
| `captionMaxCharsPerLine` | `0` (off) | Re-cut SRT/VTT cues so each line has at most N characters (e.g. 42 or 32). 0 = one cue per segment, as before. |
| `captionMaxLines` | `2` | Lines per cue when the line limit is on (1–3). |
| `skipSilence` | `true` | Voice-activity detection. |
| `maxFiles` | `0` | Stop after N files (0 = all). |
| `timeBudgetSecs` | `0` | Stop after N seconds; a file cut short is charged only for what was transcribed. |

### Output example

```json
{
  "source": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg",
  "status": "ok",
  "fileName": "Jfk_rice_university_we_choose_to_go_to_the_moon.ogg",
  "model": "base",
  "language": "en",
  "durationSecs": 1060.25,
  "transcribedSecs": 60.01,
  "truncated": true,
  "minutesCharged": 1,
  "text": "... Mr. Vice President, Governor, Congressman Thomas, Senator Wiley and Congressman Miller, Mr. Webb, Mr. Bell, scientists, distinguished guests and ladies and gentlemen ...",
  "segments": [{"start": 2.45, "end": 11.73, "text": "..."}],
  "srt": "1\n00:00:02,450 --> 00:00:11,730\n...",
  "srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/transcript-0001.srt",
  "vttUrl": "https://api.apify.com/v2/key-value-stores/.../records/transcript-0001.vtt",
  "error": null
}
```

Failed or refused files get `"status": "failed"` and an `error` such as `{"code": "platform_not_supported", ...}`, `not_media`, `not_found`, `access_denied`, `robots_disallowed` or `unreadable_media`. They are not charged. `RUN_STATS` and `ERRORS` records are in the key-value store.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| File transcribed (once per file with a transcript) | $0.005 |
| Minute of audio transcribed (per started minute) | $0.008 |

Example: a 30-minute recording costs $0.005 + 30 × $0.008 = **$0.245**. A 10-file batch of 3-minute voice notes costs 10 × ($0.005 + 3 × $0.008) = **$0.29**. Minutes are counted from the audio actually transcribed (capped by *Max minutes per file*), rounded up to whole minutes per file. Set a maximum total charge on the run and the Actor stops before it.

### Tips and limits

- `small` is about 3× slower than `base`; for long files give the run more time (and 4 GB memory is faster).
- Default memory is 2 GB. For files longer than ~2 hours use 4 GB.
- Podcast feeds and enclosure hosts are checked against **robots.txt**; some ad-tracking redirect hosts disallow bots, and those episodes are reported as `robots_disallowed` (free).
- Private links (login, 401/403) can't be read; use a public or signed link, or upload the file.

### FAQ

**Can it transcribe YouTube, TikTok or Spotify links?**
No. Platform links are refused because those platforms' terms forbid third-party downloading. Use a direct link to a file you have the rights to, or upload the file.

**Which languages does it support?**
99 languages. Leave the language on `auto` to detect it, or set it (for example `en`) for better accuracy.

**Do I need an OpenAI or other API key?**
No. The open Whisper model runs inside the Actor.

**How much does a one-hour recording cost?**
$0.005 per file plus $0.008 per minute, so 60 minutes cost $0.005 + 60 × $0.008 = $0.485. Use *Max minutes per file* to cap it.

**Which model should I pick?**
`base` is the fast default. `small` is more accurate on accents, noise and names but about 3× slower. `tiny` is for rough drafts. The price is the same.

**How do I get subtitles?**
Include `srt` and/or `vtt` in *Output formats*. Each row has the subtitle text plus `srtUrl` and `vttUrl` download links. For on-screen captions, also set *Caption max characters per line* (for example 42). See the tutorial above.

**Am I charged for files that fail?**
No. Failed, refused, silent or unreadable files are free.

**Something isn't working?**
Open an issue on the Actor's Issues tab with the run ID.

### Legal

Transcribe only content you own or have the right to process. Copyright in the audio and the transcript stays with its owner. The Actor stores nothing beyond your run's own storage. FFmpeg (Debian build) is used to decode media; Whisper weights by OpenAI / Systran conversions are MIT-licensed.

# Actor input Schema

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

Direct links to audio or video files (mp3, m4a, wav, ogg, opus, flac, mp4, webm, mov, mkv ...), e.g. on your own server, S3/GCS signed links, Dropbox direct links or Apify storage. Web pages and platform links (YouTube, TikTok, Spotify, Apple Music, SoundCloud, Instagram, Facebook, X/Twitter) are refused.

## `uploadedFiles` (type: `array`):

Upload your own audio/video files (stored in your Apify key-value store) or paste their links.

## `podcastRssUrls` (type: `array`):

Podcast RSS/Atom feed URLs. The newest episodes' audio enclosures are transcribed (see Max episodes per feed). The feed host's robots.txt is respected. Example: \["https://feeds.npr.org/510289/podcast.xml"].

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

How many of the newest episodes to transcribe from each feed (1–100). Default: 1.

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

Whisper model size. base = fast and good for clear speech (default). small = more accurate on accents, noise and names, about 3x slower. tiny = fastest, rough drafts. The price is the same for all models.

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

Spoken language as a 2-letter code (en, de, es, fr, pt, it, nl, ja, zh ...), or auto to detect it. Setting it improves accuracy. Example: "en", "de" or "" for auto-detect. Default: "auto".

## `maxMinutesPerFile` (type: `number`):

Only the first N minutes of each file are transcribed and charged (1–300). Caps the cost of long files. Default: 120.

## `outputFormats` (type: `array`):

text = full transcript; segments = timestamped segments; words = word-level timestamps; srt / vtt = subtitle and caption files for video players, YouTube Studio, Premiere, DaVinci Resolve or HTML5 <track> (inline in each row and saved to the key-value store with srtUrl / vttUrl download links). Example: \["text", "srt", "vtt"]. Default: \["text", "segments", "srt", "vtt"].

## `captionMaxCharsPerLine` (type: `integer`):

Optional. 0 = off (default): one subtitle cue per transcript segment, exactly as before. Set e.g. 42 (broadcast/Netflix style) or 32 (phones, vertical video) to re-cut SRT/VTT cues at word boundaries so each line fits, using word timestamps. Only changes the srt/vtt output; price is the same.

## `captionMaxLines` (type: `integer`):

Lines per subtitle cue when 'Caption max characters per line' is set (1–3, default 2). Cues also never exceed 7 seconds.

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

Skip long silent parts with voice activity detection. Faster and avoids made-up text in silence. Billing is by audio length, not speech length. Default: true.

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

Stop after this many files (0 = all). Default: 0.

## `timeBudgetSecs` (type: `integer`):

Stop after this many seconds and keep what is done; a file cut short is charged only for the minutes transcribed (0 = only the run timeout guard). Default: 0.

## Actor input object example

```json
{
  "mediaUrls": [
    {
      "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"
    }
  ],
  "maxEpisodesPerFeed": 1,
  "model": "base",
  "language": "en",
  "maxMinutesPerFile": 1,
  "outputFormats": [
    "text",
    "srt",
    "vtt"
  ],
  "captionMaxCharsPerLine": 0,
  "captionMaxLines": 2,
  "skipSilence": true,
  "maxFiles": 0,
  "timeBudgetSecs": 0
}
```

# Actor output Schema

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

No description

## `runStats` (type: `string`):

No description

## `errors` (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 = {
    "mediaUrls": [
        {
            "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"
        }
    ],
    "model": "base",
    "language": "en",
    "maxMinutesPerFile": 1,
    "outputFormats": [
        "text",
        "srt",
        "vtt"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("phaux/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": [{ "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg" }],
    "model": "base",
    "language": "en",
    "maxMinutesPerFile": 1,
    "outputFormats": [
        "text",
        "srt",
        "vtt",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("phaux/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": [
    {
      "url": "https://upload.wikimedia.org/wikipedia/commons/5/50/Jfk_rice_university_we_choose_to_go_to_the_moon.ogg"
    }
  ],
  "model": "base",
  "language": "en",
  "maxMinutesPerFile": 1,
  "outputFormats": [
    "text",
    "srt",
    "vtt"
  ]
}' |
apify call phaux/audio-video-transcriber --silent --output-dataset

```

## MCP server setup

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