summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/cmd/listend/main.go54
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