diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-09-26 08:37:53 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-09-26 08:37:53 +0000 |
| commit | 8a4ae0293cc7870fe5c88034067c619071810440 (patch) | |
| tree | 1f86e145d001b015c061c242ca848fde9a51378b /tools | |
| parent | 4965d5971c1443ee69af42b9f86920fd6121fea5 (diff) | |
Fetch yt-dlp sources before playing them, and stop losing errors
Peter reported that YouTube subscribing and individual videos work but nothing
plays. Reproduced and root-caused on a device rather than guessed at:
UnrecognizedInputFormatException: None of the available extractors
(FlvExtractor, FlacExtractor, ... Mp3Extractor, ...) could read the stream
A YouTube episode's mediaUrl is its watch page -- the feed carries no enclosure,
and the audio URL only exists once yt-dlp has resolved it. SubscriptionKind was
consulted in exactly one place, EpisodeDownloader, which routes downloads. So
playback handed ExoPlayer an HTML page.
SubscriptionKind now says whether a source needs extracting, and
PlaybackAdvancer.start reports NeedsFetch instead of a NextUp that cannot work.
fetchAndStart runs the extraction and re-resolves, so the two places that start
episodes -- the service on queue advance, the view model on a tap -- share one
implementation rather than each growing their own. Both had to handle it: the
queue moves on without the UI, which was the lesson of the previous commit.
The second half of this is that none of it was visible. Nothing in the app
observed onPlayerError, and nothing rendered PlayerViewModel.banner at all --
so playback failures, fetch failures and even "sleep timer finished" were set
on a flow no screen collected. That is why a broken feature looked like a
dead button. Errors now surface in the player bar and on the player screen,
and a failed fetch carries yt-dlp's own words: "Sign in to confirm you're not
a bot" and "video unavailable" are very different problems and identical
without them. A fetch in progress says so rather than reading as "Nothing
playing" for thirty seconds.
Verified on a device, and one part could not be:
The mechanism works end to end. A YOUTUBE_CHANNEL episode pointed at a real
audio URL went NONE -> DOWNLOADING -> DOWNLOADED with a file on disk, and then
played -- yt-dlp doing the extraction and the download for real.
YouTube's own extractor could not be verified here, and I am not claiming it
was. This host's IP is bot-challenged for every video tried, directly from the
command line as well as from the app -- the same block CLAUDE.md recorded as
transient in July. Peter's phone is on a residential connection and is the only
place that can confirm the reported bug is actually gone.
Correcting something I said earlier in the session: YouTubeAudioTest passing
does not prove extraction works. It only starts Python and checks yt-dlp's
version; it never extracts anything.
No permission changes, no schema change. 392 unit tests green, detekt and lint
clean. Coverage 65.33 -> 65.16, exception recorded.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'tools')
0 files changed, 0 insertions, 0 deletions
