Skip to content

Fix playlist stopping between tracks; add retry logic to getNextTrack#74

Open
ElFishi wants to merge 1 commit intophilippe44:masterfrom
ElFishi:feature/retry-getNextTrack
Open

Fix playlist stopping between tracks; add retry logic to getNextTrack#74
ElFishi wants to merge 1 commit intophilippe44:masterfrom
ElFishi:feature/retry-getNextTrack

Conversation

@ElFishi
Copy link
Contributor

@ElFishi ElFishi commented Mar 8, 2026

Fix playlist stopping between tracks; add retry logic to getNextTrack

This PR fixes a bug that caused playlist playback to stop between tracks instead of advancing automatically, and adds automatic retry logic to make the player resilient against the transient yt-dlp failures that triggered it.

Bug

When yt-dlp resolves a track's stream URL, YouTube occasionally returns only format 18 — a legacy muxed 360p mp4 — instead of the expected audio-only streams (opus/ogg/aac). Since format 18 is not present in the @audioId or @videoId lookup tables, _selectTracks returns an empty list, _getNextTrack finds no matching track and calls errorCb, causing LMS to stop playback entirely. Because the track is not removed from the playlist, pressing play manually succeeds — typically because yt-dlp returns proper audio streams on the second attempt.

A secondary bug existed in _selectTracks: in the audio loop, $track->{_id} = $item was executed after the push and unconditionally, meaning it ran even when no matching track was found (leaving $track undef), and any pushed track had _id unset at the point it was pushed.

Changes

getNextTrack now accepts an optional $_retries parameter, defaulting to 3. On any failure — yt-dlp parse error, no matching tracks, or stream initialisation failure from _getNextTrack — a $retryOrFail closure either schedules a fresh attempt via Slim::Utils::Timers::setTimer after a 2-second delay, or calls the real errorCb once all retries are exhausted. The 2-second delay avoids immediately hammering YouTube's CDN and gives the event loop room to breathe. The $retryOrFail closure is passed down as the error callback to _getNextTrack as well, so failures at the stream initialisation level are retried on the same terms.

In _selectTracks, both the audio and video loops are corrected to assign $track->{_id} before pushing, and only when a matching track was actually found.

@ElFishi ElFishi marked this pull request as draft March 8, 2026 19:49
@ElFishi ElFishi marked this pull request as ready for review March 9, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant