Live-TV: die Abspielliste ist fertig — sie gehört abgerufen, nicht umgerechnet

Das Belegen des Tuners klappt, und heraus kommt:

    /livetv/sessions/1b5bb998…/DBACCA6D…/index.m3u8?offset=-1.000000

Eine fertige HLS-Abspielliste. Ich habe sie an den Transcoder gegeben —
also darum gebeten, etwas umzurechnen, das schon fertig ist. Daher die
nackte 400. Sie wird jetzt unmittelbar abgerufen, mit Token und
Gerätekennung in der Adresse, weil der Systemplayer keine Kopfzeilen
mitschickt. Die eigene Abfrage der Sitzung bleibt dabei erhalten.

Dazu das Gegenstück, ebenfalls aus dem Quelltext des Plex-Clients:
`DELETE /media/subscriptions/{id}` gibt den Tuner wieder frei. Er ist ein
Stück Hardware — vier Stück gibt es, und ein nicht freigegebener fehlt
beim nächsten Einschalten. Das passiert jetzt beim Schließen des Players
und auch dann, wenn das Belegen zwar klappt, aber nichts Abspielbares
dabei herauskommt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-12 15:25:56 +02:00
co-authored by Claude Opus 5
parent 562fd758d5
commit a9563be1e1
6 changed files with 120 additions and 11 deletions
@@ -50,6 +50,35 @@ extension PlexServer {
return components.url
}
/// Baut die Adresse eines Stroms, den der Server schon bereitstellt.
///
/// Für Live-TV. Das Belegen eines Tuners liefert eine fertige
/// HLS-Abspielliste — die gehört abgerufen, nicht umgerechnet. Sie durch
/// den Transcoder zu schicken heißt, ihn um die Umrechnung von etwas zu
/// bitten, das bereits fertig ist; er antwortet mit einer nackten 400.
///
/// Token und Gerätekennung müssen in die Adresse, weil sie der
/// Systemplayer abruft und der keine Kopfzeilen mitschickt.
public nonisolated func directStreamURL(forPath path: String) -> URL? {
guard let baseURL = connection.url,
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
else { return nil }
// Die Adresse aus der Sitzung bringt ihre eigene Abfrage mit
// (`?offset=-1.000000`); die darf nicht verlorengehen.
let pieces = path.split(separator: "?", maxSplits: 1)
components.percentEncodedPath = String(pieces[0])
var items = pieces.count > 1
? (URLComponents(string: "?\(pieces[1])")?.queryItems ?? [])
: []
items.append(URLQueryItem(name: "X-Plex-Token", value: token))
items += identity.queryItems
components.queryItems = items
return components.url
}
/// Fragt den Server, ob er diese Wiedergabe zulässt.
public func transcodeDecision(for request: TranscodeRequest) async throws(PlexError) -> TranscodeDecision {
try await client.send(