# Remove podcast ads

Source: https://soundleafapp.com/remove-podcast-ads/

Self-hosted podcasts

## Remove Ads From Your Podcasts

Self-hosted solutions that work with the podcast app you already use. Real numbers from my own server, not a vendor pitch.

[Get MinusPod on GitHub](https://github.com/ttlequals0/MinusPod) [Compare all tools ↓](https://soundleafapp.com/remove-podcast-ads/#tools)

By [Hemant](https://soundleafapp.com/about/) · August 21, 2026

episodes tracked

3,357

hours of ads removed

34:56

total LLM spend

$43.93

per episode on Haiku

$0.09

Podcast ads are baked into the audio file itself, so ad blockers can't touch them. The approach that actually works: transcribe the episode with Whisper, have an LLM find the ad segments in the transcript, cut them out with FFmpeg, and serve the cleaned episode through a new RSS feed that your existing podcast app subscribes to. A handful of self-hosted tools do exactly this. I run one at home, it has cut over 1,300 ads from a single show so far, and this page covers how it works, what it costs to run, and which tool to pick.

### How it works

1.  Poll the real feed
    
    New episodes picked up on a schedule
    
2.  Transcribe
    
    Whisper, locally, on your hardware
    
3.  Detect
    
    An LLM marks the ad segments with timestamps
    
4.  Cut
    
    FFmpeg removes them cleanly
    
5.  Serve
    
    A rewritten RSS feed for your app
    

Your podcast app never knows the difference. You keep the app you already like, point it at the rewritten feed instead of the original one, and episodes just show up without ads. Nothing runs on your phone.

### Why you can’t just block podcast ads

There is nothing to block. A web ad is a separate request your browser can refuse. A podcast ad is part of the same MP3 as the show.

It gets worse with dynamic ad insertion (DAI), which most big shows use now. The host stitches ads in at download time, so two people downloading the same episode get different ads at different timestamps. A crowdsourced timestamp database (the SponsorBlock model that works so well for YouTube) breaks here, because the timestamps in my download don’t match yours.

So the ad has to be found in _your_ copy of the episode, every episode. That means listening to it, in the machine sense: transcribe, detect, cut.

### MinusPod, the one I run

Full disclosure, and honestly the reason you should trust this page: [MinusPod](https://github.com/ttlequals0/MinusPod) is a fork of [podcast-server](https://github.com/hemant6488/podcast-server), a podcast ad removal server I built and open sourced. The fork grew into a more mature product than my original, with a review UI, a verification pass, and pattern learning that mine never had. So I switched to it. Not every day your own project gets out-built, but the result is the best tool in this space, so I’ll take it.

Here’s my instance after about nine months of running this kind of setup, currently 9 feeds and 3,357 known episodes:

![MinusPod system status showing 9 feeds, 3,357 episodes, and 34 hours of ads removed](https://soundleafapp.com/blog/minuspod-system-status-dashboard.png)

That “Time Saved” number is real: almost 35 hours of ads I did not listen to.

What sets MinusPod apart from the simpler tools:

*   **A second pass** - after cutting, it re-transcribes the output and asks the LLM “what doesn’t belong here”. Anything that survived the first pass gets folded into a re-cut.
*   **Pattern learning** - confirmed ads become text patterns checked _before_ the LLM runs. A repeat sponsor gets caught for free, no API call, so cost drops the longer it runs.
*   **Confidence gates** - high-confidence detections are cut, borderline ones are held for your review instead of silently butchering the show.
*   **Beep instead of cut** - per category (sponsor, self-promo, intro), you can replace a segment with a short tone instead of removing it. That keeps the episode’s original length, so timestamps in show notes still line up.

Here’s what it did to one feed. Planet Money, 325 episodes processed, 1,318 ads removed:

![MinusPod feed stats for Planet Money: 325 episodes processed, 1,318 ads removed, 22.3 hours saved](https://soundleafapp.com/blog/minuspod-planet-money-ad-removal-stats.png)

#### Setting it up

It ships as a prebuilt Docker image with a compose file in the repo. The minimum config is an LLM API key, your public base URL, and a passphrase that encrypts stored keys:

```
mkdir -p /opt/minuspod && cd /opt/minuspod
curl -O https://raw.githubusercontent.com/ttlequals0/MinusPod/main/docker-compose.yml
docker compose up -d
```

One catch as of this writing: the shipped compose file has an empty `environment:` key under the optional `claude-wrapper` service, and compose rejects the whole file for it. Comment that line out and it validates.

```
# .env
ANTHROPIC_API_KEY=<key>              # or any OpenAI-compatible endpoint
BASE_URL=https://podcasts.example.com
MINUSPOD_MASTER_PASSPHRASE=<long random string>
OPENAI_MODEL=claude-haiku-4-5
WHISPER_MODEL=large-v3
WHISPER_DEVICE=cuda                  # or cpu
```

Three things I hit on a real install, so you don’t have to:

*   **A fresh install has no password and is fully open.** Set one in Settings > Security before exposing it to anything.
*   **Set `MINUSPOD_MASTER_PASSPHRASE` from day one.** Without it your API keys sit in the database as plaintext. Adding it later works, but backups made after that need the passphrase to restore.
*   **On plain HTTP, make sure `BASE_URL` starts with `http://`** (or set `SESSION_COOKIE_SECURE=false` on versions before 2.36), or the login cookie never sticks and it looks exactly like a wrong password.

A GPU is optional but makes a real difference. On my RTX 4060, Whisper transcribes at roughly 16x realtime, so an hour-long episode is done in about 4 minutes:

![GPU monitor showing Whisper transcription pinning an RTX 4060 at 100%](https://soundleafapp.com/blog/whisper-podcast-transcription-rtx-4060.png)

#### What it actually costs

The numbers nobody publishes. I run detection on claude-haiku-4-5, and a typical half-hour episode costs 5 to 11 cents to process:

![MinusPod episode list showing per-episode LLM cost of $0.05 to $0.11 on claude-haiku-4-5](https://soundleafapp.com/blog/minuspod-per-episode-llm-cost-haiku.png)

My whole instance, every episode across 9 feeds since I set it up, sits at $43.93 in total LLM spend. Cost scales with episode length (the transcript goes to the LLM in overlapping windows, so a 3-hour show costs roughly 6x a 30-minute one), and it falls over time as learned patterns start catching repeat sponsors before the LLM is ever called.

One tip: don’t pick the biggest model you can afford. MinusPod’s own benchmark of 83 models ranks claude-haiku-4-5 first for this task, ahead of frontier models costing 5x more. Ad detection rewards tight timestamps and restraint, not deep reasoning. Small and cheap wins here.

> Pro tip: process one feed first and watch the per-episode cost for a week before you backfill a 2,000-episode back catalogue.

#### Listening to the clean feeds

Any podcast app that accepts an RSS URL works. I subscribe to the rewritten feeds in [Audiobookshelf](https://www.audiobookshelf.org/) and listen in SoundLeaf, which keeps everything (audiobooks and de-ad-ed podcasts) on my own hardware end to end. One Audiobookshelf-specific catch: its SSRF protection blocks requests to private addresses, so if MinusPod lives on your LAN you need its host in `SSRF_REQUEST_FILTER_WHITELIST` or the feed won’t load.

MinusPod also generates transcripts and chapters for the cut audio and puts them in the feed as Podcasting 2.0 tags. Player support is patchy (Audiobookshelf reads the chapters and ignores transcripts, as of 2.36), but the data is there as apps catch up.

### Pick your tool

| Tool | Best for | Verification pass | Pattern learning | Fully local option |
| --- | --- | --- | --- | --- |
| [MinusPod ↗](https://github.com/ttlequals0/MinusPod) | The most complete setup, the one I run | Yes | Yes | Yes |
| [Podly Pure Podcasts ↗](https://github.com/jdrbc/podly_pure_podcasts) | Best-known project, $0/month fully local | No | No | Yes |
| [Podcast Ad Remover ↗](https://github.com/jdcb4/podcast-ad-remover) | Single container with SQLite, YouTube subscriptions | No | No | Yes |
| [podcast-server ↗](https://github.com/hemant6488/podcast-server) | My original: smallest codebase, easiest to read or fork | No | No | Whisper only |

The core idea is a few hundred lines of code. What you're really choosing between is how a tool handles its mistakes, because there will be mistakes, and a bad cut takes real show content with it.

### Apps that skip instead of cut

There are also player apps (Skipper and Podgy on iOS, STFUAI on Android) that detect ads at playback time and jump over them, and hosted services that run the same transcribe-and-cut pipeline on their servers for a subscription.

Both work, with the same tradeoff: someone else’s software sits between you and your shows. The skip apps only help inside their own player, so you give up the app you actually like. The hosted services route your listening through a third party. If you’re the kind of person who self-hosts a podcast server, neither is what you want, but they’re the honest alternative if you don’t want to run anything.

### FAQ

#### How do I remove ads from podcasts?

Run a tool that rewrites the feed: it downloads each episode, transcribes it with Whisper, finds the ad segments with an LLM, cuts them out, and serves a clean RSS feed. You subscribe to that feed in the podcast app you already use. [MinusPod](https://github.com/ttlequals0/MinusPod) is the most complete tool for this; setup is one Docker compose file and an LLM API key. If you’d rather not run a server, there are player apps that skip ads at playback instead, at the cost of switching apps.

#### Does this work with dynamic ad insertion?

Yes, and that’s the point. The detection runs on the transcript of the exact file you downloaded, so it doesn’t matter that your copy has different ads at different timestamps than anyone else’s.

#### What happens when I play an episode that isn’t processed yet?

MinusPod returns a “try again shortly” response to your app and starts processing in the background. It deliberately never falls back to serving the original file, because that would hand you the ad-filled version with no warning. First play of a new episode means a short wait; a half-hour episode takes about 5 to 7 minutes on my hardware.

#### Do I need a GPU?

No. Whisper runs on CPU, just slower. A GPU takes transcription from “minutes per episode” territory to roughly 16x realtime; even a mid-range consumer card like an RTX 4060 is plenty.

#### What does it cost to run?

My real numbers on claude-haiku-4-5: 5 to 11 cents per half-hour episode, $43.93 total for 9 feeds over the life of the instance. Fully local setups (local Whisper plus a local LLM) run at $0 per month on your own hardware.

#### Will I lose my listening history if I switch tools?

Yes, plan on it. These tools mint their own episode IDs, so when you switch, every episode looks new to your podcast app and played/unplayed state doesn’t carry over.

#### Is this legal?

These tools are built for personal use: you modifying episodes you downloaded, for your own listening, on your own server. Don’t redistribute the processed feeds. If a show you love runs ads, the ads are how it stays free, so consider its paid ad-free tier if it has one (I pay for a couple).

If you run Audiobookshelf and want the listening side of this on iOS, that's what I build [SoundLeaf](https://soundleafapp.com/) for. Add the cleaned feed to your server, then use the [podcast guide](https://soundleafapp.com/docs/podcasts/) for downloads, queues and transcripts. Happy (ad-free) listening!
