diff options
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 39 |
1 files changed, 32 insertions, 7 deletions
@@ -211,13 +211,38 @@ by default and correct; it is simply waiting for a publisher who marks breaks. ## Domain notes worth keeping - **A feed's declared duration is often wrong, and not by rounding.** Radiolab publishes Grass - Apes as `00:22:05`; the file ExoPlayer opens is 29:34. The seven and a half minutes between - them are dynamically inserted ads -- the feed states the ad-free content length and the CDN - stitches in the rest -- so the error is large, systematic, and worst on exactly the shows the - midroll detector cares about. `PositionWriter` replaces the stored value with the player's - once per episode, on the position tick, via the narrow `PlaybackStateDao`. Once per episode, - not once per tick: a lookup on every tick for the length of an episode is the per-episode - work the feed-scale note below warns about. + Apes as `00:22:05`; the file served is 27-30 minutes. The gap is dynamically inserted ads -- + the feed states the ad-free content length and the CDN stitches in the rest -- so the error + is large, systematic, and worst on exactly the shows the midroll detector cares about. + + **Two columns, not one.** `durationMs` is the feed's claim and stays the feed's: + `EpisodeMatcher.mergedWith` rewrites it on every refresh, correctly, which is why writing the + measured length there lasted exactly until the next refresh. `actualDurationMs` is what the + player measured and nothing else touches. **Read `playbackDurationMs`**, which prefers the + measured one -- the feed's figure otherwise sizes the decode buffer a full-episode scan + allocates, places the outro offset, and drives the finished check that would mark a + 29-minute episode played at 21. + + `PositionWriter` records it once per episode on the position tick, via the narrow + `PlaybackStateDao` -- not once per tick, which would be the per-episode work the feed-scale + note below warns about. + +- **The difference between the two durations is the advertising**, free and with no audio + analysis: `insertedAdMs`, shown on the episode screen. Peter's observation. It is also a + check on the midroll detector, which should eventually account for roughly that much. + **It is per *file*, not per episode** -- the same Grass Apes measured 7:29 of ads on one + fetch and 5:34 on another, because insertion happens per request. Do not treat it as a + stable property of an episode, and do not be surprised when a re-download changes the + length. + +- **A timestamped link shared in starts playing there.** `WatchLink` parses the `t`, the + repository stores it as the position, and the share activity hands the episode to + `MainActivity.playIntent` so the app opens on the player already playing -- the point being + to move between YouTube and Listen without hunting for your place. Re-sharing a video + already in the library updates its position and unplays it, which is the case that was + broken: the insert ignores a clashing guid, so every share after the first silently did + nothing. A share carrying no timestamp still just adds it quietly, since interrupting + whatever is playing would be rude. - **The media notification opens the app**, via `setSessionActivity` on the session. Without it the transport buttons work and tapping the body does nothing, which reads as breakage rather |
