# Podcast Show Notes & Clip Finder - Whisper (`yasaslive/podcast-clipper`) Actor

Transcribes podcast episodes from an RSS feed with Whisper, then generates show notes, chapter markers, pull-quotes and a ranked list of 30–60s clip-worthy segments with exact timestamps.

- **URL**: https://apify.com/yasaslive/podcast-clipper.md
- **Developed by:** [Eonix Pvt Ltd](https://apify.com/yasaslive) (community)
- **Categories:** AI, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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

## Podcast Show Notes & Clip Finder — Whisper

Point this Actor at a podcast RSS feed and every new episode comes back as ready-to-publish assets:

- **Full transcript** (`.txt`) and **subtitles** (`.srt`) with exact timestamps
- **Show notes** in Markdown — a hook paragraph plus topic bullets
- **Chapter markers** (start time + title)
- **Pull-quotes** with speaker guesses
- A **ranked list of 30–60 s clip-worthy segments** — start/end timestamps, the spoken words, a scroll-stopping hook line, a 0–100 score, and platform fit (Shorts / Reels / TikTok)

Transcription runs on **Whisper** — on the Actor's own CPU via faster-whisper (no external API needed) or through the OpenAI transcription API. The AI analysis (show notes, chapters, quotes, clips) uses one structured OpenAI call per episode and needs your OpenAI API key; **without a key you still get transcripts and subtitles**, and the clip-report fee is never charged.

**Built for:** podcasters and their editors, social teams clipping shows for short-form video, agencies producing show notes at scale, and anyone building a searchable archive of a show.

### How it works

1. Parses the RSS feed and picks the newest **unseen** episodes (or oldest first with `backCatalog`). Seen episodes are remembered per feed, so scheduled runs only pay for new content.
2. Streams the audio with a size guard — episodes above `maxAudioMb` are skipped with a `skipped_too_large` record and **charge nothing**.
3. Transcribes with Whisper; the status message updates every 60 seconds of processed audio, so long episodes visibly move.
4. Runs one structured LLM call per episode. Clips are enforced to 20–75 s, non-overlapping, capped at `maxClips`, ranked best first.
5. Pushes one dataset record per episode and saves `{guid}.txt`, `{guid}.srt` and `{guid}-shownotes.md` to the key-value store — all linked from the record and the Output tab.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `rssFeedUrl` | string | *(required)* | The podcast's public RSS feed URL. |
| `episodeLimit` | integer | `1` | Max unseen episodes per run (1–25). |
| `backCatalog` | boolean | `false` | `false`: newest unseen first. `true`: back catalog oldest → newest. |
| `transcriptionMode` | enum | `local-whisper` | `local-whisper` (on-CPU, no API cost) or `openai-api` (needs `openaiApiKey`). |
| `whisperModel` | enum | `base` | `tiny` / `base` / `small` — local mode only. Bigger = more accurate, slower. |
| `maxAudioMb` | integer | `300` | Larger episodes are skipped and never charged. |
| `maxClips` | integer | `8` | Upper bound on clip suggestions per episode (1–20). |
| `openaiApiKey` | secret | — | Enables the AI analysis and `openai-api` mode. Stored encrypted; sent only to api.openai.com. |
| `model` | string | `gpt-4o-mini` | OpenAI chat model for the analysis call. |
| `proxyConfiguration` | object | off | Optional proxy for feed/audio downloads. |

### Sample output

Real dataset record from a run against NPR News Now (`local-whisper`, `tiny`, no `openaiApiKey` → transcript-only):

```json
{
  "type": "episode",
  "feedUrl": "https://feeds.npr.org/500005/podcast.xml",
  "guid": "b326dfe6-8f9b-4f24-9525-e725000a6484",
  "episodeTitle": "NPR News: 08-13-2026 4AM EDT",
  "publishedAt": "2026-08-13T08:11:13Z",
  "durationSec": 298.1,
  "durationHuman": "4:58",
  "language": "en",
  "transcriptionMode": "local-whisper",
  "whisperModel": "tiny",
  "wordCount": 776,
  "transcriptPreview": "Live from NPR news in Washington, I'm Dan Roman.\nSome agents at immigration and customs enforcement will be getting new gloves to wear\non the field. [...]",
  "showNotesMarkdown": null,
  "chapters": [],
  "pullQuotes": [],
  "clips": [],
  "clipCount": 0,
  "analysis": "skipped-no-openai-key",
  "transcriptUrl": "https://api.apify.com/v2/key-value-stores/.../records/b326dfe6-...-2d7af797.txt",
  "srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/b326dfe6-...-2d7af797.srt",
  "showNotesUrl": null,
  "chargedEvents": { "audio-minute": 5, "clip-report": 0 }
}
```

With `openaiApiKey` set, `analysis` becomes `"ok"` and the record additionally carries:

```jsonc
"showNotesMarkdown": "…150–400 words of Markdown…",
"chapters":   [ { "start": 0, "title": "Intro" }, … ],
"pullQuotes": [ { "start": 154.2, "quote": "…", "speakerGuess": "Host" }, … ],
"clips": [
  {
    "start": 612.4, "end": 654.0,
    "transcript": "the words spoken in that window",
    "hookLine": "a scroll-stopping caption",
    "score_0_100": 91.0,
    "platformFit": ["shorts", "tiktok"]
  }, …
],
"showNotesUrl": "…/{guid}-shownotes.md"
```

The dataset's **Clips** view shows one row per suggested clip across all episodes. Oversized episodes produce a `skipped_too_large` record, failures an `episode_error` record, and each run ends with a `run-summary` listing counts and every saved file.

### Use cases

1. **Weekly clip pipeline** — schedule the Actor on your show's feed; every new episode lands as an SRT, show notes, and a ranked shortlist of moments to cut for Shorts/Reels/TikTok the same day.
2. **Back-catalog revival** — `backCatalog: true` with `episodeLimit: 25` works through an archive; per-feed state guarantees each episode is transcribed and billed exactly once.
3. **Agency show-notes desk** — one scheduled task per client feed; pull `showNotesMarkdown` and chapters straight into your CMS via the dataset API.

### Pricing (pay-per-event)

| Event | When it's charged | Price |
|---|---|---|
| Actor start | Once per run | **$0.00005** |
| Audio transcribed (per minute) | After transcription succeeds and the transcript + SRT are saved; every started minute counts | **$0.015 / minute** |
| AI clip report (per episode) | Once per episode when the AI analysis succeeds | **$0.07 / episode** |

You are never charged for failed or skipped work: oversized episodes, download failures and transcription failures charge nothing, and a failed or key-less analysis charges no clip report. **A one-hour episode with the full AI report costs about $0.97**; transcript-only about $0.90. Compare that with typical transcription services at $0.25–1.00 per minute.

**Quality note:** the default `base` model is solid for clear English audio but will make mistakes on crosstalk, heavy accents, music beds and niche jargon; `tiny` is rougher (fine for clip-finding, not verbatim quotes). Use `small` or `openai-api` mode when accuracy matters most. Whisper auto-detects ~100 languages; the record's `language` field reports what it heard.

### State, dedupe and reprocessing

- Processed episode GUIDs are stored per feed in the named key-value store **`podcast-clipper-state`**. A second run on an unchanged feed reports `0 new episodes` and charges only the Actor start fee.
- Episodes skipped as too large are remembered with their size; raising `maxAudioMb` above it makes them eligible again automatically.
- To re-process everything, delete the feed's key from `podcast-clipper-state` (Storage → Key-value stores).

### FAQ

**Do I need an OpenAI API key?** Only for show notes/chapters/quotes/clips (and `openai-api` transcription). Without it you still get transcripts and SRT files.

**Is my API key safe?** The field is marked secret, so the platform stores it encrypted. It is sent only to `api.openai.com` and never logged or written to output.

**Why did my run say "0 new episodes"?** Every episode in the feed is already in the state store — that's the dedupe working. See the section above to reset.

**Can it process video podcasts?** If the feed's enclosure is audio (`audio/*`), yes. Video enclosures are ignored.

**Private / paywalled feeds?** Any URL served without login works (including secret-token URLs). Feeds requiring cookies or auth headers are not supported.

**How are clips chosen?** The LLM proposes moments; the Actor then enforces 20–75 s length, clamps to episode bounds, drops overlaps (best score wins) and caps at `maxClips`, ranked by `score_0_100`.

**A 2-hour episode looks stuck.** It isn't — the status message updates every 60 seconds of processed audio. Expect roughly 15–30 minutes for a 2-hour episode on the default settings.

### Changelog

- **0.1** — Initial release: RSS ingestion with per-feed dedupe, local faster-whisper (tiny/base/small) and OpenAI API transcription with chunking, AI show notes / chapters / pull-quotes / ranked clips, SRT + transcript + show-notes artifacts, pay-per-event pricing, dataset Overview + Clips views and Output tab.

# Actor input Schema

## `rssFeedUrl` (type: `string`):

The public RSS feed of the podcast, e.g. <code>https://feeds.npr.org/500005/podcast.xml</code>.

## `episodeLimit` (type: `integer`):

Maximum number of unseen episodes to process in this run.

## `backCatalog` (type: `boolean`):

Off (default): process the newest unseen episodes. On: work through the back catalog oldest → newest.

## `transcriptionMode` (type: `string`):

<b>local-whisper</b> runs faster-whisper on the actor's CPU (no extra API cost). <b>openai-api</b> sends audio to OpenAI's transcription API and requires an OpenAI API key.

## `whisperModel` (type: `string`):

Model size for local-whisper mode. Bigger = more accurate but slower: tiny ≈ 3–4× faster than small.

## `maxAudioMb` (type: `integer`):

Episodes with larger audio files are skipped with a <code>skipped\_too\_large</code> record and are never charged.

## `maxClips` (type: `integer`):

Upper bound on the number of clip suggestions returned per episode.

## `openaiApiKey` (type: `string`):

Enables the AI analysis (show notes, chapters, pull-quotes, clips) and the openai-api transcription mode. Without it the actor outputs transcript-only records.

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

Chat model used for the per-episode analysis call. Must support JSON-object responses.

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

Optional proxy for fetching the RSS feed and audio files. Podcast CDNs are usually open, so no proxy is needed by default.

## Actor input object example

```json
{
  "rssFeedUrl": "https://feeds.npr.org/500005/podcast.xml",
  "episodeLimit": 1,
  "backCatalog": false,
  "transcriptionMode": "local-whisper",
  "whisperModel": "base",
  "maxAudioMb": 300,
  "maxClips": 8,
  "model": "gpt-4o-mini",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `episodes` (type: `string`):

All records pushed by this run: episode results, skips, errors and the run summary.

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

Key listing of the saved artifacts: {guid}.txt, {guid}.srt and {guid}-shownotes.md. Fetch each via .../records/{key}.

# 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 = {
    "rssFeedUrl": "https://feeds.npr.org/500005/podcast.xml",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yasaslive/podcast-clipper").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 = {
    "rssFeedUrl": "https://feeds.npr.org/500005/podcast.xml",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("yasaslive/podcast-clipper").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 '{
  "rssFeedUrl": "https://feeds.npr.org/500005/podcast.xml",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call yasaslive/podcast-clipper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yasaslive/podcast-clipper"
        }
    }
}

```

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/CnQzLoM08eElwRMoU/builds/24UPj9YGvRosY7A45/openapi.json
