# Public Audio Speech Transcription (`automation-lab/public-audio-speech-transcription`) Actor

Transcribe authorized public audio files into searchable text, detected language and timestamped speech segments, with optional word timing. Audio only; no private links or translation.

- **URL**: https://apify.com/automation-lab/public-audio-speech-transcription.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.44 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Public Audio Speech Transcription

Turn authorized direct public audio recordings into searchable text with audio speech transcription, detected language, timestamped segments, and optional word timing.

Supply audio file URLs, not website pages. Recognition runs locally inside the Actor with the multilingual Whisper tiny model on CPU. No transcription API key is required and audio is not sent to an external AI inference service.

### What does this Actor do?

The Actor downloads each unique audio URL, checks that it contains audio and no video stream, validates size and duration, and recognizes speech in its original language. Each source produces one dataset row containing either a transcript or an uncharged error.

It does not search for podcasts, discover new episodes, crawl social websites, translate speech, identify speakers, or access private recordings. You supply the authorized direct audio files each time.

### Who is it for?

- Podcast editors building searchable episode archives from public audio files.
- Researchers indexing recordings they are entitled to process.
- Training teams preparing timestamped reference text from authorized public lessons.
- Automation builders sending text and timestamps into downstream search and review pipelines.

### Why use this Actor?

Use a small, inspectable audio-only workflow rather than a website downloader. You get full text and machine-readable timing in the same record, without credentials for an AI provider. Optional word timing adds approximate alignment and probabilities without a separate charge event.

Whisper tiny favors low resource use over maximum accuracy. It is not equivalent to a larger Whisper model or professional transcription. Human review is important for names, numbers, accents and noisy recordings.

### Getting started

1. Choose an anonymous direct public audio file that you are authorized to transcribe.
2. Add its URL to `audioUrls`.
3. Leave `language` as `auto`, or supply a supported lowercase Whisper code such as `en`.
4. Enable `wordTimestamps` if individual words need approximate timing.
5. Run the Actor and open the dataset's Transcripts view.
6. Check `status` before using a row. Export JSON for nested segment and word data.

Example input:

```json
{
  "audioUrls": ["https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav"],
  "language": "auto",
  "wordTimestamps": true,
  "maxFileSizeMb": 25,
  "maxDurationMinutes": 10
}
```

### Input parameters

| Parameter | Default | Behavior |
| --- | --- | --- |
| `audioUrls` | Required | 1–10 URL strings; trimmed exact duplicates run once |
| `language` | `auto` | Detect speech language or force a lowercase Whisper code |
| `wordTimestamps` | `false` | Include word timing and estimated probabilities |
| `maxFileSizeMb` | `25` | Per-file binary megabyte cap; integer 1–100 |
| `maxDurationMinutes` | `10` | Per-file duration cap; integer 1–30 |

Both size and duration limits apply. Exceeding either rejects the file; audio is never silently truncated. Zero does not mean unlimited. Unknown input fields are rejected rather than silently ignored.

Only anonymous HTTP(S) on standard ports is supported. Each redirect is checked for public IP destinations and downloads use pinned DNS resolution. No custom headers, cookies, proxies, signed/expiring access links or credentials are accepted.

### What data can I extract?

| Field | Meaning |
| --- | --- |
| `sourceUrl` | Submitted URL without credentials, query or fragment; invalid URLs use a safe marker |
| `status` | `succeeded` or `failed` |
| `transcript` | Recognized text in the spoken language; null on failure |
| `language` | Language code for the first speech-bearing window |
| `languageProbability` | Model confidence estimate for that window |
| `durationSeconds` | Full source duration; null if probing failed |
| `segments` | Array of segment IDs, absolute start/end seconds and text |
| `words` | Optional array of text, absolute start/end seconds and probability |
| `model` | Recognition model and compute mode |
| `error` | Failure description or null on success |
| `processedAt` | UTC processing timestamp |

JSON preserves the nested timing arrays. CSV exports may represent those arrays as serialized values. There are no separate subtitle files or speaker labels.

### Output example

This excerpt comes from the public example's local recognition result. Word and segment arrays are shortened here for readability; actual rows retain all recognized entries.

```json
{
  "sourceUrl": "https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav",
  "status": "succeeded",
  "transcript": "And so my fellow Americans ask not what your country can do for you ask what you can do for your country",
  "language": "en",
  "languageProbability": 0.960389,
  "durationSeconds": 11,
  "segments": [{"id": 0, "start": 0, "end": 10.58, "text": "And so my fellow Americans ask not what your country can do for you ask what you can do for your country"}],
  "words": [{"start": 0, "end": 0.74, "text": "And", "probability": 0.714715}],
  "model": "Whisper tiny (int8 CPU)",
  "error": null,
  "processedAt": "2026-10-24T20:04:31.062Z"
}
```

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

Pricing is pay per event: one `start` event per run that produces a successful transcript, plus an `audio-minute` event for each started minute of each successful file. Failed files, silence-only files and duplicate URLs have no transcription event charge. Segments and words are included, not charged separately.

The run fee is **$0.0005**, charged only when at least one file succeeds. The per-started-minute prices depend on your Apify Store spend tier (qualifying aggregate monthly Store spend, not a private per-Actor volume discount):

| Tier | Price per successful audio minute |
| --- | --- |
| FREE | $0.00851 |
| BRONZE | $0.0074 |
| SILVER | $0.005772 |
| GOLD | $0.00444 |
| PLATINUM | $0.00444 |
| DIAMOND | $0.00444 |

Estimated BRONZE Actor event totals: one started minute costs $0.0079; five cost $0.0375; ten cost $0.0745; thirty cost $0.2225. These are examples, not guaranteed invoices; consult the active pricing panel. Round minutes up separately for each file: a 61-second file is two audio minutes; two 11-second files are two audio minutes. A run with no successful transcript has no Actor event charges. Apify may apply its own account/platform conditions.

### Accuracy, limits and performance

- WAV, MP3, FLAC, OGG and M4A are supported when FFmpeg recognizes their audio streams. Codec availability and source integrity still matter.
- Video containers, video streams, embedded cover-art video streams, web pages and playlists are excluded.
- The 30-minute and 100-MiB hard limits apply per file, with at most ten submitted URLs per run.
- Files run sequentially to keep memory bounded. Batched inference decodes at most 60 seconds at a time and offsets timestamps back to the original file.
- Speech crossing a processing boundary may be split or recognized less accurately. There is no overlap reconciliation.
- Auto language detection is performed per processing window; the row's language describes the first window with recognized speech. Code-switched recordings can vary by segment.
- Word timestamps are approximate alignment, not certified timing. Probabilities are model estimates, not accuracy guarantees.
- Noise, music and silence can cause missed speech or hallucinated words. Voice activity detection reduces but does not eliminate this risk.
- Downloads retry transient network failures and selected 408/429/5xx responses at most three times. Permanent errors do not trigger blind retry.

### Failure behavior and troubleshooting

Before inference, the Actor checks that the remaining run charge budget covers the complete file and any still-unpaid start event. An insufficient budget rejects that file without a transcription charge; it does not return an unmetered full transcript.

A failed file produces a row with `status: failed`, null transcript fields, empty timing arrays and an `error` message. Other files continue. If every file fails, the run fails rather than reporting an empty success. Partial-success runs can contain both success and error rows.

**The URL works in my browser but fails here.** Browser sessions, cookies, private networks, expired signatures and anti-bot access are outside scope. Use a genuine public audio download URL you are authorized to access.

**My MP3 says it contains video.** Some MP3s contain cover art exposed as a video stream. Remove cover art before supplying an audio-only file.

**No speech detected.** Check that the file contains intelligible speech. Music-only and silence-only files do not satisfy the transcription job.

**Recognition is wrong.** Try a clear source and an explicit language. Review names and numbers. This lightweight model does not promise professional accuracy.

### Integrations

Send successful transcript rows to a search index, research archive or document-processing pipeline. Keep segments alongside text so downstream reviewers can jump to the relevant audio time. A spreadsheet can track source URLs, status, language and processing date; use JSON storage for complete timing arrays.

With Make, Zapier, n8n or an Apify webhook, start the Actor after your upstream system supplies a new authorized public audio URL. Scheduling repeats the input you supply; this Actor does not monitor feeds or discover newly published episodes.

### API usage

Start once and retain the returned run ID. Follow that run to a terminal state before reading its default dataset. Do not restart a run merely because an HTTP client timed out.

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~public-audio-speech-transcription/runs' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"audioUrls":["https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav"]}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/public-audio-speech-transcription').call({
  audioUrls: ['https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav']
});
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 10 });
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/public-audio-speech-transcription').call(run_input={
    'audioUrls': ['https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav']
})
print(client.dataset(run['defaultDatasetId']).list_items(limit=10).items)
```

### MCP setup

Use the Actor-specific hosted endpoint rather than an unqualified tool catalog. Actor selection also exposes run/dataset helpers; inspect actual names and argument schemas with read-only `tools/list`.

#### Claude Code

```bash
claude mcp add --transport http apify \
  'https://mcp.apify.com?tools=automation-lab/public-audio-speech-transcription'
