# Audio & Video File Transcriber – Whisper to Text, SRT, VTT (`raspberry_rondel/audio-video-file-transcriber`) Actor

Transcribe direct links to your own audio/video files (mp3, wav, m4a, mp4, ogg, flac) into text, timestamped segments, SRT and WebVTT subtitles with open-source Whisper on CPU. US$0.005 per run + US$0.004 per audio minute. Unofficial; no platform downloads.

- **URL**: https://apify.com/raspberry_rondel/audio-video-file-transcriber.md
- **Developed by:** [星賢 陳](https://apify.com/raspberry_rondel) (community)
- **Categories:** AI, Videos, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% 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 File Transcriber – Whisper to Text, SRT, VTT

Turn **direct links to audio or video files you have the right to use** (mp3, wav, m4a, mp4, ogg, webm, flac …) into:

- plain text,
- timestamped segments (`start`, `end`, `text`),
- **SRT** and **WebVTT** subtitles (in the dataset item and as files in the run's key-value store).

It runs the open-source Whisper model (MIT license) through [faster-whisper](https://github.com/SYSTRAN/faster-whisper) on CPU inside the Actor. No API key and no third-party transcription service is needed.

> **Unofficial.** This Actor is not affiliated with, endorsed by or connected to OpenAI, YouTube, TikTok, or other companies or platforms.

### Pricing

Pay-per-event:

- **US$0.005 per run** (start event, charged once per run, not per file, and only if at least one file is transcribed), plus
- **US$0.004 per audio minute.**

**Put many files into one run.** The start fee and the model start-up time are paid once per run, so 20 files in one run cost US$0.005 in start fees, while 20 separate runs cost US$0.10. `fileUrls` takes a list. Duplicate links are removed before anything is downloaded or charged. Matching ignores `#fragments`, tracking parameters (`utm_*`, `fbclid`, `gclid` and similar) and letter case in the domain. A duplicate gets a free row with status `duplicate`.

Example: one run with a 161 s file and a 263 s file = 0.005 + (3 + 5) × 0.004 = **US$0.037**.

- Each successfully transcribed file is charged for its duration **rounded up to the next whole minute** (24 s = 1 minute, 161 s = 3 minutes). The `chargedMinutes` field shows what each file cost.
- Failed downloads, rejected URLs, unreadable files and files skipped because of your spending limit are **free**. If no file in the run is transcribed (for example, because every link is invalid or rejected), the run costs nothing: the start fee is charged only together with the first transcribed file.
- **Files with no speech are free.** If no speech is detected in a file (for example only music or silence), it gets status `no-speech`, is not charged, and does not count as a transcribed file, so on its own it does not trigger the run fee. With `vadFilter: false`, Whisper may mistake music for speech and output text for it; such a file gets status `ok` and is charged like any other transcribed file.
- Your **maximum total charge** (`maxTotalChargeUsd`) includes the start fee. If it cannot cover the start fee plus one audio minute (US$0.009), the run stops without charging anything. A file that would exceed the remaining budget is skipped, not charged.
- A restarted or migrated run does not charge the start fee or the same file a second time.

### Accuracy (internal test, 2026-10-17, prototype version run locally; not promised)

- **English:** word error rate **4.6–7.8%** with the default `base` model on 4 public-domain LibriVox recordings (2.7–18 min), measured after trimming the LibriVox intro/outro. Clear read speech; noisy audio, overlapping speakers, strong accents and music will be worse.
- **Chinese:** output **may mix Simplified and Traditional characters** in the same transcript (see the example below). Convert afterwards (e.g. OpenCC) if you need one script.
- Names and rare words are often misspelled (e.g. "LibriVox" → "Libravox").
- `tiny` is faster but less accurate than `base`.

### Input

| Field | Default | Notes |
|---|---|---|
| `fileUrls` | – | Direct file links. **Platform page URLs (YouTube, TikTok, Instagram, Facebook, X, Vimeo, SoundCloud, Spotify, Bilibili …) are rejected**: this Actor does not download from such platforms. |
| `model` | `base` | `base` (more accurate) or `tiny` (faster). |
| `language` | auto | ISO code (`en`, `zh`, `es` …) to skip auto-detection. |
| `task` | `transcribe` | `translate` = English output for non-English audio. |
| `vadFilter` | `true` | Skips silence/music; reduces hallucinations. With `false`, music may be mistaken for speech and charged. |
| `beamSize` | `1` | 1 = greedy (fastest). |
| `maxFileSizeMb` | 200 | Hard limit (max 500). |
| `maxDurationMinutes` | 120 | Hard limit per file (max 120). Longer files are rejected and not charged. |

Each file gives one dataset item with `status` = `ok`, `no-speech`, `error` or `duplicate`, and a readable `error` message when it is not `ok`. `no-speech` means the file was processed but no speech was detected; it is free. `duplicate` means the link points to the same file as an earlier entry in the same run, after ignoring `#fragments`, tracking parameters (`utm_*`, `fbclid`, `gclid` and similar), letter case in the domain and the default port. A duplicate is not downloaded or transcribed, is free, and its `error` text names the earlier entry. This applies even if the earlier entry failed. One bad URL does not fail the whole run. If the file host answers HTTP 429/5xx, the Actor waits (honouring `Retry-After`) and retries up to 3 times, then reports the file as failed (free). It does not use proxies or try to get around rate limits.

### Output (real rows from a platform run, text shortened)

```json
{"url": "https://archive.org/download/gettysburg_address_librivox/gettysburg_address_lincoln_64kb.mp3", "status": "ok", "language": "en", "durationSeconds": 161.18, "chargedMinutes": 3, "segmentCount": 29, "text": "This is a Libravox Recording. All Libravox recordings are in the public domain. …", "srt": "1\n00:00:01,900 --> 00:00:04,620\nThis is a Libravox Recording.\n\n2\n…"}
{"url": "https://archive.org/download/call_to_arms_jl_librivox/calltoarms_06_lu_64kb.mp3", "status": "ok", "language": "zh", "durationSeconds": 262.95, "chargedMinutes": 5, "segmentCount": 45, "text": "魯迅小说急,那喊,一见小事。此次Librivalc's錄音由公眾所有。我从相下跑到京城里,一转眼已经六年了。…"}
{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "status": "error", "error": "Platform URLs are not supported (youtube.com). …"}
```

Items also contain `segments`, `vtt`, `processingSeconds`, `realTimeFactor`, `fileBytes` and `files` (links to the `.txt`, `.srt`, `.vtt` records in the key-value store).

### Speed

On the platform at 4 GB memory, transcription with `base` ran at about 0.08–0.12 × real time, plus about 10–20 s start-up per run. In internal tests (2026-10-17) a 4.4 min file took 30 s, an 8.5 min file took 50 s, and a 61.5 min audiobook chapter took about 7 min. Files longer than 15 minutes are transcribed in windows of about 10 minutes, cut at pauses. This keeps memory use roughly flat, so files up to the 120-minute limit fit in the default 4 GB. The default run timeout is 3 hours, enough for about 15 hours of audio in one run.

### API examples (all three were run and returned data in an internal test, 2026-10-17, build 1.0.2)

**curl**

```bash
curl -s -X POST "https://api.apify.com/v2/acts/raspberry_rondel~audio-video-file-transcriber/run-sync-get-dataset-items?fields=url,status,language,durationSeconds,chargedMinutes,text" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"fileUrls": ["https://archive.org/download/sammlung_deutscher_gedichte_018_1506_librivox/deutschegedichte018_03_wunder_hn_64kb.mp3"], "model": "tiny"}'
```

This one-file example costs US$0.005 + 1 × US$0.004 = US$0.009. For real work, list all your files in `fileUrls` in one run.
**Python** (`pip install apify-client`, v3)

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("raspberry_rondel/audio-video-file-transcriber").call(
    run_input={"fileUrls": ["https://archive.org/download/sammlung_deutscher_gedichte_018_1506_librivox/deutschegedichte018_03_wunder_hn_64kb.mp3"], "model": "tiny"}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["status"], item.get("language"), item.get("durationSeconds"), item.get("chargedMinutes"))
    print(item.get("srt", "")[:200])
```

**JavaScript** (`npm install apify-client`)

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('raspberry_rondel/audio-video-file-transcriber').call({
    fileUrls: ['https://archive.org/download/sammlung_deutscher_gedichte_018_1506_librivox/deutschegedichte018_03_wunder_hn_64kb.mp3'],
    model: 'tiny',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.status, item.language, item.durationSeconds, item.chargedMinutes, item.text?.slice(0, 120));
```

### Your responsibility

Only submit files you own or are allowed to transcribe. Transcripts can contain personal data spoken in the audio; you are responsible for handling it lawfully (e.g. under the GDPR or Taiwan's Personal Data Protection Act). Files are downloaded into the run's temporary storage and deleted after transcription; transcripts stay in your run storage under Apify's normal retention.

**Copyright.** Speech, music, lectures, podcasts and videos are usually protected by copyright. A transcript is a copy of the spoken words, and a **translation (`task: translate`) is a derivative work** (in Taiwan, translation is 改作 under [Copyright Act](https://law.moj.gov.tw/LawClass/LawAll.aspx?pcode=J0070017) Art. 3(1)(11) and Art. 28). Transcribe or translate only content you own, content you are licensed to use, or content where an exception such as fair use ([US 17 U.S.C. §107](https://www.law.cornell.edu/uscode/text/17/107)) or 合理使用 (Taiwan Copyright Act Art. 65) clearly applies.

**Why platform links are rejected.** Platforms such as YouTube do not allow downloading except as they expressly authorise. YouTube's [Terms of Service](https://www.youtube.com/static?template=terms) say you may not "access, reproduce, download … any Content except: (a) as expressly authorized by the Service; or (b) with prior written permission from YouTube and, if applicable, the respective rights holders". This Actor therefore accepts only direct file links and rejects platform URLs, including after redirects. Please do not use converter or mirror links to get around this.

**Rights holders.** If you believe this Actor has been used to process your content without permission, please contact us through this Actor's Issues tab on Apify.

This is general information, not legal advice.

### Other Actors by the same developer

- [Google Trends Scraper](https://apify.com/raspberry_rondel/actor-google-trends): interest over time, related queries and regions.
- [Google Autocomplete Keyword Expander](https://apify.com/raspberry_rondel/google-autocomplete-keywords): A–Z and question keyword ideas.

# Actor input Schema

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

Direct links to audio or video files you have the right to transcribe (mp3, wav, m4a, mp4, ogg, webm, flac, ...). Platform page URLs (YouTube, TikTok, Instagram, Facebook, X, Vimeo, ...) are rejected.

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

Whisper model size (open-source, runs on CPU). 'base' = better accuracy, 'tiny' = faster.

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

ISO code such as 'en', 'zh', 'es'. Leave empty to auto-detect.

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

'Translate' outputs English text for non-English audio (Whisper translate mode).

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

Skip non-speech parts with Silero VAD. Faster and reduces hallucinations on music/silence.

## `beamSize` (type: `integer`):

1 = fastest (greedy). Higher may be slightly more accurate but slower.

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

Files larger than this are rejected before/while downloading.

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

Files longer than this are rejected before transcription and not charged. Default and maximum: 120 minutes.

## Actor input object example

```json
{
  "fileUrls": [
    "https://archive.org/download/gettysburg_address_librivox/gettysburg_address_lincoln_64kb.mp3"
  ],
  "model": "base",
  "task": "transcribe",
  "vadFilter": true,
  "beamSize": 1,
  "maxFileSizeMb": 200,
  "maxDurationMinutes": 120
}
```

# Actor output Schema

## `transcripts` (type: `string`):

No description

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

No description

## `runSummary` (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_address_librivox/gettysburg_address_lincoln_64kb.mp3"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("raspberry_rondel/audio-video-file-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 = { "fileUrls": ["https://archive.org/download/gettysburg_address_librivox/gettysburg_address_lincoln_64kb.mp3"] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,raspberry_rondel/audio-video-file-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/b5HFSkxxDyStjvXqC/builds/9Pp3GF5Zk2R2E9fUb/openapi.json
