Skip to content

Intro and outro phrases, Transcribe again on Downloads, Custom only where it applies - #21

Merged
dben merged 5 commits into
mainfrom
ccr-70170a16-tewdp7
Oct 23, 2026
Merged

dben merged 5 commits into
mainfrom
ccr-70170a16-tewdp7

Conversation

@dben

@dben dben commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Intro and outro phrases

A podcast's Settings tab now lists phrases that end its intro and phrases that begin its outro, one a line (podblock/app/phrases.py).

  • Matched against the episode's timed transcript (the feed's, or whisper captions), ignoring case and punctuation.
  • Intro phrase in the first third: cut from the start through its first hearing. Outro phrase in the last third: cut from its last hearing to the end.
  • Hearings under 20 s apart count as one run, so a repeated chant is cut whole.
  • A line between slashes is a regex over the same normalised words: /(we are )*the youth of (the|a) nation/. Whole words only, at most 30 per match; invalid or empty-matching patterns are refused on save.
  • The captions job now saves whisper's per-word times (*.words.json) beside the captions, so cuts land between words. Feed transcripts, timed by cue, place words by their position in the cue.
  • Cuts are saved per episode (episodes.phrase_cuts), written into the chapters, and shown on the timeline as read-only Intro (phrase) / Outro (phrase).
  • Captions arrive after the first cut, so a phrase heard in them queues a re-cut; saving phrases queues only the ready episodes they'd cut differently.
  • Migration 16: podcasts.intro_phrases, podcasts.outro_phrases, episodes.phrase_cuts. No change to the whisper container.

Transcribe again (Downloads)

With a transcriber set, the downloads selection bar has Transcribe: a forced captions job that replaces any transcript the episode has, the feed's included, and deletes the replaced files. It also picks up speakers when WHISPER_SPEAKERS is on.

The selection bar's actions now wrap to their own row when they don't fit. On a phone, the podcast page's bar was already cutting off Archive and Clear.

Timeline: Custom only where it applies

A section was marked "Custom (this show)" whenever any block in it had a show type, even where that type didn't apply (an Outro block that also opens an episode is cut there as a plain repeat), leaving nothing to remove. Bumpers near non-break sections counted too. Now Custom means the show's type is the value shown, the section has blocks marked by hand, or it's a break with the show's bumpers.

Testing

  • ruff check . and the full suite (218 tests) pass.
  • New tests: tests/test_phrases.py; captions word times, phrase re-cut and forced transcription in tests/test_captions.py; end-to-end phrase cut through the settings route and the Custom regression in tests/test_processing.py.
  • Checked in Chromium: timeline with phrase cuts, the settings form (desktop and phone), and the selection bars at phone and desktop widths.

Generated by Claude Code

… a phrase to the end

Each podcast's Settings tab lists phrases that end its intro and phrases
that begin its outro. When an episode is cut, its timed transcript (the
feed's, or captions) is searched for them, ignoring case and punctuation:
an intro phrase in the first third cuts from the start through its first
hearing, an outro phrase in the last third from its last hearing to the
end. The cuts are saved on the episode, written into its chapters, and
shown on the timeline as Intro (phrase) and Outro (phrase).

The captions job now keeps whisper's time for each word beside the
captions, so these cuts land between words; feed transcripts, timed by
cue, place words by where they fall in the cue. Captions arrive after the
first cut, so a phrase heard in them queues the episode to be cut again;
saving new phrases queues the ready episodes they would cut differently.
The transcription service is unchanged: it already sent word times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015gCh3c3PYL5Y4shMugurtB
…ant is cut whole

A show's outro chant sung three times was cut only from its last time,
leaving the first two in. Hearings of any of a show's intro (or outro)
phrases less than 20 seconds apart now make one run, and the cut covers
the whole run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015gCh3c3PYL5Y4shMugurtB
…sion

`/youth of (the|a) nation/` is matched against the transcript's words as
plain phrases are: lower case, without punctuation, one space apart. It
matches whole words only, and at most 30 words at once, so a loose
pattern can't reach far. Invalid patterns, and ones that match nothing at
all, are refused when saving.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015gCh3c3PYL5Y4shMugurtB
… it is

A block set to Outro for a show that also plays at an episode's start is
cut there as a plain repeat, but the section was still marked Custom,
with nothing to remove. Bumpers near a section that isn't a break counted
too. Now a section is Custom when the show's type is the one it shows,
it has blocks marked by hand, or it is a break with the show's bumpers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015gCh3c3PYL5Y4shMugurtB
…ey have

With a transcriber set, the downloads page's selection bar has Transcribe:
it queues a captions job marked `force`, which transcribes the episode
even when it has a transcript, its feed's or earlier captions. The new
captions (with speakers, when the service finds them) replace it, and the
files they replace are deleted, apart from the ones written over.

The selection bar's actions now drop to a row of their own when they
don't fit, as on a phone; the podcast page's bar was cutting off Archive
and Clear there.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015gCh3c3PYL5Y4shMugurtB
@dben
dben merged commit 53f314e into main Oct 23, 2026
5 checks passed
@dben
dben deleted the ccr-70170a16-tewdp7 branch October 23, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants