# Podcast and Video to Text, Billed by the Minute (`usta/media-transcriber-by-minute`) Actor

For podcast producers and content-repurposing leads: turn public podcast RSS feeds or direct audio/video URLs into a timestamped transcript, billed one event per started audio minute.

- **URL**: https://apify.com/usta/media-transcriber-by-minute.md
- **Developed by:** [US Tech Automations](https://apify.com/usta) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$40.00 / 1,000 audio minutes

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

## Podcast transcript, audio transcription, and video to text, billed by the minute

This Actor takes public podcast RSS feeds or direct audio/video file URLs and returns a podcast transcript with timed audio transcription (and video to text when the file is video), one row per file, billed one event per started audio minute.

### Who it is for

A podcast producer or a content-repurposing lead who needs a back catalogue turned into articles and captions without uploading one file at a time.

### Input

| Field | What it does |
|---|---|
| Direct audio or video URLs | Public http(s) file links (mp3, wav, ogg, mp4, and other formats ffmpeg can read) |
| Podcast RSS feed URLs | Public RSS/Atom feeds; the Actor reads enclosure URLs from the feed |
| Maximum episodes per RSS feed | How many enclosures to take from each feed, from the top |
| Maximum files | Hard cap on files transcribed this run |
| Maximum minutes per file | ffmpeg stops each file after this many minutes |
| Whisper model | `base` (default, baked into the image) or `small`; CPU, int8 |
| Include SRT text | Optional SubRip captions on each row |
| Language hint | Optional (`en`, `es`, …). Blank = detect from the audio |
| Proxy configuration | Apify Proxy, **off** by default |

You must pass at least one direct file URL or one RSS URL.

### Output (one row per file)

| Field | What it holds |
|---|---|
| `source_url` | The media file that was transcribed |
| `title` | Episode title when the file came from an RSS feed; otherwise null |
| `language` | Language the model reported, or null |
| `audio_minutes` / `audio_seconds` | Length of the audio actually transcribed (after the per-file cap) |
| `text` | Full transcript text |
| `segments` | Timed `{start, end, text}` list |
| `srt` | SubRip text when Include SRT is on; otherwise null |
| `model` | `base` or `small` |
| `error` | Null on success. On failure this is the HTTP or tool error, and `text` is null |
| `fetched_at` | UTC timestamp of this run |
| `billed_minutes` | `ceil(audio_minutes)`, the number of `audio-minute` events for this row |

### Example row (live run on this machine, 2026-09-20)

Input:

```json
{
  "mediaUrls": ["https://archive.org/download/testmp3testfile/mpthreetest.mp3"],
  "maxItems": 1,
  "maxMinutesPerFile": 2,
  "modelSize": "base",
  "includeSrt": false
}
```

Output:

```json
{
  "source_url": "https://archive.org/download/testmp3testfile/mpthreetest.mp3",
  "title": null,
  "language": "en",
  "audio_minutes": 0.2068,
  "audio_seconds": 12.408,
  "text": "Okay, we are trying this for a second time to test the ability to upload an MP3 file. Hopefully this will work.",
  "segments": [
    {"start": 0.0, "end": 7.48, "text": "Okay, we are trying this for a second time to test the ability to upload an"},
    {"start": 7.48, "end": 12.24, "text": "MP3 file. Hopefully this will work."}
  ],
  "srt": null,
  "model": "base",
  "error": null,
  "fetched_at": "2026-09-20T21:47:53Z",
  "billed_minutes": 1
}
```

That file is 12.408 seconds of public test speech on archive.org. On this machine, one `fetch()` run (download + ffmpeg to 16 kHz mono + faster-whisper `base` int8 on CPU) returned the row above in 2.41 seconds of wall time. A whisper-only pass on the already-downloaded file took 1.08 seconds. Those are two measured runs of this one file, not a speed claim for other files or other machines.

### Pricing

**Pay per result.** On Apify the Actor charges one `audio-minute` event for every started minute of audio actually transcribed (`count = ceil(minutes)`). A 12-second file bills 1 event. A 90-second file bills 2 events. Error rows (HTTP 404, empty download, ffmpeg failure) bill 0. The store listing sets the dollar amount per event; this package does not.

**Maximum files** and **Maximum minutes per file** are the spend caps.

### Limits

- Public files only. No login, no cookies, no CAPTCHA solving.
- Direct file URLs, not a YouTube watch page or a site that only plays audio inside a logged-in player.
- CPU only. The image does not use a GPU.
- `base` is in the image. Choosing `small` downloads that model on first use.
- One file at a time. Default cap 5 files and 30 minutes each; hard cap 50 files and 180 minutes each.
- Hosts are asked 1 second apart, with a declared User-Agent.

### What this does not do

- It does not log in, store cookies, or bypass a paywall or DRM.
- It does not scrape YouTube, Spotify, or Apple Podcasts episode pages. Paste a public RSS URL or a public file URL.
- It does not promise a word-perfect transcript. The text is what faster-whisper `base` or `small` produced from the audio on this run. Quiet, overlapping, or noisy speech can come back wrong or empty. Empty text on a successful row means the model returned no words, not that words were invented.
- It does not check whether you have the right to transcribe the file you pointed at. The live sample uses a public-domain Internet Archive test file and LibriVox public-domain RSS feeds. Other URLs are your responsibility.
- It does not measure or guarantee runtime, accuracy, or uptime beyond the one sample above.

### Refunds and support

Refunds: if a run returns zero rows for a valid input, email operations@ustechautomations.com within 7 days and we refund that run. Support: same address, replies within 2 business days.

# Actor input Schema

## `mediaUrls` (type: `array`):

Public http(s) links to audio or video files (mp3, wav, ogg, mp4, and other formats ffmpeg can read). Not a login wall and not a YouTube watch page.

## `rssUrls` (type: `array`):

Public RSS or Atom feed URLs. Enclosures (the audio/video files the feed publishes) are downloaded in feed order, up to maxEpisodes per feed.

## `maxEpisodes` (type: `integer`):

How many enclosures to take from each RSS feed, starting at the top of the feed.

## `maxItems` (type: `integer`):

Hard ceiling on files transcribed this run (direct URLs plus RSS enclosures). This is the spend cap on the number of files, on top of the per-minute charge.

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

ffmpeg stops each file after this many minutes of audio. A 40-minute episode with this set to 2 produces about two minutes of transcript and two started-minute events.

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

faster-whisper on CPU, int8. 'base' is the default and is baked into the image. 'small' is optional and is downloaded on first use.

## `includeSrt` (type: `boolean`):

If on, each row also carries an srt field with the timed captions as SubRip text. Off by default.

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

Optional short code such as en or es. Leave blank and the model detects the language from the audio.

## `proxyConfiguration` (type: `object`):

Apify Proxy. Off by default. Local runs ignore this. Turn it on only if a public host is blocking the platform IP.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://archive.org/download/testmp3testfile/mpthreetest.mp3"
  ],
  "rssUrls": [
    "https://librivox.org/rss/100"
  ],
  "maxEpisodes": 3,
  "maxItems": 5,
  "maxMinutesPerFile": 30,
  "modelSize": "base",
  "includeSrt": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `csv` (type: `string`):

