Describe the bug
Seeking (or resuming after a pause, which appears to use the same code path) on a track whose custom-convert.conf profile combines the R (remote URL) and T (seek-to-start-time) capabilities reliably fails, even though every intermediate step is provably correct.
The transcoded stream (ffmpeg fed a remote HLS URL, R-only, no T) plays perfectly from the start. Adding T and seeking mid-playback causes Slim::Player::Source::_readNextChunk to report end of file or error on socket roughly 1 second after the seek-triggered reopen - even though the exact command LMS constructs (confirmed via the Tokenized command: log line) decodes the entire rest of the file with zero errors when run directly, outside LMS.
With multiple players synced together, this repeats indefinitely (seek → ~1s of audio → reopen at ~the same position → repeat). With a single, unsynced player, it stops instead of looping - but the same "end of file or error on socket" / immediate-reopen pattern is the underlying cause in both cases.
I want to be upfront that I can't rule out something specific to my own profile/handler causing this, but every piece I could independently verify came back correct - see the sequence of log lines below - which is what made me suspect the bug is in LMS's own pipe-reading/seek-reopen logic for an R-capability stream rather than in my own code.
To Reproduce
- A custom protocol handler for a remote (
isRemote => 1, canDirectStream => 0) HLS stream, resolved to a .m3u8 URL and handed to ffmpeg via a custom-convert.conf profile declaring RT:{START=-ss %s} (mirroring the built-in flac/faad profiles' T:{START=--skip=%t} pattern), plus a getSeekData($client, $song, $newtime) implementation returning { timeOffset => $newtime }.
- Start playback of a track using that profile - it plays normally from the beginning.
- A few seconds/minutes in, seek to a new position (or pause, wait, then resume).
- Observe
server.log (with the built-in player.source category raised to INFO, to see the Tokenized command: line):
Slim::Player::Song::open correctly logs Adding seekdata { timeOffset => <N> } and seek=true time=<N> canSeek=2
- The
Tokenized command: line correctly includes -ss <N> at the right position
- Within ~1 second,
Slim::Player::Source::_readNextChunk logs end of file or error on socket, song pos: <bytes>
- Several
Slim::Player::StreamingController::_Invalid lines follow (event ... received while in invalid state ...)
- Confirm the same command run directly (outside LMS) works correctly for the full remaining duration:
ffmpeg -loglevel warning -nostdin -ss <N> -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 10 \
-i "<the exact resolved HLS URL from the Tokenized command line>" \
-vn -c:a flac -compression_level 0 -f flac -y out.flac
This decodes cleanly to completion with no errors in every case I tried.
I hit this in a small open-source plugin I wrote (source, including the exact custom-convert.conf profile and protocol handler: https://github.com/NikolajChristensen/lyrion-drlive - see the README's Troubleshooting section, "Seeking and pause/resume on TVA", for the full write-up of what I tried across several versions). The specific content is a Danish public broadcaster's on-demand HLS stream, which is geo-restricted to Denmark/EU, so I can't hand you a URL that works everywhere - but the failure pattern doesn't look content-specific, and I'd expect it to reproduce with any R+T profile seeking into a remote HLS VOD asset. Happy to help reproduce against a different, non-geo-restricted source if that's useful, or to pull further log detail from my own server.
Expected behavior
Seeking (and resuming after a pause) on a remotely-transcoded (R-capability) stream should restart the transcoder at the requested offset and continue playing normally, the same way it does for a locally-transcoded (non-R) T-capable profile.
Screenshots
N/A (audio-only issue, no visual component beyond the progress bar and playback state).
System Information (please complete the following information):
- OS on which you're running LMS: Debian/Ubuntu-based Linux
- Hardware: x86_64
- Web skin used: Default
- Browser: N/A (reproduced via a Squeezebox2-family hardware player)
- LMS Version: 9.1.1
- Player(s) involved: Squeezebox2-family hardware, both a single unsynced player and a 4-player sync group
- ffmpeg 5.1.9 (Debian package)
Additional context
Relevant server.log excerpt (player MAC redacted), plugin.drlive at DEBUG and the built-in player.source at INFO:
Slim::Player::StreamingController::jumpToTime
Slim::Player::Song::open (371) Adding seekdata { timeOffset => 259.52 }
Slim::Player::Song::open (395) seek=true time=259.52 canSeek=2
Slim::Player::TranscodingHelper::tokenizeConvertCommand2 (668) Using command for conversion: "/bin/ffmpeg" -loglevel error -nostdin -ss 259.52 -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 10 -i "https://<redacted HLS URL>" -vn -c:a flac -compression_level 0 -f flac - & |
Slim::Player::Song::open (586) Tokenized command: "/bin/ffmpeg" -loglevel error -nostdin -ss 259.52 -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 10 -i "https://<redacted HLS URL>" -vn -c:a flac -compression_level 0 -f flac - & |
...
Slim::Player::Source::_readNextChunk (379) end of file or error on socket, song pos: 2440298
Slim::Player::Source::_readNextChunk (384) <player>: mark end of stream
Slim::Player::StreamingController::_setStreamingState (2439) new streaming state STREAMOUT
...
Slim::Player::StreamingController::_Invalid (325) <player>: event ReadyToStream received while in invalid state WAITING_TO_SYNC-STREAMOUT
Slim::Player::StreamingController::_Invalid (325) <player>: event BufferReady received while in invalid state PLAYING-IDLE
I also came across DEVELOPERS.md's "Issue of 'Volatile' Redirection" section while investigating, which describes LMS closing the connection on pause and needing to re-resolve on resume - a related but distinct scenario (that one is about a redirected URL going stale; this one reproduces on a stable, unredirected URL that decodes perfectly when fetched again immediately after the failure). Mentioning it in case the two share a root cause in the same area of Slim::Player::Song/Slim::Player::Source.
Happy to provide the full plugin source, a longer log excerpt, or test further against my own server - just let me know what would help.
Describe the bug
Seeking (or resuming after a pause, which appears to use the same code path) on a track whose
custom-convert.confprofile combines theR(remote URL) andT(seek-to-start-time) capabilities reliably fails, even though every intermediate step is provably correct.The transcoded stream (ffmpeg fed a remote HLS URL,
R-only, noT) plays perfectly from the start. AddingTand seeking mid-playback causesSlim::Player::Source::_readNextChunkto reportend of file or error on socketroughly 1 second after the seek-triggered reopen - even though the exact command LMS constructs (confirmed via theTokenized command:log line) decodes the entire rest of the file with zero errors when run directly, outside LMS.With multiple players synced together, this repeats indefinitely (seek → ~1s of audio → reopen at ~the same position → repeat). With a single, unsynced player, it stops instead of looping - but the same "end of file or error on socket" / immediate-reopen pattern is the underlying cause in both cases.
I want to be upfront that I can't rule out something specific to my own profile/handler causing this, but every piece I could independently verify came back correct - see the sequence of log lines below - which is what made me suspect the bug is in LMS's own pipe-reading/seek-reopen logic for an
R-capability stream rather than in my own code.To Reproduce
isRemote => 1,canDirectStream => 0) HLS stream, resolved to a.m3u8URL and handed to ffmpeg via acustom-convert.confprofile declaringRT:{START=-ss %s}(mirroring the built-in flac/faad profiles'T:{START=--skip=%t}pattern), plus agetSeekData($client, $song, $newtime)implementation returning{ timeOffset => $newtime }.server.log(with the built-inplayer.sourcecategory raised to INFO, to see theTokenized command:line):Slim::Player::Song::opencorrectly logsAdding seekdata { timeOffset => <N> }andseek=true time=<N> canSeek=2Tokenized command:line correctly includes-ss <N>at the right positionSlim::Player::Source::_readNextChunklogsend of file or error on socket, song pos: <bytes>Slim::Player::StreamingController::_Invalidlines follow (event ... received while in invalid state ...)I hit this in a small open-source plugin I wrote (source, including the exact
custom-convert.confprofile and protocol handler: https://github.com/NikolajChristensen/lyrion-drlive - see the README's Troubleshooting section, "Seeking and pause/resume on TVA", for the full write-up of what I tried across several versions). The specific content is a Danish public broadcaster's on-demand HLS stream, which is geo-restricted to Denmark/EU, so I can't hand you a URL that works everywhere - but the failure pattern doesn't look content-specific, and I'd expect it to reproduce with anyR+Tprofile seeking into a remote HLS VOD asset. Happy to help reproduce against a different, non-geo-restricted source if that's useful, or to pull further log detail from my own server.Expected behavior
Seeking (and resuming after a pause) on a remotely-transcoded (
R-capability) stream should restart the transcoder at the requested offset and continue playing normally, the same way it does for a locally-transcoded (non-R)T-capable profile.Screenshots
N/A (audio-only issue, no visual component beyond the progress bar and playback state).
System Information (please complete the following information):
Additional context
Relevant
server.logexcerpt (player MAC redacted),plugin.drliveat DEBUG and the built-inplayer.sourceat INFO:I also came across
DEVELOPERS.md's "Issue of 'Volatile' Redirection" section while investigating, which describes LMS closing the connection on pause and needing to re-resolve on resume - a related but distinct scenario (that one is about a redirected URL going stale; this one reproduces on a stable, unredirected URL that decodes perfectly when fetched again immediately after the failure). Mentioning it in case the two share a root cause in the same area ofSlim::Player::Song/Slim::Player::Source.Happy to provide the full plugin source, a longer log excerpt, or test further against my own server - just let me know what would help.