Fix anipub decoy playlists (mpv never starts playback) - #114
Conversation
megap.kotocdn.site master playlists can be served with segments pointing at p16-ad-sg.ibyteimg.com (ByteDance ad CDN). The segments are 1x1 PNGs, so mpv stays on its idle screen and never starts playback (fixes #113). Validate resolved anipub streams before returning them: fetch the media playlist, reject all-ad or >=50% decoy playlists, and probe the first real segment's magic bytes for non-video content. Errors propagate up through ResolveEpisodeURLForPlayback so the provider stack falls back to anineko/ allanime/etc. instead of opening an idle mpv window.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6cb01715b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return fmt.Errorf("anipub stream media playlist fetch failed: %w", err) | ||
| } | ||
|
|
||
| segments := parsePlaylistSegments(mediaBody) |
There was a problem hiding this comment.
Reject non-HLS media playlists
When a master playlist points to a variant that returns a 200 HTML/challenge page, this code never verifies that mediaBody is an HLS playlist before calling parsePlaylistSegments. The HTML line is treated as a segment; fetchRange then receives an invalid URL and deliberately tolerates the probe failure, so validateResolvedStream returns nil and mpv still opens the bad stream instead of falling back. Please validate the fetched media playlist before segment parsing.
Useful? React with 👍 / 👎.
| if isDecoySegmentURI(segment) { | ||
| continue | ||
| } | ||
| if data := v.fetchRange(segment, 0, 15); looksLikeDecoySegment(data) { |
There was a problem hiding this comment.
Resolve relative segment URLs before probing
For media playlists whose segment lines are relative, such as seg/1.ts or /seg/1.ts, this call passes the raw relative URI into http.NewRequest inside fetchRange. That parse error is swallowed as a tolerated probe failure, so a relative segment that redirects to the PNG/HTML decoy is never detected and the AniPub provider is accepted instead of falling back. Resolve the segment against mediaURL before checking/probing it.
Useful? React with 👍 / 👎.
Fixes #113
Problem
anipub/megaplay streams occasionally resolve to ad-injected "decoy" HLS playlists on megap.kotocdn.site. The media playlist's segments point at
p16-ad-sg.ibyteimg.com(ByteDance ad CDN) and are 1x1 PNGs. mpv can't decode them, so it stays on the idle "Drop files or URLs to play here." screen and playback never starts.Confirmed live: A Silent Voice resolved to a playlist where 1770/1770 segments were decoy; Solo Leveling had 12 real / 306 decoy. The decoy playlists are Cloudflare-cached, so this isn't transient.
Previously the stream URL resolved without error, so the provider fallback never engaged.
Fix
Add
validateResolvedStreamin the anipub provider (internal/providers/anipub/validate.go), called fromgetEpisodeStreamsForMode:The validation error propagates through
ResolveEpisodeURLForPlayback, so the provider stack falls back to anineko/allanime/etc. instead of opening an idle mpv window.Testing
go build ./...,go vet ./...,go test ./internal/...all green.CURD_LIVE_ANIPUB=1) confirmed the real A Silent Voice decoy playlist is rejected (~0.5s).