diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-10-29 19:44:34 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-10-29 19:44:34 +0000 |
| commit | b99fe8294e49804175e063c4447dfd664e349959 (patch) | |
| tree | 48eaaa44754aa43da86582b21647e992d89bccea /server | |
| parent | e40183385b6c983c0ac9413b18a2419409faee57 (diff) | |
Re-derive stored advertising when the rule improves
Recognition is the expensive part and its output does not change. Which
stretches of it are advertising is a judgement that does -- and when subtraction
learned to pull its edges off the programme, the eighteen episodes already
transcribed kept the old boundaries.
Re-recognising them to pick up a better answer would cost hours of CPU for text
already sitting on disk, so this runs over the stored transcripts at startup
instead: eighteen alignments, a few milliseconds each, writing only where the
answer actually moved. The next improvement costs nothing to apply either.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'server')
| -rw-r--r-- | server/cmd/listend/main.go | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/server/cmd/listend/main.go b/server/cmd/listend/main.go index 100eae5..dad5c30 100644 --- a/server/cmd/listend/main.go +++ b/server/cmd/listend/main.go @@ -129,6 +129,7 @@ func main() { defer stop() if *once { + worker.rederiveAds() worker.pollAll(ctx) // Recognition too, so a deployment check exercises the expensive path rather than // discovering it is misconfigured hours later in a log nobody is reading. @@ -216,6 +217,8 @@ func (w *worker) Request(feedURL, guid, enclosureURL, title string) { } func (w *worker) run(ctx context.Context, every time.Duration) { + w.rederiveAds() + w.save() w.pollAll(ctx) w.save() w.transcribeSome(ctx) @@ -528,6 +531,57 @@ func (w *worker) transcribeSome(ctx context.Context) { } /* +rederiveAds works out every stored episode's advertising again, from the words it already has. + +Recognition is the expensive part and its output does not change; which stretches of it are +advertising is a judgement that has. When subtraction learned to pull its edges back off the +programme, the episodes already transcribed kept the old boundaries, and re-recognising them to +pick up a better answer would cost hours of CPU for text that is already on disk. + +So it runs over the stored transcripts at startup instead -- eighteen alignments, a few +milliseconds each -- and the next improvement costs nothing to apply either. +*/ +func (w *worker) rederiveAds() { + changed := 0 + for _, show := range w.state.Shows() { + for _, e := range show.Episodes { + if e.MasterCues == 0 || !e.HasTranscript() { + continue + } + held, err := w.transcripts.Get(e.ID) + if err != nil { + continue + } + found := w.adsIn(e, held.Cues) + if sameCandidates(found, held.Ads) { + continue + } + held.Ads = found + if err := w.transcripts.Put(held); err != nil { + log.Printf("re-deriving %q: %v", e.Title, err) + continue + } + changed++ + } + } + if changed > 0 { + log.Printf("re-derived the advertising in %d stored transcript(s)", changed) + } +} + +func sameCandidates(left, right []transcript.Candidate) bool { + if len(left) != len(right) { + return false + } + for i := range left { + if left[i].StartMs != right[i].StartMs || left[i].EndMs != right[i].EndMs { + return false + } + } + return true +} + +/* adsIn works out which stretches of a recognised episode are advertising. By subtraction where the publisher's ad-free master is held, and by reading the ad copy where it |