```

#### Claude Desktop and Cursor

Use a client version that supports remote HTTP MCP servers and configure your Apify authentication securely. The server URL is:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/public-audio-speech-transcription"
    }
  }
}
```

#### VS Code

```json
{
  "mcp": {
    "servers": {
      "apify": {
        "type": "http",
        "url": "https://mcp.apify.com?tools=automation-lab/public-audio-speech-transcription"
      }
    }
  }
}
```

Example prompt: “Transcribe this authorized public WAV file and show its language and the first five timestamped segments.”

For an authorized invocation, start once and keep the returned run ID and storage IDs. These IDs are metadata, not result rows. `call-actor` waits at most 45 seconds; if still running, follow the same run using `get-actor-run` with bounded backoff such as 2, 4, 8 then 10 seconds and a 120-second total consumer deadline. On timeout recover the known run instead of launching a duplicate; at the deadline report pending with the run ID. Report failures and partial rows honestly.

After success, use `get-dataset-items` with explicit limit, offset and needed fields. An example consumer budget is 20 source rows per page, at most 100 rows and 64 KiB of serialized result content admitted to model context. Enforce byte bounds host-side, summarize oversized rows with disclosure, and keep full exports outside model context. Report the continuation offset and incomplete status when bounded. If the client cannot enforce a byte ceiling, do not claim one. Tool discovery bytes are not necessarily model-visible context; no numeric token-savings claim is made.

### Legality and responsible use

Only process audio you own, are licensed to use, or are otherwise authorized to transcribe. Public accessibility does not itself grant copyright, privacy, redistribution or commercial usage rights. Do not submit sensitive recordings, private links, credentials or access tokens. This Actor does not grant permission to reuse third-party material.

Temporary audio and chunk files are removed after processing. Dataset records contain a sanitized source URL (credentials, query and fragment removed) and recognized speech; manage their storage, sharing and retention in your Apify account.

For support, open an issue on this Actor's Apify page with a safe input example and run link. Do not include credentials or private recordings.

Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed and reports are retained for 30 days.

### FAQ

**Does it translate or identify speakers?** No. It transcribes speech in its original language, without diarization.

**Can it transcribe a social media page or private storage link?** No. Supply an authorized anonymous direct audio-only file.

**Can I supply multiple files?** Yes, 1–10 URL strings. Exact trimmed duplicates run once. Each successful file is rounded up independently for billing.

**Does it return subtitles?** No separate SRT/VTT files are generated. Segment and optional word timestamps are available in JSON for downstream formatting.

### Related Actors

Use [Video to Text Transcriber](https://apify.com/automation-lab/video-to-text-transcriber) for the distinct supplied-video workflow. This Actor intentionally accepts audio-only files and does not replace a video downloader or extractor.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/public-audio-speech-transcription/changelog.md

# Actor input Schema

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

Provide 1–10 authorized, anonymous direct HTTP(S) audio-only file URL strings. Exact duplicate trimmed URLs are processed once. No video (including embedded cover-art video streams), web pages, playlists, private addresses, signed links or login. Failed files produce uncharged error rows; an all-failed run fails.

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

Use auto to detect the spoken language, or a lowercase Whisper language code such as en, es or de to force recognition. Unsupported codes fail for that file. This does not translate speech; detected language confidence is a model estimate.

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

Include a words array with approximate start/end seconds and recognition probabilities for each successful file. False omits words. Segment timing is always included. Word timing may increase runtime and is not speaker diarization.

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

Per-file download cap in binary megabytes (1,048,576 bytes), including redirects. Files exceeding the cap are rejected, never truncated. Range 1–100; no unlimited value. The duration limit also applies.

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

Per-file total audio duration cap, 1–30 minutes; default 10. Longer files are rejected after download, not silently clipped. Billing rounds each successful file up separately to whole audio minutes. There is no unlimited setting.

## Actor input object example

```json
{
  "audioUrls": [
    "https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/samples/jfk.wav"
  ],
  "language": "auto",
  "wordTimestamps": false,
  "maxFileSizeMb": 25,
  "maxDurationMinutes": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

Overview of transcript status, text, language and timestamped segments.

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

All fields, including optional words and languageProbability, without the overview projection.

# 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/ggerganov/whisper.cpp/master/samples/jfk.wav"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/public-audio-speech-transcription").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/ggerganov/whisper.cpp/master/samples/jfk.wav"] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/public-audio-speech-transcription").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/ggerganov/whisper.cpp/master/samples/jfk.wav"
  ]
}' |
apify call automation-lab/public-audio-speech-transcription --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/public-audio-speech-transcription"
        }
    }
}
```

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/DzWfSsDMSo2YAaga4/builds/5Af1MxcLKbdV6fFzn/openapi.json
