diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-10-27 07:54:25 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-10-27 07:54:25 +0000 |
| commit | 50b52d58e9865ac01e5364ec68247edb323db9b7 (patch) | |
| tree | 868cb610482705138a32c07ffce95cae698b332b /server/cmd | |
| parent | aa046a7ee11a20914a5851dd0e5a89d129683b28 (diff) | |
Use the labels: seed signatures from them, and take them back
The labels have been arriving and sitting there. Now the shadow run
acts on all three kinds.
A report is advertising pointed at where detection found nothing, so
it becomes a signature in its own right -- that being the whole gap
the library exists to close, since the scan accounts for about 38% of
what the feeds imply is there.
A mark saying a break is right adds no audio, because the break is
harvested anyway. What it adds is that a person vouched for it.
A mark saying a break is wrong does two things. It stops that audio
being harvested, and it takes back any signature already held that
matches it. That second half is the one that matters: a signature
built from programme would cut the programme in every episode carrying
it, until somebody noticed. So his "no" removes it outright rather
than lowering a score.
Being pointed at outranks partners and occasions both. Those are ways
of inferring what a stretch of audio is; he was there. A confirmed
signature is trusted at once and stays confirmed -- he does not
un-hear it next week.
A report whose end was never corrected is trimmed to its first fifteen
seconds. An uncorrected end is wherever the 25-second jump landed
rather than where the advertising stopped, so its tail may be
programme -- and one ad unit is already far more audio than a landmark
fingerprint needs to be distinctive.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'server/cmd')
| -rw-r--r-- | server/cmd/listend/shadow.go | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/server/cmd/listend/shadow.go b/server/cmd/listend/shadow.go index 7531115..03f4b71 100644 --- a/server/cmd/listend/shadow.go +++ b/server/cmd/listend/shadow.go @@ -56,8 +56,24 @@ func (w *worker) runShadow(ctx context.Context, show *store.Show, episodes []*st Occasion: show.FeedURL + "@" + show.DetectedBatch, AtUnix: time.Now().Unix(), } + // What the listener has said, indexed so each episode can pick up its own. Labels outlive + // the episodes they were given on, so most of these belong to batches long since rotated + // out; only the ones matching this batch's guids are of any use here. + labels := map[string][]signature.ShadowLabel{} + for _, l := range w.state.Labels() { + if l.FeedURL != show.FeedURL { + continue + } + labels[l.GUID] = append(labels[l.GUID], signature.ShadowLabel{ + StartMs: l.StartMs, + EndMs: l.EndMs, + Advertising: l.Verdict == store.LabelAd, + EndMeasured: l.EndMeasured, + }) + } + for _, e := range episodes { - ep := signature.ShadowEpisode{ID: e.ID, FeedURL: show.FeedURL} + ep := signature.ShadowEpisode{ID: e.ID, FeedURL: show.FeedURL, Labels: labels[e.GUID]} for _, br := range e.Breaks { ep.Breaks = append(ep.Breaks, signature.ShadowBreak{ StartMs: br.StartMs, @@ -81,11 +97,12 @@ func (w *worker) runShadow(ctx context.Context, show *store.Show, episodes []*st novel++ } } - log.Printf("%s: shadow -- learned %d, reinforced %d, library %d (%d worth matching); "+ + log.Printf("%s: shadow -- learned %d, reinforced %d%s, library %d (%d worth matching); "+ "would cut %d, %d of them new%s, took %s", - show.Title, report.Harvested, report.Reinforced, w.signatures.Len(), - len(w.signatures.Trusted(shadowMinOccasions)), len(report.WouldCut), novel, - skippedNote(report.Skipped), time.Since(started).Round(time.Second)) + show.Title, report.Harvested, report.Reinforced, disownedNote(report.Disowned), + w.signatures.Len(), len(w.signatures.Trusted(shadowMinOccasions)), + len(report.WouldCut), novel, skippedNote(report.Skipped), + time.Since(started).Round(time.Second)) // The novel ones are the whole point: what the library would add to what detection already // publishes. Logged individually so they can be listened to and judged. @@ -104,6 +121,15 @@ func (w *worker) runShadow(ctx context.Context, show *store.Show, episodes []*st } } +// disownedNote reports signatures taken back because the listener said that audio is the +// programme. Always logged when it happens: it is the library being told it was wrong. +func disownedNote(n int) string { + if n == 0 { + return "" + } + return fmt.Sprintf(", disowned %d", n) +} + func skippedNote(n int) string { if n == 0 { return "" |
