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

Transcribe audio and video URLs to timestamped text with speaker labels, chapters, keywords and SRT/VTT subtitles in 99 languages.

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

## Pricing

from $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/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

## Whisper Speech to Text — Audio & Video Transcriber

Turn any direct audio or video URL into a clean, timestamped transcript with **speaker labels**, chapters, keywords and ready-to-use **SRT / VTT / TXT subtitle files** — in one run, from a spreadsheet-friendly dataset. Paste one file or a batch of ten; podcasts, interviews, meetings, webinars, voice memos and video files all work.

### What you get

Every row in the dataset carries a `rowType`, so you can filter to exactly what you need:

- **`minute`** — one row per transcribed minute with the plain-text transcript, the sentence-level `segments` (start, end, content, confidence, speaker), the language, and the names of the subtitle files
- **`speaker`** — one row per detected voice (`SPEAKER_1`, `SPEAKER_2`, …): speaking time, share of speech, word count, first-spoke timestamp and a sample quote
- **`chapter`** — pause-detected sections with `startSec`/`endSec`, a title from the opening sentence, a YouTube-ready `youtubeChapter` stamp (`MM:SS Title`) and a 200-character preview
- **`keyword`** — the ten most-mentioned topic words with occurrence counts and the timestamp of every mention
- **`file-summary`** — language, duration, transcribed minutes, word count, words per minute, speaker count, chapter count, top keywords and the full transcript text
- **`segment`** — opt-in, one row per sentence with exact timestamps (roughly 10 per minute of speech)
- **Subtitle files** — `transcript-1.srt`, `transcript-1.vtt` and `transcript-1.txt` per input file in the run's **Key-value store**, with `[SPEAKER_N]` tags when diarization is on

Files that fail to download, cannot be decoded, contain no speech or were trimmed produce an unbilled **notice row** (`noticeCode` + `message`), so an empty result is never silent.

### Use cases

- **Podcast show notes and SEO pages** — chapters with timestamps, keywords and a full transcript from one episode URL
- **Meeting and interview analysis** — who said what, how long each person spoke, and quotable lines per speaker
- **Video subtitling** — drop the SRT/VTT straight into YouTube, Premiere, CapCut or your player
- **Content repurposing** — turn webinars and recordings into blog posts, clips and social captions
- **Research pipelines** — sentence-level rows with timestamps and confidence scores for joining, searching and embedding
- **Multilingual archives** — 99 languages auto-detected, or translated straight into English

### How to use

1. Paste one or more **direct media URLs** (mp3, wav, m4a, aac, ogg, flac, mp4, mov, mkv, webm, …) into **Audio / video URLs**
2. Leave **Speaker diarization** on for anything with more than one voice; set **Number of speakers** if you know it
3. Optionally set a **Language** code, turn on **Translate to English**, or add **Word-level timestamps**
4. Use **Max minutes per file** and **Max result rows per run** as spend guards
5. Run the actor — rows appear in the **Dataset** tab, subtitle files in the **Key-value store** tab

Example input:

```json
{
  "audioUrls": ["https://example.com/podcast-episode-42.mp3"],
  "speakerDiarization": true,
  "numSpeakers": 2,
  "enrichmentRows": true,
  "segmentRows": false,
  "maxMinutesPerFile": 60,
  "maxResults": 500
}
```

### Output format

A `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…",
  "speakers": ["SPEAKER_1", "SPEAKER_2"],
  "segments": [
    { "start": 0.0, "end": 4.2, "content": "Welcome back to the show.", "confidence": 0.94, "speaker": "SPEAKER_1" }
  ],
  "language": "en",
  "task": "transcribe",
  "audioDurationSec": 1834.2,
  "subtitleFiles": ["transcript-1.srt", "transcript-1.vtt", "transcript-1.txt"],
  "charged": true
}
```

A `speaker` row:

```json
{
  "rowType": "speaker",
  "speaker": "SPEAKER_2",
  "speakingTimeSec": 412.5,
  "speechShare": 0.38,
  "wordCount": 1093,
  "segmentCount": 141,
  "firstSpokeSec": 12.4,
  "sampleQuote": "The thing nobody tells you about launching is…"
}
```

### Pricing

Pay per result row (`transcribed-minute` event). A row is a transcribed minute, a chapter, a keyword, a file summary, a speaker summary or an opt-in sentence segment. Minute rows that carry speaker labels add a `speaker-diarization` surcharge on top of the row price, because diarization is several times more expensive to run; switch **Speaker diarization** off when you only need the words. Notice rows and subtitle files are free. Switch off **Enrichment rows** or **Sentence segment rows** to receive only the rows you need, and cap any run with **Max result rows** or a maximum cost in the run options.

Free-plan runs return up to 25 rows without speaker labels; any paid plan lifts both limits.

### Notes and limits

- Direct file URLs only — pair with a downloader actor for YouTube, TikTok or other platform pages
- Up to 10 files per run and 500 MB per file; files longer than 60 minutes are transcribed in 60-minute parts, and speaker labels restart in each part
- Word-level timestamps are produced when speaker diarization is off; with diarization on, segments carry sentence-level timing
- Translate to English produces an English transcript without speaker labels
- Heavy crosstalk, phone-quality audio or very similar voices can blur speaker labels; setting **Number of speakers** helps
- Confidence scores are available on non-diarized transcripts

Only transcribe media you have the right to process. Files are downloaded into the run, transcribed, and discarded with it.

# Actor input Schema

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

Direct URLs to audio or video files (mp3, wav, m4a, mp4, ogg, flac, webm, …). Up to 10 files per run, 500 MB per file.

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

Alternative to the list above — a single direct media URL.

## `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 speech in any language directly into English text.

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

Add per-word start/end times to every segment (slower, larger rows). Word times are estimated and can drift by a few hundred milliseconds.

## `speakerDiarization` (type: `boolean`):

Detects the different voices in the recording and labels every transcript segment with SPEAKER\_1, SPEAKER\_2, … Adds one speaker summary row per detected voice (speaking time, word count, share of speech, sample quote) and \[SPEAKER\_N] tags in the SRT/VTT/TXT files. Recommended for meetings, interviews and podcasts.

## `numSpeakers` (type: `integer`):

If you know how many people speak (e.g. 2 for an interview), set it here for more reliable labels. Leave 0 to detect the count automatically.

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

Adds per-file enrichment rows: 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 pipelines that join on exact timestamps. Off by default because it multiplies the number of billed rows.

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

Transcription stops after this many minutes of audio per file (cost guard). Longer files are trimmed and flagged with a notice row. Max 240.

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

Upper bound on billable result rows (minutes, chapters, keywords, summaries, speakers, 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"
  ],
  "translateToEnglish": false,
  "wordTimestamps": false,
  "speakerDiarization": true,
  "numSpeakers": 0,
  "enrichmentRows": true,
  "segmentRows": false,
  "maxMinutesPerFile": 20,
  "maxResults": 100
}
```

# Actor output Schema

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

One row per transcribed minute, plus file-summary, speaker, chapter, keyword and optional segment rows. Every row carries rowType, sourceUrl, fileIndex and timestamps.

## `subtitles` (type: `string`):

transcript-N.srt, transcript-N.vtt and transcript-N.txt for each input file, stored in the default key-value store.

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("seemuapps/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"] }

# Run the Actor and wait for it to finish
run = client.actor("seemuapps/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"
  ]
}' |
apify call seemuapps/whisper-speech-to-text --silent --output-dataset

```

## MCP server setup

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