Wiedergabe: ohne Basisprofil lehnt der Transcoder alles ab
Der Unterschied zwischen 400 und 200 war ein einziger Parameter:
…&protocol=hls&X-Plex-Token=… → 400
…&protocol=hls&X-Plex-Client-Profile-Name=Chrome&… → 200
Flixy hat immer nur `X-Plex-Client-Profile-Extra` geschickt. Das
**erweitert** ein Profil, es ersetzt keins — ohne Basis gibt es nichts zu
erweitern, und der Server kann keine Entscheidung bilden. Seine Antwort
darauf ist eine nackte 400 ohne jeden Hinweis.
Das betrifft alles, was durch den Transcoder geht: die Qualitätswahl im
Player, komprimierte Downloads und Live-TV. Bei Filmen fiel es nicht auf,
weil dort DirectPlay greift.
„Chrome" als Basis, weil dieses Profil auf jedem Server vorhanden ist und
genau das kann, was AVPlayer kann: HLS mit H.264 und AAC. Die Feinheiten
für iOS stehen weiterhin im Zusatz.
Gefunden wurde es, indem die Anfragen Angabe für Angabe aufgebaut wurden,
bis eine davon umschlug — nicht durch Nachdenken.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f87cddbd21
commit
d28df346f2
@@ -1635,3 +1635,43 @@ extension PlexServer {
|
||||
return await probeStream(url: url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension PlexServer {
|
||||
/// Schickt eine beliebige Anfrage und zeigt Status und Antwort.
|
||||
///
|
||||
/// Zum Prüfen einzelner Vermutungen. `headers:` entscheidet, ob die
|
||||
/// Anfrage so aussieht wie die der App oder wie die des Systemplayers —
|
||||
/// der schickt keine Kopfzeilen mit, und dieser Unterschied war schon
|
||||
/// einmal die Ursache.
|
||||
public func attempt(target: String, headers: Bool = true) async -> String {
|
||||
guard let baseURL = connection.url else { return "keine Verbindung" }
|
||||
|
||||
let pieces = target.split(separator: "?", maxSplits: 1)
|
||||
guard var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
|
||||
else { return "Adresse nicht baubar" }
|
||||
components.percentEncodedPath = String(pieces[0])
|
||||
if pieces.count > 1 {
|
||||
components.percentEncodedQuery = String(pieces[1])
|
||||
.replacingOccurrences(of: "{token}", with: token)
|
||||
}
|
||||
guard let url = components.url else { return "Adresse nicht baubar" }
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.timeoutInterval = 25
|
||||
if headers {
|
||||
for (field, value) in identity.headers { request.setValue(value, forHTTPHeaderField: field) }
|
||||
request.setValue(token, forHTTPHeaderField: "X-Plex-Token")
|
||||
}
|
||||
|
||||
do {
|
||||
let (data, response) = try await transport.data(for: request)
|
||||
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
|
||||
let body = String(decoding: data.prefix(500), as: UTF8.self)
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return "HTTP \(status)\n\(redacted(body))"
|
||||
} catch {
|
||||
return Self.shortDescription(of: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user