# Whisper Speech to Text — Audio & Video Transcriber (`ntriqpro/whisper-speech-to-text`) Actor

Turn audio and video into text with the open-source Whisper engine. Paste one or more file URLs and get back a timestamped transcript, per-segment detail, and ready-to-use SRT/VTT subtitle files — across 90+ languages, with optional translation to English.

- **URL**: https://apify.com/ntriqpro/whisper-speech-to-text.md
- **Developed by:** [daehwan kim](https://apify.com/ntriqpro) (community)
- **Categories:** Videos, AI, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$40.00 / 1,000 result rows

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/platform/actors/running/actors-in-store#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

## Whisper Speech to Text — Audio & Video Transcriber

Turn any **audio or video URL into accurate, timestamped text** — powered by [Whisper](https://github.com/openai/whisper), the state-of-the-art open-source speech recognition model, running here on the fast [faster-whisper](https://github.com/SYSTRAN/faster-whisper) engine. Paste one URL or a whole batch, get back a clean per-minute transcript table **plus ready-to-use SRT, VTT and TXT subtitle files** — in one run, with no OpenAI API key and no per-seat subscription.

> **Unofficial.** This Actor runs the open-source [faster-whisper](https://github.com/SYSTRAN/faster-whisper) engine (MIT) with OpenAI's open-source [Whisper](https://github.com/openai/whisper) models (MIT) and is **not affiliated with, endorsed by, or sponsored by** OpenAI or SYSTRAN. It processes **only the media URLs you provide**. You are responsible for having the right to transcribe those files and for complying with the source site's Terms of Service and the laws that apply to you.

***

### Why use this Actor?

- **One URL → the whole transcript, structured.** Every minute of speech becomes one dataset row with its text, sentence-level segments, exact timestamps and a confidence score — ready for spreadsheets, dashboards, embeddings or LLM pipelines.
- **Chapters, keywords and a summary — from the same run.** Each file also produces pause-detected **chapter rows with YouTube-ready `MM:SS Title` stamps**, the **top 10 keywords with every mention's timestamp**, and a one-row **file summary** (language, duration, word count, speech rate). Show notes, video chapters and topic research without a second tool.
- **Batch-first.** Feed 10 podcast episodes, interview recordings or video files in a single run.
- **99 languages, auto-detected.** Spanish meeting? Korean vlog? It just works — and the built-in **Translate to English** switch gives you an English transcript of any language in one step.
- **Subtitles included.** Each file also produces `.srt`, `.vtt` and `.txt` files in the run's key-value store — drop them straight into YouTube, Premiere or your video player. No extra charge.
- **Word-level timestamps** on demand, for karaoke-style captions or precise clip cutting.
- **Private by design.** Your media is processed inside the run and discarded with it. Nothing is sent to third-party transcription APIs.

Typical uses: podcast show notes and SEO pages, turning webinars into blog posts, subtitling short-form video, mining user interviews, monitoring earnings calls, making meeting recordings searchable.

***

### How to use it

1. Paste one or more direct media URLs into **Audio / video URLs** (mp3, wav, m4a, mp4, ogg, flac, webm and most other formats work).
2. Optionally pick a model, a language, or flip on **Translate to English** / **Word-level timestamps**.
3. Run it. Read the transcript in the **Dataset** tab; download subtitles from the **Key-value store** tab (`transcript-1.srt`, `transcript-1.vtt`, `transcript-1.txt`, …).

### Input

```json
{
    "audioUrls": [
        "https://example.com/podcast-episode-42.mp3",
        "https://example.com/interview.mp4"
    ],
    "model": "base",
    "language": "",
    "translateToEnglish": false,
    "wordTimestamps": false,
    "vadFilter": true,
    "maxMinutesPerFile": 20,
    "maxResults": 100
}
```

| Field | What it does |
|---|---|
| `audioUrls` (array) / `audioUrl` (single) | Direct URLs to media files. Up to 10 files per run, 500 MB per file. |
| `model` | `tiny` (fastest) · `base` (recommended) · `small` (most accurate; downloads on first use, ~1 min extra). |
| `language` | ISO 639-1 code (`en`, `es`, `ko`, …). Empty = auto-detect. |
| `translateToEnglish` | Transcribe any language directly into English. |
| `wordTimestamps` | Per-word start/end times inside every segment. |
| `vadFilter` | Skip long silences (faster, cleaner). On by default. |
| `enrichmentRows` | Adds the file summary, chapter and keyword rows (on by default). |
| `segmentRows` | Adds one row per sentence segment — roughly 10 rows per minute of speech. Off by default; see Pricing before enabling. |
| `maxMinutesPerFile` | Cost guard — transcription stops after this many minutes per file. |
| `maxResults` | Cap on billable result rows per run. |

### Output

Every row carries a `rowType` so you can filter in one click:

| `rowType` | How many | What it is |
|---|---|---|
| `file-summary` | 1 per file | Language, duration, transcribed minutes, word count, speech rate (wpm), chapter count, top keywords. |
| `chapter` | ~1 per 2–10 min | Pause-detected chapter with `startSec`/`endSec`, a title from its opening words, a YouTube-ready `youtubeChapter` stamp (`MM:SS Title`), a 200-character `textPreview` and word/segment counts. |
| `keyword` | up to 10 per file | A most-mentioned topic word with `occurrences`, `firstMentionSec` and `mentionsSec` (timestamps of mentions). English stopwords are filtered; other languages get plain frequency ranking. |
| `minute` | 1 per transcribed minute | The transcript workhorse row, unchanged from day one — see below. |
| `segment` | opt-in, ~10 per min | One sentence segment per row with exact timestamps and confidence (`segmentRows: true`). |

The `minute` row:

```json
{
    "rowType": "minute",
    "sourceUrl": "https://example.com/podcast-episode-42.mp3",
    "fileIndex": 1,
    "minuteIndex": 0,
    "startSec": 0,
    "endSec": 60,
    "transcript": "Welcome back to the show. Today we are talking about…",
    "segments": [
        {
            "start": 0.0,
            "end": 4.2,
            "content": "Welcome back to the show.",
            "confidence": 0.94
        }
    ],
    "language": "en",
    "languageProbability": 0.99,
    "task": "transcribe",
    "modelUsed": "base",
    "audioDurationSec": 1834.2,
    "subtitleFiles": ["transcript-1.srt", "transcript-1.vtt", "transcript-1.txt"],
    "charged": true
}
```

Files that fail to download, cannot be decoded, or contain no speech produce a separate **notice row** (`noticeCode` + `message`) instead — so "nothing found" is always distinguishable from "the run broke".

### Data fields

| Field | Meaning |
|---|---|
| `rowType` | `file-summary` · `chapter` · `keyword` · `minute` · `segment`. |
| `sourceUrl` | The media URL this row came from. |
| `minuteIndex` / `startSec` / `endSec` | Which minute of the recording this row covers. |
| `transcript` | All speech in that minute, as plain text. |
| `segments[]` | Sentence-level pieces with `start`, `end`, `content`, `confidence` (0–1), and `words[]` when word timestamps are on. |
| `language` / `languageProbability` | Detected language and detection confidence. |
| `task` | `transcribe` or `translate`. |
| `modelUsed` / `audioDurationSec` | Model that ran, and the file's total duration. |
| `subtitleFiles` | Names of the SRT/VTT/TXT files in the run's key-value store. |
| `charged` | Whether this row was billed. Notice rows are never billed. |

***

### Pricing / Cost estimation

**$0.04 per result row** (billed as the `transcribed-minute` event). A row is a transcribed minute, a chapter, a keyword, a file summary or an opt-in sentence segment — every row you receive is one event; rows you don't want can be switched off. No subscription, no monthly fee, no OpenAI API key. Failed downloads, unreadable files, silent audio and notice rows are **never charged**.

| What you transcribe (defaults: enrichment on, segments off) | Rows returned | Cost |
|---|---|---|
| 5-minute voice memo | ~5 minutes + ~1 chapter + up to 10 keywords + 1 summary ≈ 17 | **~$0.68** |
| 40-minute podcast episode | ~40 + ~8 + 10 + 1 ≈ 59 | **~$2.36** |
| 10 × 30-minute interviews | ~300 + ~60 + 100 + 10 ≈ 470 | **~$18.80** |

Want the plain per-minute transcript only? Set `enrichmentRows: false` — a 40-minute episode is then ~40 rows (**~$1.60**), exactly as before. `segmentRows: true` adds roughly 10 rows per minute of speech on top; enable it only when your pipeline needs sentence-level rows.

Three ways to control spend: switch off `enrichmentRows`/`segmentRows`, lower **Max minutes per file**, or set **Max result rows per run** — the run stops cleanly at that number and tells you it stopped. You can also set a maximum cost per run in the Actor's **Run options**; the run then finishes successfully with everything collected up to that point.

**Free-plan users** get a sample of up to **25 result rows per run** — the highest-value rows first (file summary → chapters → keywords → transcript minutes), so you see everything the Actor produces before upgrading. The run ends successfully with a message listing exactly what the full run contained.

***

### Tips

- **`base` is the sweet spot** for podcasts and meetings. Switch to `small` for noisy audio, heavy accents or dense technical vocabulary; drop to `tiny` for quick previews at half the runtime.
- **Batch related files in one run** — the model loads once and every additional file transcribes faster.
- **Setting `language` explicitly** skips detection and shaves a few seconds per file. Worth it on large batches in a known language.
- **Schedule it** against a podcast RSS enclosure URL and pipe the dataset into Google Sheets — an always-current, searchable archive of every episode.

### Limitations

- Transcribes **media you have the right to process**, fetched from direct URLs. It does not log into any site, bypass DRM or paywalls, or rip streaming platforms.
- Music, heavy crosstalk and very low-quality recordings reduce accuracy — that is a property of speech recognition, not of this wrapper.
- Speaker labels (diarization) are not included; segments are timestamped but not attributed to speakers.
- Files over 500 MB or past `maxMinutesPerFile` are truncated with a clear notice row (nothing silently dropped).

### Privacy & data protection

You (the customer) are the **data controller** for any personal data contained in the media you submit; this Actor acts as a **processor** during the run only. Media files are downloaded to ephemeral run storage, transcribed locally inside the run, and destroyed with it — **no transcripts or audio are retained by the developer**, and nothing is sent to third-party transcription services. Ensure you have a lawful basis (GDPR/PIPA/CCPA etc.) before transcribing recordings of other people.

### FAQ and support

**Is this the official OpenAI Whisper API?** No — it runs the same open-source Whisper models on the faster-whisper engine, inside Apify. Same quality family, no API key, per-minute pay-as-you-go.

**Which formats are supported?** Practically everything with an audio track: mp3, wav, m4a, aac, ogg, opus, flac, mp4, mov, mkv, webm and more.

**Can it transcribe YouTube/TikTok links?** No — it needs a *direct* media file URL. Pair it with a downloader Actor if your source is a platform page, and mind that platform's Terms of Service.

**Something is wrong or missing.** Open an issue on the Actor's Issues tab — it is read and answered.

⭐ If this Actor saved you time, a sentence about what you used it for helps the next person decide whether it fits their case.

# Actor input Schema

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

One or more direct URLs to audio or video files (mp3, wav, m4a, mp4, ogg, flac, webm, …). Max 10 files per run.

## `audioUrl` (type: `string`):

Alternative to the list above — a single media URL.

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

Larger models are more accurate but slower. "tiny" and "base" start instantly; "small" downloads on first use (~1 min extra).

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

ISO 639-1 code of the spoken language, e.g. "en", "es", "ko". Leave empty to auto-detect (99 languages supported).

## `translateToEnglish` (type: `boolean`):

Transcribe any language directly into English text (Whisper's built-in translation task).

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

Add per-word start/end times to every segment (slightly slower).

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

Voice-activity detection removes long silences before transcription — faster and fewer hallucinated repetitions. Recommended.

## `enrichmentRows` (type: `boolean`):

Adds per-file enrichment rows to the transcript: one file summary, pause-detected chapters with YouTube-ready timestamps, and the top 10 keywords with every mention's timestamp. Each delivered row is billed like any other result row.

## `segmentRows` (type: `boolean`):

Adds one row per sentence segment (roughly 10 per minute of speech). Useful for research pipelines that join on exact timestamps. Off by default because it multiplies the number of billed rows — check the pricing section before enabling.

## `maxMinutesPerFile` (type: `integer`):

Transcription stops after this many minutes of audio per file (cost guard). Max 240.

## `maxResults` (type: `integer`):

Upper bound on billable result rows (minutes, chapters, keywords, summaries, segments) returned by this run. Free-plan runs return at most 25.

## Actor input object example

```json
{
  "audioUrls": [
    "https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"
  ],
  "model": "base",
  "vadFilter": true,
  "enrichmentRows": true,
  "maxMinutesPerFile": 20,
  "maxResults": 100
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `subtitles` (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://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"
    ],
    "model": "base",
    "translateToEnglish": false,
    "wordTimestamps": false,
    "vadFilter": true,
    "enrichmentRows": true,
    "segmentRows": false,
    "maxMinutesPerFile": 20,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("ntriqpro/whisper-speech-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 = {
    "audioUrls": ["https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"],
    "model": "base",
    "translateToEnglish": False,
    "wordTimestamps": False,
    "vadFilter": True,
    "enrichmentRows": True,
    "segmentRows": False,
    "maxMinutesPerFile": 20,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("ntriqpro/whisper-speech-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 '{
  "audioUrls": [
    "https://raw.githubusercontent.com/ggml-org/whisper.cpp/master/samples/jfk.wav"
  ],
  "model": "base",
  "translateToEnglish": false,
  "wordTimestamps": false,
  "vadFilter": true,
  "enrichmentRows": true,
  "segmentRows": false,
  "maxMinutesPerFile": 20,
  "maxResults": 100
}' |
apify call ntriqpro/whisper-speech-to-text --silent --output-dataset

```

## MCP server setup

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