Trigger icon
Fail icon
Script icon
If icon
Log icon
Exit icon
ChatCompletion icon
Anthropic icon
SlackIncomingWebhook icon
Pause icon
Upload icon
Parallel icon
List icon
Download icon
Set icon

Podcast Episode Publisher that Transcribes Locally, Writes Show Notes and Chapters with AI, and Publishes a Validated RSS Feed

Transcribe podcast episodes locally, draft show notes and chapters with AI, approve them, and publish a validated RSS feed to S3.

Categories
AIBusiness

Independent podcasters spend hours per episode on transcripts, show notes and chapter timestamps, then hand-edit an RSS feed where one wrong tag or file size stops Apple and Spotify from updating. This flow turns a finished recording into a published episode with a human approval step.

How it works

  1. new_episode (aws.s3.Trigger) picks up an .mp3 or .m4a in podcast/inbox/ and moves it to processing/; manual runs take an audio upload.
  2. probe (scripts.python.Script) rejects files that aren't audio and fingerprints the recording; an episode already published ends at skip_duplicate.
  3. transcribe runs faster-whisper on CPU (whisper_model, default base), so the audio never leaves your infrastructure.
  4. write_notes (ai.completion.ChatCompletion) drafts titles, summary, show notes, chapters and quotes; check_notes keeps only chapters inside the episode and quotes found word for word in the transcript.
  5. approve (Pause) publishes or rejects, with an optional title, episode number and explicit flag; no answer in 3 days cancels the run.
  6. aws.s3.Upload stores the audio, podcast:chapters JSON and podcast:transcript VTT; build_feed adds the episode (or creates the feed), validates it, backs up the old feed and only then replaces it.

What you get

  • A transcript, show notes, chapters and quotes in about the length of the episode, on CPU.
  • An RSS feed with exact enclosure sizes, durations and Podcasting 2.0 chapters and transcripts.
  • Unique file names per recording, so a new episode never overwrites a published one.
  • Outputs {{ outputs.episode_title }}, {{ outputs.audio_url }}, {{ outputs.feed_url }} and {{ outputs.transcript }}.

Who it's for

  • Independent podcasters, and teams publishing a company podcast.

Why orchestrate this with Kestra

  • Transcription, AI, approval and uploads in one YAML flow with retries and a failure alert.
  • The live feed is replaced only after the new one validates, so a failed run never breaks it.

Prerequisites

  • An S3 bucket (or S3-compatible store) served publicly at public_base_url; set the bucket, prefix and the show details under variables.
  • Docker on the worker; the first run downloads the Whisper model.

Secrets

  • S3_ACCESS_KEY_ID and S3_SECRET_KEY_ID: read the inbox and upload episodes and the feed.
  • ANTHROPIC_API_KEY: drafts the notes from the transcript (model in variables.claude_model).
  • SLACK_WEBHOOK_URL: previews, published and rejected notices, and failure alerts.

Quick start

  1. Set the variables and secrets.
  2. Execute with audio (FILE), episode_title (STRING, optional) and dry_run (BOOL, default false) set to true; read the preview.
  3. Execute without the dry run, approve, and open the feed URL in a podcast validator.
  4. Submit the feed URL to podcast directories once, then enable new_episode.

How to extend

  • Use a larger whisper_model for accents or noisy audio, or a GPU worker for long episodes.
  • Post the episode to social media or a newsletter after post_published.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.