No description

## `report` (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 = {
    "mediaUrls": [
        "https://archive.org/download/testmp3testfile/mpthreetest.mp3"
    ],
    "rssUrls": [
        "https://librivox.org/rss/100"
    ],
    "maxEpisodes": 3,
    "maxItems": 5,
    "maxMinutesPerFile": 30,
    "modelSize": "base"
};

// Run the Actor and wait for it to finish
const run = await client.actor("usta/media-transcriber-by-minute").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 = {
    "mediaUrls": ["https://archive.org/download/testmp3testfile/mpthreetest.mp3"],
    "rssUrls": ["https://librivox.org/rss/100"],
    "maxEpisodes": 3,
    "maxItems": 5,
    "maxMinutesPerFile": 30,
    "modelSize": "base",
}

# Run the Actor and wait for it to finish
run = client.actor("usta/media-transcriber-by-minute").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 '{
  "mediaUrls": [
    "https://archive.org/download/testmp3testfile/mpthreetest.mp3"
  ],
  "rssUrls": [
    "https://librivox.org/rss/100"
  ],
  "maxEpisodes": 3,
  "maxItems": 5,
  "maxMinutesPerFile": 30,
  "modelSize": "base"
}' |
apify call usta/media-transcriber-by-minute --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,usta/media-transcriber-by-minute"
        }
    }
}
```

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/1rSAvF8UMQctSn4YS/builds/HiEOlsVw8t6Cmvdf4/openapi.json
