Wiedergabe: die Plex-Kennung muss in die Adresse, nicht nur in die Kopfzeilen
HTTP 400 vom Transcoder. Die Kennung dieses Geräts reist bei jeder Anfrage als Kopfzeile mit — aber die Adresse des Stroms ruft nicht die App ab, sondern AVPlayer, und der schickt keine Kopfzeilen mit. Bei Dateien fällt das nicht auf; bei Live-TV schon: der Server legt die Sitzung unter der Gerätekennung an und kann die Abholung ohne sie keiner Sitzung zuordnen. Also trägt die Transcoder-Adresse die Kennung jetzt selbst. Das gilt für alle Ströme, nicht nur für Live — dort fiel es nur zuerst auf. Dazu: umgerechnet wird die Adresse der Sitzung, nicht die des Teils darin. Der Transcoder sucht sich den Teil selbst, deshalb steht dort -1. Und der Entscheider unterscheidet jetzt zwischen „nein" und „keine Antwort". Ein Schweigen als Ablehnung zu lesen hieße, eine funktionierende Sendung zu blocken, bloß weil er Live-Adressen womöglich gar nicht kennt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
861ca805a5
commit
8dba05b4f9
@@ -397,11 +397,14 @@ extension PlexServer {
|
||||
continue
|
||||
}
|
||||
|
||||
// Die Sitzung hat jetzt einen Tuner. Die Adresse, unter der
|
||||
// sie läuft, ist der Weg zum Transcoder — nicht die des
|
||||
// Senders und nicht die der Sendung.
|
||||
let streamPath = item.media.first?.parts.first?.key
|
||||
?? (item.key.isEmpty ? "/livetv/sessions/\(session)" : item.key)
|
||||
// Die Sitzung hat jetzt einen Tuner. Umgerechnet wird die
|
||||
// Adresse der **Sitzung** — nicht die des Senders, nicht die
|
||||
// der Sendung und nicht die des Teils darin. Der Transcoder
|
||||
// sucht sich den Teil selbst; deshalb steht unten auch -1.
|
||||
let sessionPath = "/livetv/sessions/\(session)"
|
||||
let streamPath = item.key.hasPrefix("/livetv/sessions/")
|
||||
? item.key
|
||||
: (item.media.first?.parts.first?.key ?? sessionPath)
|
||||
|
||||
trace.append(ChannelProbe(path: path, result: "Sitzung: \(streamPath)"))
|
||||
|
||||
@@ -467,19 +470,28 @@ extension PlexServer {
|
||||
}
|
||||
|
||||
/// Fragt den Server, ob er diesen Strom zulässt — und warum nicht.
|
||||
public func liveTVVerdict(for url: URL) async -> String? {
|
||||
public func liveTVVerdict(for url: URL) async -> LiveTVVerdict {
|
||||
// Dieselben Angaben, nur an den Entscheider statt an den Transcoder.
|
||||
// Er antwortet im Klartext, warum er ablehnt — sonst bleibt nur „die
|
||||
// Wiedergabe wurde unterbrochen", und das sagt nichts.
|
||||
guard let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
|
||||
else { return nil }
|
||||
else { return .unknown("keine Abfrageteile in der Adresse") }
|
||||
|
||||
guard let decision = try? await client.send(
|
||||
PlexRequest(path: "/video/:/transcode/universal/decision", query: items),
|
||||
as: TranscodeDecision.self
|
||||
) else { return nil }
|
||||
|
||||
return decision.isAllowed ? nil : decision.explanation
|
||||
do {
|
||||
let decision = try await client.send(
|
||||
PlexRequest(path: "/video/:/transcode/universal/decision", query: items),
|
||||
as: TranscodeDecision.self
|
||||
)
|
||||
guard decision.isAllowed else {
|
||||
return .refused(decision.explanation ?? "ohne Begründung")
|
||||
}
|
||||
return .allowed
|
||||
} catch {
|
||||
// Antwortet der Entscheider gar nicht, heißt das **nicht** nein.
|
||||
// Live-Adressen kennt er womöglich nicht; darauf die Wiedergabe
|
||||
// zu verweigern hieße, eine funktionierende Sendung zu blocken.
|
||||
return .unknown(Self.shortDescription(of: error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,3 +736,12 @@ public struct LiveTuneResult: Sendable {
|
||||
/// Jeder versuchte Weg mit seiner Antwort.
|
||||
public let trace: [ChannelProbe]
|
||||
}
|
||||
|
||||
/// Was der Server zu einem Strom sagt.
|
||||
public enum LiveTVVerdict: Sendable, Equatable {
|
||||
case allowed
|
||||
/// Ausdrücklich abgelehnt, mit Begründung.
|
||||
case refused(String)
|
||||
/// Der Entscheider hat nicht geantwortet — kein Grund, es nicht zu versuchen.
|
||||
case unknown(String)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user