diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/cmd/second-probe/main.go | 56 | ||||
| -rw-r--r-- | server/internal/api/api.go | 19 | ||||
| -rw-r--r-- | server/internal/api/transcript_test.go | 66 |
3 files changed, 85 insertions, 56 deletions
diff --git a/server/cmd/second-probe/main.go b/server/cmd/second-probe/main.go deleted file mode 100644 index 1d2a840..0000000 --- a/server/cmd/second-probe/main.go +++ /dev/null @@ -1,56 +0,0 @@ -// Command second-probe subtracts a recognised second fetch from the mirrored copy. Throwaway. -package main - -import ( - "flag" - "fmt" - "os" - "path/filepath" - - "github.com/terst/listen/server/internal/transcribe" - "github.com/terst/listen/server/internal/transcript" -) - -func main() { - episode := flag.String("episode", "", "episode id") - secondFile := flag.String("second", "", "whisper -oj output for the second fetch") - servedMs := flag.Int64("served", 0, "") - declaredMs := flag.Int64("declared", 0, "") - show := flag.Bool("show", false, "") - flag.Parse() - - store := transcript.Store{Dir: "/site/listen.terst.org/data/transcripts"} - mirrored, err := store.Get(*episode) - if err != nil { - panic(err) - } - raw, err := os.ReadFile(*secondFile) - if err != nil { - panic(err) - } - second, err := transcribe.ParseOutput(raw) - if err != nil { - panic(err) - } - fmt.Printf("mirrored %d cues, second %d cues\n", len(mirrored.Cues), len(second.Cues)) - - found := transcript.Inserted(second.Cues, mirrored.Cues) - var total int64 - for _, c := range found { - total += c.EndMs - c.StartMs - fmt.Printf(" %s-%s (%s)\n", clock(c.StartMs), clock(c.EndMs), clock(c.EndMs-c.StartMs)) - if *show { - for _, cue := range mirrored.Cues { - if cue.StartMs >= c.StartMs && cue.EndMs <= c.EndMs { - fmt.Printf(" %.88s\n", cue.Text) - } - } - } - } - gap := *servedMs - *declaredMs - fmt.Printf("\n%d pods, %s found of the %s inserted (%d%%)\n", - len(found), clock(total), clock(gap), total*100/gap) - _ = filepath.Join -} - -func clock(ms int64) string { return fmt.Sprintf("%d:%02d", ms/1000/60, ms/1000%60) } diff --git a/server/internal/api/api.go b/server/internal/api/api.go index d2ad841..0d18c0f 100644 --- a/server/internal/api/api.go +++ b/server/internal/api/api.go @@ -97,6 +97,16 @@ type transcriptNote struct { // server keys them by its own id, and handing over a URL is what keeps that from having // to change. Empty when there is nothing to fetch. URL string `json:"url,omitempty"` + + // Ads and AdMs are what reading the words concluded about the advertising in this episode: + // how many stretches and how long they come to. Candidates, not skips -- nothing in the + // playback path reads them. + Ads int `json:"ads,omitempty"` + AdMs int64 `json:"adMs,omitempty"` + // Method is how they were found: "difference" where a second description of the programme + // was available to subtract, or the kinds of ad copy that were read otherwise. The two are + // not close in quality and the screen should not present them as if they were. + Method string `json:"method,omitempty"` } type breakRange struct { @@ -233,6 +243,15 @@ func (s *Server) transcriptNoteFor(e *store.Episode) *transcriptNote { if e.HasTranscript() { note.URL = "/api/transcript?episode=" + url.QueryEscape(e.ID) + "&token=" + url.QueryEscape(s.opts.Token) + if held, err := (transcript.Store{Dir: s.opts.TranscriptDir}).Get(e.ID); err == nil { + note.Ads = len(held.Ads) + for _, ad := range held.Ads { + note.AdMs += ad.EndMs - ad.StartMs + if note.Method == "" && len(ad.Signals) > 0 { + note.Method = ad.Signals[0] + } + } + } } return note } diff --git a/server/internal/api/transcript_test.go b/server/internal/api/transcript_test.go index 651225d..6d0ad7f 100644 --- a/server/internal/api/transcript_test.go +++ b/server/internal/api/transcript_test.go @@ -235,3 +235,69 @@ func TestTheTranscriptRouteNeedsTheToken(t *testing.T) { t.Errorf("status %d, want 401", rec.Code) } } + +/* +What reading the words concluded about the advertising, on the episode response. + +The phone needs it per episode and it is three numbers, so it travels with the line that says +there is a transcript rather than waiting for somebody to open one. The method travels with it +because subtraction and ad-copy reading are not close in quality -- 92-104% of the length gap +against 0-29% -- and a screen that showed only a figure would invite reading them alike. +*/ +func TestTheResponseSaysWhatTheWordsFound(t *testing.T) { + s, st, _, audioDir := newServer(t) + e := seedTranscribedEpisode(t, s, st, audioDir) + + held, err := (transcript.Store{Dir: s.opts.TranscriptDir}).Get(e.ID) + if err != nil { + t.Fatalf("Get: %v", err) + } + held.Ads = []transcript.Candidate{ + {StartMs: 1_000, EndMs: 61_000, Signals: []string{transcript.SignalDifference}}, + {StartMs: 100_000, EndMs: 130_000, Signals: []string{transcript.SignalDifference}}, + } + if err := (transcript.Store{Dir: s.opts.TranscriptDir}).Put(held); err != nil { + t.Fatalf("Put: %v", err) + } + + rec := get(t, s, "/api/episode?feed=https://f&guid=g1") + var got struct { + Transcript *struct { + Ads int `json:"ads"` + AdMs int64 `json:"adMs"` + Method string `json:"method"` + } `json:"transcript"` + } + if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { + t.Fatalf("decode: %v", err) + } + if got.Transcript == nil { + t.Fatal("no transcript line at all") + } + if got.Transcript.Ads != 2 || got.Transcript.AdMs != 90_000 { + t.Errorf("got %+v, want 2 breaks totalling 90s", *got.Transcript) + } + if got.Transcript.Method != transcript.SignalDifference { + t.Errorf("method = %q, want %q", got.Transcript.Method, transcript.SignalDifference) + } +} + +// An episode whose words turned up no advertising says nothing rather than zero. +func TestAnEpisodeWithNoAdvertisingInItsWordsSaysNothing(t *testing.T) { + s, st, _, audioDir := newServer(t) + seedTranscribedEpisode(t, s, st, audioDir) + + rec := get(t, s, "/api/episode?feed=https://f&guid=g1") + var got struct { + Transcript *struct { + Ads int `json:"ads"` + AdMs int64 `json:"adMs"` + } `json:"transcript"` + } + if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { + t.Fatalf("decode: %v", err) + } + if got.Transcript.Ads != 0 || got.Transcript.AdMs != 0 { + t.Errorf("got %+v, want nothing claimed", *got.Transcript) + } +} |
