Episode Processing Workflows

September 16, 2026 ยท View on GitHub

< Docs index | Project README

Every way MinusPod can process an episode, in pictures. For the behaviour behind each stage, see How It Works.


Contents

The job

A published episode with pre-roll, mid-roll and post-roll ads, and the shorter file MinusPod serves in its place

The listener subscribes to a MinusPod address once. Everything below happens behind that address.


How work arrives

Scheduled poll, publisher announcement and listener playback all feed one queue that processes a single episode at a time

The Whisper pool

A waiting queue of episodes feeding a Whisper pool that transcribes four at once, which then hand off to the pipeline

The four concurrent episodes in the diagram are an example, not the setting. Concurrency is configurable: WHISPER_POOL_MAX_EPISODES accepts 1 to 16 and defaults to 1, and out-of-range values are clamped rather than rejected. A separate cap, WHISPER_POOL_MAX_REQUESTS (1 to 64, default 4), limits how many transcription requests are in flight at once.

By default one episode runs at a time. Turn on the Whisper pool and raise its per-episode limit to transcribe several at once; the rest wait in the queue and start as slots free. Each running episode still flows through the same pipeline once its transcript is ready. The pool is off by default and only the background leader process runs it, so a single instance never double-allocates the transcriber.

The pool only activates on the remote Whisper API backend. Turning it on while transcription runs locally leaves it inactive, because the local model runs in-process and several episodes would contend for the same GPU. An inactive pool reports a per-episode limit of 1 whatever the setting says, so the queue keeps running one episode at a time.


The standard pipeline

Eleven pipeline stages from download through publish, with the second download and audio analysis running in parallel

Amber badges mark the stages that make an LLM call. Transcription is billed too if you point it at a hosted Whisper API; on a local GPU it costs only time.

Long episodes transcribe in chunks sized to fit GPU memory. Cutting and normalizing a chunk is its own ffmpeg pass, and that pass runs ahead of the GPU: while one chunk transcribes, the next ones are already being prepared. The verify pass re-transcribes the cut file the same way.


Five kinds of evidence, five outcomes

Acoustic match, known script, copy comparison and audio signals are free; the model call is paid. All five feed one decision gate that cuts, beeps, keeps, holds or rejects

Four of the five cost nothing. Fingerprints, learned scripts and the two-copy comparison are gathered before the model reads the transcript, and go into its prompt as hints. Audio signals are measured then too, but only promote or extend a cut after detection runs. Whatever a source proposes still has to clear the gate.


Processing modes

One mode per feed. Changing it does not change the published address. A single episode can also be set to pass-through on its own, which overrides the feed mode for that episode only: it skips transcription, detection, and editing. The audio may still be transcoded for serving, so pass-through means no ad removal rather than byte-identical audio. Set it from the episode page's Reprocess menu, or select episodes on the feed page and use the bulk pass-through action.

Standard, keep content only, cue-only, skip ad detection and pass-through, each with the shape of audio it produces
StageStandardKeep contentCue-onlySkip detectionPass-through
Transcribeyesyesoptionalyesno
Second downloadper feedper feedper feednono
Audio analysisyesyesyesnono
Model reads transcriptyesinvertednonono
Learned patternsmatch, learnmatch onlymatch, learnnono
Verify passper feedper feednonono
Audio editedyesyesyesnono
Transcript, chaptersyesyesoptionalyesno

Keep content safety net. Marked content has to cover at least 55% of the runtime, no single cut may exceed 7 minutes or a quarter of the episode, and every transcript window has to come back labelled. Miss any of those and the episode falls back to standard detection on its own.


Re-running an episode

Reprocess, full analysis, re-detect ads and recut audio, showing which pipeline stages each one runs, reuses or skips

Reprocess and full analysis reuse the saved transcript when there is one, and transcribe again when there is not. Re-detect ads always needs one, so it skips episodes that have none.


Learning loop

Detected ads become stored patterns that match for free on later episodes, widening from one show to a network to global scope

Every pattern carries its own confirmation and false-positive counts. One you created or confirmed always cuts what it matches; one the system learned on its own still answers to the category actions set for the feed.

Community sync is opt-in in both directions. Nothing local is published unless you submit it.


When something breaks

A failed model call publishes partial cuts, an offline endpoint parks the episode, and an uncertain cut is held rather than applied

Nothing fails silently. A run with no free evidence to fall back on, or one that died on a bad API key, fails outright and waits for you on the episode page. The offline queue is off until you turn it on; without it, an unreachable endpoint retries and then gives up.


Diagrams are generated, not hand-drawn. Edit scripts/generate_workflow_diagrams.py and re-run it to rebuild docs/images/wf-*.svg. Colors come from the index.css tokens, so they track the app's own theme.

< Docs index | Project README