vdatanet 1664 Posted 1 hour ago Posted 1 hour ago Emby Server 4.9.5.0 (Linux, .NET 8). The claim: the HLS segment list is computed from the container's declared duration and is never checked against the media. For any file whose declared duration runs past its last frame, the list therefore always contains one trailing segment that cannot be produced. It reproduces in one request No playback, no transcoding session to watch, no waiting for the end of a file — just fetch the variant playlist and count: curl -s "<server>/emby/videos/<id>/main.m3u8?<params>" | grep -c '#EXTINF' curl -s "<server>/emby/videos/<id>/main.m3u8?<params>" \ | grep -o '#EXTINF:[0-9.]*' | cut -d: -f2 | awk '{s+=$1} END {print s}' For a 22-minute MKV here (RunTimeTicks 13263360000 = 1326.336 s), 6-second segments: Segments in the list 222 (0–221) Distinct #EXTINF values one — 6.0000, all 222 times Sum of declared durations 1332.000 s Declared container duration 1326.336 s End of the written media 1325.365 s That last figure is the server's own, from SegmentComplete=video:0 Index=220 Start=0.000000 End=1325.365000. So the playlist advertises 6.635 s of video that does not exist, and the trailing segment is declared 6.0000 rather than the 0.336 s it would nominally cover. #EXT-X-TARGETDURATION is 7 while every segment says 6. What follows from it When a client asks for that trailing segment, ffmpeg is started with -ss 00:22:06.000, which is past the last frame. What happens next depends on the path: Copy / remux (-c:v copy -c:a copy ffmpeg exits 0 having written nothing, and the request is answered 500. Clients retry indefinitely; each retry starts a new ffmpeg process. Transcode (hevc_vaapi the encoder gets no frames and segfaults — Process exited with code 139 - Failed. The request is never answered at all; the connection is held open until the client disconnects. Either way the stream never terminates, so no client on the HLS path ever reaches end-of-stream. Direct play is unaffected, because it never reads the segment list. Why this is posted here This is not a configuration issue and it does not depend on the client. The symptom side — sessions stuck on the dashboard, next episode not starting — is already reported at 145772, with the playback-side measurements. This post is only about the arithmetic that builds the list. Deriving the segment count and the final #EXTINF from the actual end of the media rather than from RunTimeTicks would remove the phantom segment, and would also make the last segment's declared duration honest. Happy to provide the full playlist, the server log or the sample file.
vdatanet 1664 Posted 52 minutes ago Author Posted 52 minutes ago One last thing, and I say it with a smile. This is the bug that is pushing me to demux Matroska on the Apple TV myself. The app already carries a Matroska demuxer and an fMP4 muxer — I wrote them to keep HDR intact end to end — and the arithmetic above is what is now making me point them at everything else, HDR or not, so that the player never has to ask for a segment list at all. A playlist I never request cannot promise me a segment that was never written. For a TV app this one really is fatal: an episode that never reaches its end is an episode that never starts the next one, and a session left open on your dashboard. So I route around it — but writing container plumbing is not what a client should be spending its time on. It's a lot of code to own, a lot of new surface for bugs that are entirely mine, and every hour of it is an hour not spent on the app itself. I would delete all of it, gladly and in a single commit, the day the server hands me a stream I can play straight through. That's all this report is really asking for. Happy to test anything you want tested.
Luke 42963 Posted 35 minutes ago Posted 35 minutes ago This could be made more accurate by scanning the file for keyframe information during import. The problem is that this can take a long time, so that’s why this is a prediction.
vdatanet 1664 Posted 15 minutes ago Author Posted 15 minutes ago Thanks — I went to test that, and the result surprised me. If the list were approximating keyframe positions, changing the keyframe-break request ought to change it. It doesn't. Same file, same parameters, only BreakOnNonKeyFrames varying: BreakOnNonKeyFrames=True 222 segments, all #EXTINF:6.0000, sum 1332.000 (parameter absent) 222 segments, all #EXTINF:6.0000, sum 1332.000 BreakOnNonKeyFrames=False 222 segments, all #EXTINF:6.0000, sum 1332.000 The three playlists are byte-identical once the PlaySessionId is stripped. And the count is exactly ceil(declared duration / segment length), at both lengths I can get the server to produce: ceil(1326.336 / 6) = 222 -> 1332.000 s advertised ceil(1326.336 / 3) = 443 -> 1329.000 s advertised So the list isn't an imprecise estimate of where keyframes fall — it doesn't consult them at all, and every entry carries the nominal segment length rather than a measured one. That's why I don't think an import-time scan is what's missing here: making the last entry honest doesn't need keyframe positions, only the end of the media. And the gap isn't boundary rounding, it's 6.6 s — a whole segment. And the failure isn't confined to the predicted segment When the player doesn't get 221, it steps back to 220. That one is not predicted: it is real, it is inside the media, and it had already been served 200 earlier in the same session. It gets 500 nine times as well. One of those requests, end to end — 93 ms: 14:53:00.573 GET .../hls1/main/220.ts 14:53:00.614 ProcessRun 'StreamTranscode c2b692' Execute: ... -ss 00:22:00.000 ... -segment_start_number 220 14:53:00.628 SegmentComplete=video:0 Index=220 ... Frames=136 filename=04C768_220.ts 14:53:00.628 video:2332kB audio:148kB subtitle:0kB other streams:0kB 14:53:00.628 EXIT 14:53:00.634 ProcessRun 'StreamTranscode c2b692' Process exited with code 0 14:53:00.666 Error processing request 14:53:00.666 Response 500 ffmpeg produced the segment — 136 frames, 6.72 s, 2.4 MB — and exited 0. The request was answered 500 anyway. So there is a second failure that a better prediction would not fix, and it is the one that makes this unrecoverable: the client cannot get out of it even by stepping back to a segment that exists. Possibly related, from that same line: SegmentComplete reports Index=220 with Start=0.000000 End=1325.365000 Duration=1325.365000 — the length of the whole episode, for a segment holding 6.72 s. The command line carries -segment_time_delta -00:22:00.000 together with -copyts -start_at_zero. If anything downstream checks the produced segment against an expected time, that bookkeeping wouldn't match. I don't know the code, so this is only a guess. The transcoding path is a third thing again: there hevc_vaapi exits 139 (SIGSEGV) five times in forty seconds, and the request is never answered at all. None of this needs the prediction to become exact. Even leaving it as it is, overshooting by one segment could end the stream rather than start an unbounded retry loop — which is what turns a third of a second of missing video into a session that never finishes.
Luke 42963 Posted 1 minute ago Posted 1 minute ago Quote When the player doesn't get 221, it steps back to 220. That one is not predicted: it is real, it is inside the media, and it had already been served 200 earlier in the same session. It gets 500 nine times as well. Hi there, please attach the Emby server log from when the problem occurred: How to Report a Problem Thanks!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now