# Transcribe Audio & Video to Text - Speech to Text, Whisper SRT (`kantolabs/audio-video-to-text`) Actor

Transcribe audio and video files to text with OpenAI Whisper: transcript, timestamped segments, SRT and VTT subtitle files, word timings, 99 languages with auto-detect. $0.008 per audio minute.

- **URL**: https://apify.com/kantolabs/audio-video-to-text.md
- **Developed by:** [Kanto Labs](https://apify.com/kantolabs) (community)
- **Categories:** AI, Videos, Developer tools
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 audio minutes

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 to Text - Whisper Transcriber with SRT & VTT Subtitles

**Transcribe audio and video files to text** with OpenAI **Whisper**: a clean transcript, **timestamped
segments**, ready-to-use **SRT and WebVTT subtitle files**, optional **word-level timestamps**, in
**99 languages** with automatic language detection. Paste links to MP3,
WAV, M4A, MP4, MOV, WEBM or MKV files and get text back in minutes. No API key, no OpenAI account,
no GPU. You pay **$0.008 per audio minute**, only for files that were actually transcribed.

### What does Audio & Video to Text do?

It downloads each audio or video file you link to, pulls out the sound track, skips silence with
voice-activity detection and runs Whisper speech recognition on the speech. For every file you get:

- the **full transcript** as plain text, split into paragraphs at pauses,
- **timestamped segments** (start, end, text) sized like real subtitles (max 2 lines of 42 characters),
- **SRT, VTT and TXT files** saved with download links (plus an optional full JSON file),
- the **detected language** and its confidence, duration, codec and speech length,
- optional **word timestamps** (start and end of every word).

### Use cases

- **AI and RAG pipelines** - turn podcasts, webinars, calls and course videos into text an LLM can search, summarize or answer questions about.
- **Subtitles and captions** - get SRT/VTT files for your own videos, lessons and social clips.
- **Podcasts and interviews** - show notes, quotes and searchable archives; paste the RSS feed and a schedule transcribes each new episode.
- **Meetings and voice notes** - text you can skim, search and share.
- **Content repurposing** - blog posts, newsletters and threads from your recordings.
- **Video analysis** - pair the transcript with keyframes from our [Video Frame Extractor](https://apify.com/kantolabs/video-frame-extractor) so a vision model sees *and* hears the video.

### How to transcribe a file

1. Click **Try for free**.
2. Paste direct links to your audio or video files into **Audio or video file URLs**, one per line.
3. Leave **Spoken language** on `auto`, or set a code like `en`, `es`, `de`, `ja`.
4. Click **Start**. Open the transcript in the results table, or download the SRT/VTT/TXT files from the links.

### Input

| Field | What it does | Default |
|---|---|---|
| `fileUrls` | Direct links to audio/video files. Dropbox and Google Drive share links are converted automatically | 1 sample (Gettysburg Address, public domain) |
| `language` | `auto` or an ISO 639-1 code (`en`, `es`, `fr`, `de`, `ja`, `zh`, `hi`...) | `auto` |
| `outputFormats` | Files to save: `txt`, `srt`, `vtt`, `json` | `txt`, `srt`, `vtt` |
| `wordTimestamps` | Add start/end of every word | `false` |
| `subtitleMaxChars` | Longest subtitle cue (2 lines) | `84` |
| `maxDurationMinutes` | Skip longer files (free) | `180` (max 300) |
| `maxFileSizeMb` | Skip larger files (free) | `1000` (max 4000) |
| `downloadTimeoutSecs` | Give up on slow downloads (free) | `600` |

```json
{
    "fileUrls": [
        "https://your-bucket.s3.amazonaws.com/podcasts/episode-42.mp3",
        "https://www.dropbox.com/scl/fi/abc123/interview.mp4?dl=0"
    ],
    "language": "auto",
    "outputFormats": ["srt", "vtt", "txt"]
}
```

### Podcast RSS + scheduled new episodes

Give it a podcast's **public RSS or Atom feed** and it transcribes the episodes' audio files, newest
first. Each result row carries the episode metadata next to the transcript: `feedUrl`,
`podcastTitle`, `episodeTitle`, `episodePublishedAt`, `episodeGuid` and `episodeUrl`.

| Field | What it does | Default |
|---|---|---|
| `rssFeedUrls` | Public podcast RSS/Atom feed URLs | - |
| `maxEpisodesPerFeed` | How many of the newest episodes of each feed to look at per run | `5` |
| `episodeDateFrom` | Leave out older episodes: `2026-10-01` or `7 days` | - |
| `onlyNewEpisodes` | Transcribe (and charge) only episodes not transcribed by an earlier run | `false` |
| `stateStoreName` | Named key-value store in your account that remembers done episodes | `kanto-transcriber-state` |

**Scheduled "new episodes only" mode.** Turn on `onlyNewEpisodes` and put the input on an Apify
schedule (daily or weekly). Every run reads the feeds, skips the episodes it already transcribed
(they produce **no row and no charge**, just a log line) and transcribes only the new ones. You
pay once per episode. Use a different `stateStoreName` per schedule to keep them apart; delete
that store to start over.

```json
{
    "rssFeedUrls": ["https://feeds.npr.org/510318/podcast.xml"],
    "maxEpisodesPerFeed": 3,
    "onlyNewEpisodes": true,
    "stateStoreName": "my-podcast-monitor",
    "outputFormats": ["txt", "srt"]
}
```

**n8n:** a *Schedule Trigger* (every morning) -> the **Apify** node, operation *Run actor and get
dataset*, actor `kantolabs/audio-video-to-text`, with the JSON input above -> each new episode
arrives as one item with `episodeTitle`, `text` and `srtUrl`; send it to an LLM for show notes,
to Notion/Sheets for an archive, or to Slack. A morning with no new episode returns 0 items, so
nothing downstream fires. **Make:** *Schedule* -> Apify *Run an Actor* (wait) -> *Get dataset items*.

Notes: reading feeds is free; you pay only the transcribed minutes. Feeds that fail (404, a web
page instead of a feed, a feed without audio files) return a free `failed` row that says what to
fix. Apple Podcasts and Spotify pages are not feeds - use the show's own RSS URL, which every
public podcast has. If you leave the sample link in `fileUrls` while adding a feed, the sample is
ignored.

**Supported formats:** MP3, WAV, M4A, AAC, OGG, OPUS, FLAC, WMA, AMR, MP4, MOV, M4V, WEBM, MKV, AVI,
MPEG-TS and anything else ffmpeg can decode. Video files are fine - only the audio track is used.

### Output

One dataset item **per file**. Real output from a cloud test run (`text` shortened, `segments` trimmed to 3 of 42):

```json
{
    "fileUrl": "https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3",
    "fileName": "gettysburg_address_64kb.mp3",
    "fileSizeBytes": 1350656,
    "durationSeconds": 157.884,
    "container": "mp3",
    "audioCodec": "mp3",
    "hasVideo": false,
    "speechSeconds": 144.3,
    "status": "ok",
    "language": "en",
    "languageProbability": 0.999,
    "task": "transcribe",
    "model": "Whisper base",
    "transcribedSeconds": 157.884,
    "truncated": false,
    "billedMinutes": 3,
    "wordCount": 308,
    "segmentCount": 42,
    "text": "This is a Libravox recording. All Libravox recordings are in the public domain. For more information or to volunteer, please visit Libravox.org.\n\nThe Gettysbur...",
    "segments": [
        {
            "id": 1,
            "start": 0.05,
            "end": 1.91,
            "text": "This is a Libravox recording."
        },
        {
            "id": 2,
            "start": 2.39,
            "end": 4.87,
            "text": "All Libravox recordings are in the public domain."
        },
        {
            "id": 3,
            "start": 5.49,
            "end": 9.99,
            "text": "For more information or to volunteer, please visit Libravox.org."
        }
    ],
    "txtUrl": "https://api.apify.com/v2/key-value-stores/dixfgDWP87NhufUSb/records/49d29889-gettysburg_address_64kb.txt?signature=...",
    "srtUrl": "https://api.apify.com/v2/key-value-stores/dixfgDWP87NhufUSb/records/49d29889-gettysburg_address_64kb.srt?signature=...",
    "vttUrl": "https://api.apify.com/v2/key-value-stores/dixfgDWP87NhufUSb/records/49d29889-gettysburg_address_64kb.vtt?signature=...",
    "processingTimeSeconds": 15.1,
    "realTimeFactor": 0.082,
    "error": null
}
```

The SRT/VTT/TXT links open without an Apify login, so you can pass them straight to a video
player, an editor, an LLM or a spreadsheet. A file that could not be transcribed gets a row with
`"status": "failed"` and an `error` that says how to fix the input - and costs nothing.

### How much does it cost to transcribe audio?

Pay per event, **no start fee per file, no monthly subscription**:

| Event | Price | When |
|---|---|---|
| Audio minute transcribed | **$0.008** per started minute ($8 per 1,000 minutes) | the file was transcribed |

Minutes are counted on the file's audio length, rounded up per file with a 1-second grace (a 2 min 10 s file = 3 minutes, a 60.4 s file = 1 minute).
**Free:** refused links, failed downloads, unreadable files, files with no audio track, files with
no speech (music or silence only), files over your size/duration limits.

Worked examples:

- A 45-minute podcast episode = 45 minutes = **$0.36**
- 100 product videos of 1 minute each = **$0.80**
- A 3-hour webinar = 180 minutes = **$1.44**

Set **Maximum cost per run** and the Actor never transcribes more minutes than that budget allows:
the last file is cut at the budget (and marked `truncated`), later files are listed as skipped, free.

### Speed and real costs (measured on Apify, October 2026)

| Test file | Audio | Run time | Billed | Price |
|---|---|---|---|---|
| Gettysburg Address (MP3, English) | 2 min 38 s | 26 s | 3 min | $0.024 |
| "Duck and Cover" 1951 film (MP4 video, English) | 9 min 14 s | ~2 min | 10 min | $0.08 |
| Tolstoy chapter (MP3, Spanish) | 21 min 54 s | ~5 min | 22 min | $0.176 |
| Melville's "Bartleby" (MP3, English) | 73 min | 20.5 min | 74 min | $0.592 |

Speech is transcribed at roughly 0.1-0.3x real time at the default 2 GB memory. Long files are
processed in ~10-minute parts cut at silent moments, so a 3-hour file needs no more memory than a
15-minute one. More memory makes a run start faster but does not change the price per minute.

### Use it from code, AI agents, n8n and Make

Python (`apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("kantolabs/audio-video-to-text").call(run_input={
    "fileUrls": ["https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"],
    "outputFormats": ["srt", "txt"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["language"], item["text"][:200], item.get("srtUrl"))
```

One HTTP call that waits for the result:

```bash
curl -X POST "https://api.apify.com/v2/acts/kantolabs~audio-video-to-text/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fileUrls": ["https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"]}'
```

- **AI agents (MCP):** add the Apify MCP server (`https://mcp.apify.com`) to Claude, ChatGPT, Cursor or any MCP client; the agent can find this Actor and call it whenever it needs to read what is said in an audio or video file.
- **n8n:** use the Apify node, operation *Run actor and get dataset*, actor `kantolabs/audio-video-to-text`, input `{"fileUrls": ["{{ $json.fileUrl }}"]}`, then map `text` or `srtUrl` into the next node.
- **Make / Zapier:** Apify module *Run an Actor* (wait for finish) -> *Get dataset items*.
- **Schedules and webhooks:** transcribe new uploads every hour, or get a webhook when a run finishes.

### Limits

- **Direct file links only.** YouTube, TikTok, Instagram, Facebook, X, LinkedIn, Vimeo, Twitch, Douyin, SoundCloud and Spotify pages are refused on purpose - their terms forbid downloading.
- Google Drive and Dropbox files must be shared as "anyone with the link". Private S3/R2/GCS objects need a pre-signed URL.
- Up to 300 minutes and 4 GB per file.
- No speaker labels (diarization) and no translation yet - the transcript does not say *who* speaks.
- Whisper base can mishear names and rare terms, and is weak on some languages: in our tests Hindi came out in Urdu script and Japanese had many kanji errors. For those, check the result on a short sample first. If the model gets lost on very unclear audio, the Actor stops there and charges only the minutes it transcribed.
- Music-only and silent files return a free "no speech" row; sung lyrics are transcribed poorly.

### FAQ

**Which languages are supported?** The 99 Whisper languages, including English, Spanish, French,
German, Portuguese, Italian, Dutch, Polish, Russian, Ukrainian, Turkish, Arabic, Hindi, Japanese,
Chinese, Korean, Indonesian and Vietnamese. Leave `language` on `auto` to detect it per file.

**Which model is it?** OpenAI Whisper **base** (74M parameters), int8, with Silero voice-activity
detection. It is fast and cheap and does well on clear speech in English, Spanish, French, German,
Italian, Portuguese, Dutch and other widely spoken languages. Transcripts include punctuation and
capitalisation.

**Can I get subtitles for my video?** Yes - every successful file gets an SRT and a VTT file with
cues of at most two 42-character lines, timed to the speech.

**Is it the real OpenAI Whisper?** Yes - the open-source Whisper base model (MIT licence) run with
faster-whisper (int8 CTranslate2) on Apify servers. Your files are not sent to OpenAI or any
other API.

**Does it work with YouTube links?** No. Download rights belong to the platform and the creator;
this Actor only processes files you can link to directly.

**What happens to my files?** They are downloaded to the run's temporary disk, transcribed and
deleted when the run ends. The transcripts stay in your run's storage under your Apify account.

**Something is not working?** Open an issue on the Issues tab with the file link - it is answered quickly.

### Related Actors by Kanto Labs

- [Video to LLM Context](https://apify.com/kantolabs/video-to-llm-context) - transcript aligned to each scene plus a keyframe per scene, ready for AI agents
- [Auto Captions & Lyric Video Maker](https://apify.com/kantolabs/auto-captions-lyric-video) - burn TikTok-style captions into a video or make a karaoke lyric video
- [Video Frame Extractor](https://apify.com/kantolabs/video-frame-extractor) - keyframes, scene changes and thumbnails from any video, ready for AI vision
- [Image to Text OCR](https://apify.com/kantolabs/image-to-text-ocr) - text from photos, screenshots and scanned PDFs
- [Document to Markdown](https://apify.com/kantolabs/document-to-markdown) - PDF, Word, PowerPoint and Excel to clean Markdown for LLMs

# Actor input Schema

## `fileUrls` (type: `array`):

Direct links to audio or video files (MP3, WAV, M4A, AAC, OGG, OPUS, FLAC, MP4, MOV, WEBM, MKV, AVI...), one per line. Your own storage, S3/R2/GCS (public or pre-signed URLs), CDNs, Dropbox and Google Drive share links (shared as 'anyone with the link') all work. Pages of platforms such as YouTube, TikTok or Instagram are refused. For podcasts, use 'Podcast RSS feed URLs' below.

## `rssFeedUrls` (type: `array`):

Public podcast RSS or Atom feed URLs, one per line (e.g. https://feeds.example.com/show.xml). The audio file of each episode (its enclosure) is transcribed, newest episodes first, with the podcast and episode title, date, GUID and link in each result. Apple Podcasts, Spotify and YouTube pages are not feeds - use the show's own RSS URL.

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

How many of the newest episodes of each feed to consider per run. With 'Only new episodes' on, the ones among them that were already transcribed are skipped for free.

## `episodeDateFrom` (type: `string`):

Optional. Leave out episodes published before this date: an absolute date like 2026-10-01, or a relative age like '7 days'.

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

Remember which episodes were transcribed, so the next run of the same feed only transcribes and charges NEW episodes. Already-done episodes produce no result row. Made for daily/weekly schedules. Applies to RSS feeds only.

## `stateStoreName` (type: `string`):

Named key-value store in your account where 'Only new episodes' remembers transcribed episodes. Use a different name per schedule to keep them separate; delete the store (or change the name) to start over.

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

'auto' detects the language of each file. Or give a 2-letter ISO 639-1 code (en, es, de, fr, pt, it, nl, pl, ru, uk, tr, ja, zh, ko, ar...) to skip detection - recommended for short clips and strong accents. 99 languages are accepted; accuracy is best for English and the major European and Asian languages.

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

Files saved to the run's key-value store, with download links in each result. The transcript text and timestamped segments are always in the dataset.

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

Also return the start and end time of every word (karaoke captions, search, editing).

## `subtitleMaxChars` (type: `integer`):

Longest subtitle cue (shown as up to 2 lines). 84 = two lines of 42, the common broadcast limit. Chinese, Japanese and Thai always use 32.

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

Longer files are skipped (free). Up to 300 minutes.

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

Larger files are skipped (free).

## `downloadTimeoutSecs` (type: `integer`):

Give up on a file that does not download within this time (free).

## Actor input object example

```json
{
  "fileUrls": [
    "https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"
  ],
  "maxEpisodesPerFeed": 5,
  "onlyNewEpisodes": false,
  "stateStoreName": "kanto-transcriber-state",
  "language": "auto",
  "outputFormats": [
    "txt",
    "srt",
    "vtt"
  ],
  "wordTimestamps": false,
  "subtitleMaxChars": 84,
  "maxDurationMinutes": 180,
  "maxFileSizeMb": 1000,
  "downloadTimeoutSecs": 600
}
```

# Actor output Schema

## `results` (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 = {
    "fileUrls": [
        "https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"
    ],
    "language": "auto"
};

// Run the Actor and wait for it to finish
const run = await client.actor("kantolabs/audio-video-to-text").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 = {
    "fileUrls": ["https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"],
    "language": "auto",
}

# Run the Actor and wait for it to finish
run = client.actor("kantolabs/audio-video-to-text").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 '{
  "fileUrls": [
    "https://archive.org/download/gettysburg_johng_librivox/gettysburg_address_64kb.mp3"
  ],
  "language": "auto"
}' |
apify call kantolabs/audio-video-to-text --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kantolabs/audio-video-to-text"
        }
    }
}
```

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/ojX7AwAF93toFwQWE/builds/bBaobbnYceRxuWGad/openapi.json
