Transcoder: es lag nie an Live-TV
Die Gegenprobe ist eindeutig:
Gegenprobe — Transcoder mit: Mogli: Legende des Dschungels
→ HTTP 400
Eine gewöhnliche Datei scheitert genauso. Damit ist die Suche der letzten
Tage an der falschen Stelle gelaufen: Transcoding hat in Flixy noch nie
funktioniert, es ist nur nie aufgefallen. Filme laufen über DirectPlay,
da wird der Transcoder gar nicht gefragt — Live-TV ist das Erste, was ihn
zwingend braucht.
Diese Annahme habe ich tagelang mitgeschleppt, ohne sie zu prüfen. Sie zu
prüfen hat zehn Zeilen gekostet.
Jetzt wird richtig halbiert, an einer Datei statt an einem Sender: von
„nur Pfad und Token" aufwärts, Angabe für Angabe, bis eine davon die 400
auslöst. Dazu derselbe Satz an den Entscheider, der in Plex' Format
antwortet statt mit HTML.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
458396c2b7
commit
8ab7baecb8
@@ -93,7 +93,10 @@ if let hubs = try? await server.homeHubs(),
|
|||||||
)
|
)
|
||||||
if let url = server.transcodeURL(for: request) {
|
if let url = server.transcodeURL(for: request) {
|
||||||
print("Gegenprobe — Transcoder mit: \(movie.title)")
|
print("Gegenprobe — Transcoder mit: \(movie.title)")
|
||||||
print(" → \(await server.probeStream(url: url))")
|
print(" volle Anfrage: \(await server.probeStream(url: url))")
|
||||||
|
for line in await server.transcoderBisect(ratingKey: movie.ratingKey) {
|
||||||
|
print(line)
|
||||||
|
}
|
||||||
print()
|
print()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1492,3 +1492,89 @@ extension CharacterSet {
|
|||||||
charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~*'()"
|
charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~*'()"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension PlexServer {
|
||||||
|
/// Klopft den Transcoder mit verschiedenen Angaben ab.
|
||||||
|
///
|
||||||
|
/// Eine gewöhnliche Datei scheitert genauso wie Live-TV: der Transcoder
|
||||||
|
/// antwortet auf alles mit einer nackten 400. Damit ist es kein
|
||||||
|
/// Live-Problem, sondern eines der Anfrage selbst — und welche Angabe
|
||||||
|
/// stört, sagt nur das Halbieren.
|
||||||
|
public func transcoderBisect(ratingKey: String) async -> [String] {
|
||||||
|
let session = UUID().uuidString
|
||||||
|
let path = "/library/metadata/\(ratingKey)"
|
||||||
|
let encoded = path.addingPercentEncoding(withAllowedCharacters: .plexParameterAllowed) ?? path
|
||||||
|
|
||||||
|
let variants: [(String, [URLQueryItem])] = [
|
||||||
|
("nur Pfad und Token", [
|
||||||
|
URLQueryItem(name: "path", value: encoded),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
]),
|
||||||
|
("Pfad unkodiert", [
|
||||||
|
URLQueryItem(name: "path", value: path),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
]),
|
||||||
|
("mit Protokoll und Indizes", [
|
||||||
|
URLQueryItem(name: "path", value: encoded),
|
||||||
|
URLQueryItem(name: "protocol", value: "hls"),
|
||||||
|
URLQueryItem(name: "mediaIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "partIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
]),
|
||||||
|
("dazu die Gerätekennung", [
|
||||||
|
URLQueryItem(name: "path", value: encoded),
|
||||||
|
URLQueryItem(name: "protocol", value: "hls"),
|
||||||
|
URLQueryItem(name: "mediaIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "partIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
URLQueryItem(name: "X-Plex-Client-Identifier", value: identity.clientIdentifier),
|
||||||
|
]),
|
||||||
|
("dazu hasMDE", [
|
||||||
|
URLQueryItem(name: "path", value: encoded),
|
||||||
|
URLQueryItem(name: "protocol", value: "hls"),
|
||||||
|
URLQueryItem(name: "hasMDE", value: "1"),
|
||||||
|
URLQueryItem(name: "mediaIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "partIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
URLQueryItem(name: "X-Plex-Client-Identifier", value: identity.clientIdentifier),
|
||||||
|
]),
|
||||||
|
("dazu die Sitzung", [
|
||||||
|
URLQueryItem(name: "path", value: encoded),
|
||||||
|
URLQueryItem(name: "protocol", value: "hls"),
|
||||||
|
URLQueryItem(name: "hasMDE", value: "1"),
|
||||||
|
URLQueryItem(name: "mediaIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "partIndex", value: "0"),
|
||||||
|
URLQueryItem(name: "session", value: session),
|
||||||
|
URLQueryItem(name: "X-Plex-Session-Identifier", value: session),
|
||||||
|
URLQueryItem(name: "X-Plex-Token", value: token),
|
||||||
|
URLQueryItem(name: "X-Plex-Client-Identifier", value: identity.clientIdentifier),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
var lines: [String] = []
|
||||||
|
for (name, items) in variants {
|
||||||
|
lines.append(" \(name): \(await probe(items: items, endpoint: "start.m3u8"))")
|
||||||
|
}
|
||||||
|
// Und derselbe Satz an den Entscheider: er antwortet in Plex' Format
|
||||||
|
// statt mit HTML, wenn er überhaupt antwortet.
|
||||||
|
lines.append(" Entscheider: \(await probe(items: variants.last!.1, endpoint: "decision"))")
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
private func probe(items: [URLQueryItem], endpoint: String) async -> String {
|
||||||
|
guard let baseURL = connection.url,
|
||||||
|
var components = URLComponents(
|
||||||
|
url: baseURL.appending(path: "/video/:/transcode/universal/\(endpoint)"),
|
||||||
|
resolvingAgainstBaseURL: false
|
||||||
|
)
|
||||||
|
else { return "Adresse nicht baubar" }
|
||||||
|
|
||||||
|
components.percentEncodedQuery = items
|
||||||
|
.map { "\($0.name)=\($0.value ?? "")" }
|
||||||
|
.joined(separator: "&")
|
||||||
|
guard let url = components.url else { return "Adresse nicht baubar" }
|
||||||
|
|
||||||
|
return await probeStream(url: url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user