# Audio & Video Transcriber (Whisper, SRT/VTT) (`inn_corp/audio-video-transcriber`) Actor

Transcribe audio and video you supply, or public podcast RSS/Atom feed episodes, with Whisper (faster-whisper, int8) running inside the Actor. Plain text, SRT, VTT, and optional approximate word timestamps. No scraped platform video.

- **URL**: https://apify.com/inn\_corp/audio-video-transcriber.md
- **Developed by:** [Inn Corp](https://apify.com/inn_corp) (community)
- **Categories:** AI, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $25.00 / 1,000 audio minute 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Audio & Video Transcriber (Whisper, SRT/VTT)

Give it audio or video URLs, or public podcast RSS/Atom feeds, and get back a
clean transcript: plain text, SRT, VTT, and, if you want it, approximate
word-level timestamps. Transcription runs inside the Actor with
[faster-whisper](https://github.com/SYSTRAN/faster-whisper) (CTranslate2,
int8 quantized). No third-party transcription API in the loop, no scraped
platform video.

### What it does

- Fetches each URL with a single plain HTTP GET, downloads it to disk, and
  probes its duration with `ffprobe` **before** spending any compute on it.
- Extracts and normalizes audio with `ffmpeg` (16kHz mono), which is also
  how it pulls the audio track out of a video file. Works the same whether
  you point it at an MP3, an MP4, or anything else `ffmpeg` reads.
- Parses podcast RSS `<enclosure>` tags (and Atom `<link rel="enclosure">`)
  from feed URLs, up to `enclosuresPerFeed` episodes per feed, and runs each
  one through the same pipeline, tagged with the feed URL and episode title.
- Writes two record types, discriminated by `recordType`:
  - **`transcript`**, one per source that finished: `text`, `srt`, `vtt`,
    optional `wordTimestamps`, `detectedLanguage`, `durationSeconds`,
    `modelSize`, and where it came from (`sourceType`, `feedUrl`,
    `episodeTitle`).
  - **`summary`**, one per source attempt, always, success or not: `status`
    (`ok` / `too-long` / `download-failed` / `error`), `error` message, and
    `durationSeconds`.

### What it deliberately does not do

- **No YouTube, TikTok, Instagram, or any platform video.** This Actor only
  transcribes files you supply directly or podcast episodes from a public
  RSS/Atom feed's own `<enclosure>` link. That is the whole differentiator:
  rivals in this category feed on scraped platform URLs, which puts them on
  the wrong side of those platforms' terms; this one never goes there.
- **Word timestamps are Whisper's inference-time approximation, not exact
  forced alignment.** They drift, sometimes noticeably, around pauses,
  cross-talk, music beds, and fast speech. Treat them as "close," not
  "frame-accurate." Off by default; turn `wordTimestamps` on when you need
  them and can tolerate the imprecision.
- **No language is invented.** `detectedLanguage` comes from Whisper's own
  detection (or echoes back the `language` you supplied). A source with no
  intelligible speech will still return *something*; garbage in, garbage
  transcript, honestly labeled with whatever confidence Whisper had.
- **maxAudioMinutes is a real cap, not a suggestion.** Apify bills the
  Actor's operator for compute time, not the caller. A job that cannot
  finish inside the run's timeout would otherwise burn real money and
  produce nothing. Duration is checked with `ffprobe` before a single
  second of audio is transcribed; anything over the cap comes back as a
  clean `too-long` summary record, no charge, no wasted compute. Raise the
  cap only with model size and the numbers below in mind.

### Model size: speed vs. accuracy

Real-time factor (RTF) is compute minutes needed per minute of audio, on
this Actor's default 4096 MB / 1 vCPU allocation. Below 1.0x is faster than
real time.

| Model | Relative accuracy | Real-world feel |
| --- | --- | --- |
| `tiny` | Roughest; fine for skimming, gets names and jargon wrong more often | Fastest, cheapest |
| `base` (default) | Solid general-purpose accuracy | Good default for most podcasts and clean speech |
| `small` | Noticeably better on accents, cross-talk, and technical vocabulary | Meaningfully slower than base |
| `large-v3-turbo` | Best accuracy this Actor offers | Slowest and most expensive; reserve for content that has to be right |

**The measured number, not an estimate:** a real 9:11 (551s) public-domain
recording, transcribed on Apify's cloud infrastructure at `modelSize=base`
and 4096 MB, took 2 minutes 59 seconds (178.6s) of wall-clock run time end to end
(including model load) and used 0.198 compute units,
for an RTF of 0.32x. See "Fair pricing" below for what that
means in dollars.

### Podcast feeds

Tested against two real, currently-active feeds on two different hosts:
LibriVox's own generated podcast RSS (archive.org-hosted enclosures) and
NASA's official "Houston We Have a Podcast" feed (Megaphone-hosted). Neither
blocked a plain, honestly-identified HTTP GET. Podcast CDNs are built to be
fetched without authentication; that is the whole point of RSS-based
podcasting, and this Actor leans on exactly that, nothing more.

### Sources and privacy

This Actor transcribes audio and video you supply, or that you point it to
via public podcast RSS feeds. Use it only on content you have the right to
transcribe. It fetches URLs with a plain HTTP GET and never bypasses
paywalls, logins, or DRM. Your content and its transcript are yours; results
go only to your own Apify dataset.

### Output example

Real records from the cloud benchmark run against LibriVox's "The Raven"
(Edgar Allan Poe, public domain, 9:11 / 551s), `modelSize=base`.

A `transcript` record (SRT/VTT truncated for length):

```json
{
  "recordType": "transcript",
  "url": "https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_12_poe_64kb.mp3",
  "sourceType": "audioUrls",
  "feedUrl": null,
  "episodeTitle": null,
  "detectedLanguage": "en",
  "durationSeconds": 550.74,
  "modelSize": "base",
  "text": "Section 12 of Miscellaneous Poe This is a LibriVox recording. All LibriVox recordings are in the public domain. For more information or to volunteer, please visit LibriVox.org Recording by Rosanne Hoffman Youngstown, Ohio Miscellaneous Poe by Edgar Allen Poe Section 12, The Raven Once upon a midnight dreary, while I pondered weak and weary over many acquaint and curious volume of forgotten lore... [6,469 characters total]",
  "srt": "1\n00:00:00,000 --> 00:00:09,000\nSection 12 of Miscellaneous Poe This is a LibriVox recording. All LibriVox recordings are in the public domain.\n\n2\n00:00:09,000 --> 00:00:14,000\nFor more information or to volunteer, please visit LibriVox.org\n\n... [more cues] ...",
  "vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:09.000\nSection 12 of Miscellaneous Poe This is a LibriVox recording. All LibriVox recordings are in the public domain.\n\n00:00:09.000 --> 00:00:14.000\nFor more information or to volunteer, please visit LibriVox.org\n\n... [more cues] ...",
  "wordTimestamps": null,
  "fetchedAt": "2026-08-24T21:44:32+00:00"
}
```

The matching `summary` record:

```json
{
  "recordType": "summary",
  "url": "https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_12_poe_64kb.mp3",
  "sourceType": "audioUrls",
  "feedUrl": null,
  "episodeTitle": null,
  "modelSize": "base",
  "status": "ok",
  "error": null,
  "durationSeconds": 550.74
}
```

### Input

| Field | Meaning |
| --- | --- |
| `audioUrls` | Direct links to audio or video files. |
| `rssFeedUrls` | Public podcast RSS/Atom feed URLs. `<enclosure>` (or Atom `<link rel="enclosure">`) tags are parsed and each episode runs through the same pipeline. |
| `enclosuresPerFeed` | Max episodes pulled per feed, default 5. |
| `modelSize` | `tiny` / `base` (default) / `small` / `large-v3-turbo`. See the table above. |
| `language` | Optional ISO 639-1 code. Empty = auto-detect. |
| `wordTimestamps` | Adds an approximate per-word timing array. Default off. |
| `outputFormats` | Any of `text` (always included regardless of this setting) / `srt` / `vtt`. Formats you don't select come back `null`. |
| `maxAudioMinutes` | Duration cap, checked before transcription starts, default 15 (30 max). See "What it deliberately does not do" above for why this exists. |

### Typical uses

- Turn a podcast episode into captions (SRT/VTT) without a separate
  transcription subscription.
- Feed an AI agent or a RAG index the plain-text transcript of a recording
  it was pointed at directly, no scraping involved.
- Batch-transcribe your own interview or meeting recordings from wherever
  they're hosted.
- Monitor a small podcast feed for new episodes and keep a running
  transcript archive.

### Fair pricing

Pay per audio-minute actually transcribed (rounded up) and once per source
successfully processed, once pay-per-event pricing is enabled. Rejected,
too-long, and failed-to-download sources cost nothing. No subscription.

**The math, from the real cloud benchmark, not an estimate:**

- Measured: 550.74s of audio, `modelSize=base`, 4096 MB (1 vCPU), took
  178.6s of wall-clock run time end to end (download, ffprobe, ffmpeg
  normalize, model load, transcribe) and used 0.198 compute units.
- Chad's actual Apify account rate (confirmed via the API, Free plan):
  **$0.20 / compute unit**. 0.198 CU x $0.20 = **$0.0397** for that job.
- $0.0397 / 9.18 audio-minutes = **$0.0043 raw compute cost per
  audio-minute**, at `modelSize=base`.
- Apify pays the developer roughly 80% of what a pay-per-event charge
  collects. At a recommended price of **$0.025 per audio-minute
  transcribed**, Chad nets ~$0.020/minute, a **4.6x cushion** over the
  measured $0.0043 raw cost.

That cushion is deliberate, not padding: the per-minute charge is a single
flat event regardless of which `modelSize` the caller picks, and only
`base` (the default) was cloud-benchmarked here. `tiny` should be faster
still; `small` and `large-v3-turbo` were not cloud-tested and are
plausibly several times slower per audio-minute on CPU, by general
knowledge of how those model sizes compare, not a measurement. The 4.6x
cushion is what stands between a `large-v3-turbo` job and an unprofitable
one; it is a real number, not a guaranteed-safe one. **Recommend
benchmarking `small` and `large-v3-turbo` before trusting this price at
volume**, and treat $0.025/minute as an informed starting point, not a
final answer, when Chad sets it at publish.

Secondary event: **$0.01 per source successfully processed**, in line with
the flat per-item fee this Actor family already uses (`pdf-processed`,
`company-processed`), to cover the fixed per-job overhead (download,
probing, model warm-up) that the per-minute charge alone doesn't capture.

One more honest note: Apify Actor runs are ephemeral, so each run's model
warm-up may include downloading the selected Whisper model's weights fresh
rather than hitting a warm cache. The benchmark above reflects one real run
end to end, including that overhead; base and tiny are small (well under
200 MB), so this is unlikely to matter, and it's already inside the
measured number, not an extra cost on top of it.

# Actor input Schema

## `audioUrls` (type: `array`):

Direct links to the audio or video files to transcribe. Supply only files you have the right to transcribe: each is fetched with a plain HTTP GET, and the Actor never bypasses logins, paywalls, or DRM.

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

Public podcast feed URLs. The Actor parses each feed's <enclosure> (RSS) or <link rel="enclosure"> (Atom) tags and transcribes up to enclosuresPerFeed episodes per feed, newest first as the feed lists them.

## `enclosuresPerFeed` (type: `integer`):

How many enclosure URLs to pull from each RSS/Atom feed and transcribe.

## `modelSize` (type: `string`):

Bigger models are more accurate and slower. "base" is the default balance; see the README's speed/quality table before changing it for long files. Only "base" has a real cloud cost benchmark; "tiny", "small", and "large-v3-turbo" are unverified and may run slower (and cost more at the same per-minute price) than base.

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

ISO 639-1 code (e.g. "en", "es", "fr"). Leave empty to auto-detect from the first seconds of audio.

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

Adds a per-word start/end/probability array to each transcript. This is Whisper's inference-time approximation, not exact forced alignment; it can drift around pauses, cross-talk, and music. Off by default because it costs extra compute and most callers just want segment-level SRT/VTT.

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

Which caption formats to generate alongside the plain-text transcript (always included). SRT and VTT are skipped, saved as null, for formats you don't select.

## `maxAudioMinutes` (type: `integer`):

Duration cap, checked with ffprobe before transcription starts. Apify bills the Actor's operator for compute time, not the caller, so a job that can't finish inside the run timeout would otherwise silently burn money; anything over this cap is rejected with a clean "too-long" summary and no charge. Sized against a real cloud benchmark at modelSize=base (measured real-time factor 0.32x, i.e. faster than real time); the 30-minute ceiling and the Actor's 7200s run timeout both carry margin for slower model sizes, which were not separately cloud-benchmarked. See the README.

## Actor input object example

```json
{
  "audioUrls": [
    "https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_01_poe_64kb.mp3"
  ],
  "rssFeedUrls": [
    "https://librivox.org/rss/8892"
  ],
  "enclosuresPerFeed": 5,
  "modelSize": "base",
  "language": "en",
  "wordTimestamps": false,
  "outputFormats": [
    "text",
    "srt",
    "vtt"
  ],
  "maxAudioMinutes": 15
}
```

# Actor output Schema

## `records` (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 = {
    "audioUrls": [
        "https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_01_poe_64kb.mp3"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("inn_corp/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 = { "audioUrls": ["https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_01_poe_64kb.mp3"] }

# Run the Actor and wait for it to finish
run = client.actor("inn_corp/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 '{
  "audioUrls": [
    "https://www.archive.org/download/miscellaneouspoe_1501_librivox/miscellaneouspoe_01_poe_64kb.mp3"
  ]
}' |
apify call inn_corp/audio-video-transcriber --silent --output-dataset

```

## MCP server setup

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