fix(plex): playback sessions per viewer, bounded in total; a fair share of subtitle passes

HLS sessions were keyed by the item, so a second account opening the same
film killed the first one's session; the displaced player reclaimed at its
playhead and evicted the other in turn. The registry is now keyed by
(viewer, rating_key), segment requests resolve by both, and the session
directory carries the viewer (the orphan sweep still recognises the older
shapes).

Only transcodes counted toward a cap, so remuxes — each a whole segmented
copy of the film on the scratch volume — were bounded by the library size.
Three bounds now apply after every start, each dropping the least recently
used: two sessions per account, the transcode cap, and a new admin knob,
plex_max_sessions (default 8), over every session. A superseded session
request returns at once, since it waits on the killed ffmpeg, so an account
cannot park more request workers than it may hold sessions.

The subtitle extractor's full-pass slots were global and minutes long each;
one account opening subtitles on film after film could hold them all. An
account may now hold three of the six, and still gets windows past that.
This commit is contained in:
2026-09-19 07:16:17 +02:00
parent 6f9ba428d5
commit dc4e8b9fcd
13 changed files with 278 additions and 102 deletions
+5 -1
View File
@@ -193,7 +193,11 @@
},
"plex_max_transcodes": {
"label": "Max concurrent transcodes",
"hint": "Cap on simultaneous transcode sessions for non-H.264 files. Direct-play and remux (stream-copy) files aren't limited."
"hint": "Cap on simultaneous transcode sessions for non-H.264 files. Remux (stream-copy) sessions count only toward the overall session limit; direct-play files aren't limited."
},
"plex_max_sessions": {
"label": "Max concurrent playback sessions",
"hint": "Cap on all simultaneous playback sessions, remux (stream-copy) included — each one writes a full segmented copy of the film to the scratch volume. One account can hold at most two. Direct-play files aren't sessions and aren't limited."
},
"plex_transcode_hw": {
"label": "Hardware transcode",
+5 -1
View File
@@ -193,7 +193,11 @@
},
"plex_max_transcodes": {
"label": "Max párhuzamos transcode",
"hint": "A nem-H.264 fájlok egyidejű transcode-munkameneteinek felső korlátja. A direktben játszható és a remux (stream-copy) fájlokra nincs korlát."
"hint": "A nem-H.264 fájlok egyidejű transcode-munkameneteinek felső korlátja. A remux (stream-copy) munkamenetek csak az összesített munkamenet-korlátba számítanak bele; a direktben játszható fájlokra nincs korlát."
},
"plex_max_sessions": {
"label": "Max párhuzamos lejátszási munkamenet",
"hint": "Az összes egyidejű lejátszási munkamenet felső korlátja, a remuxot (stream-copy) is beleértve — mindegyik a film teljes, szegmentált másolatát írja a munkakötetre. Egy fiók legfeljebb kettőt tarthat. A direktben játszható fájlok nem munkamenetek, rájuk nincs korlát."
},
"plex_transcode_hw": {
"label": "Hardveres transcode",