Player: die Qualitätsleiter des Servers, Bitrate im Blick, Doppeltipp
Die vier erfundenen Stufen weichen der Leiter, die der Server selbst meldet: 64, 96, 208, 320, 720, 1500, 2000, 3000, 4000, 8000, 10000, 12000, 20000 kbps mit den Auflösungen, die Plex dafür vorsieht. Eine eigene Leiter hieße, Stufen anzubieten, die der Transcoder nicht kennt — er rundet dann still auf die nächste, und die Anzeige log. Angeboten wird nur, was zur Quelle passt. Eine 720p-Datei auf 1080p hochzurechnen bringt kein Bild dazu, und die Stufen sähen alle gleich aus. Oben im Blatt steht, was tatsächlich über die Leitung kommt — gemessene Bitrate, Auflösung, verworfene Bilder. Der Unterschied zur gewählten Stufe ist keine Haarspalterei: die eine sagt, was erlaubt ist, die andere, was ankommt. Ruckelt es trotz hoher Stufe, steht die Antwort dort. „Nur Ton" gibt es, aber ehrlich beschriftet: Plex kennt für Videos keinen reinen Tonstrom, also wird die unterste Sprosse geholt und das Bild ausgeblendet. Dazu Doppeltipp links und rechts für zehn Sekunden zurück und vor. Die Reihenfolge der Gesten ist entscheidend — das einfache Tippen verschluckt sonst das doppelte. Die Kachel hängt nicht mehr in vier Ecken fest, sondern klebt links oder rechts und ist in der Höhe frei. Vier Ecken sind schnell gebaut, aber im Weg: steht sie über einem Knopf, bleiben drei Orte, die ebenso stören. Größer wird sie durch Zusammen- und Auseinanderziehen; der Griff ist weg, er saß zwangsläufig auf dem Bild und stritt sich mit dem Verschieben. Und die Begriffe: „Motor" für engine sagt kein deutscher Entwickler. Fachwörter, die im Deutschen englisch bleiben, bleiben jetzt englisch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c2ddc10871
commit
12bb49615b
@@ -385,7 +385,7 @@ extension PlexServer {
|
||||
|
||||
/// Schaltet einen Sender ein.
|
||||
///
|
||||
/// Live-TV kommt immer als umgerechneter Strom: der Tuner liefert einen
|
||||
/// Live-TV kommt immer als umgerechneter Stream: der Tuner liefert einen
|
||||
/// Transportstrom, den kein iPhone direkt abspielt.
|
||||
///
|
||||
/// Zwei Schritte, und der erste ist der, den ich zuerst übersprungen
|
||||
@@ -675,7 +675,7 @@ extension PlexServer {
|
||||
return lines.joined(separator: "\n")
|
||||
}
|
||||
|
||||
/// Belegt einen Tuner über den Empfänger und liefert den Strom.
|
||||
/// Belegt einen Tuner über den Empfänger und liefert den Stream.
|
||||
///
|
||||
/// Die Antwort auf das POST trägt den Vorgang mitsamt Metadaten-Eintrag,
|
||||
/// und **dort** steht die abspielbare Teil-Adresse — nicht im Raster und
|
||||
@@ -746,7 +746,7 @@ extension PlexServer {
|
||||
|
||||
// Abwarten, bis der Empfänger abgestimmt hat. Er meldet
|
||||
// `status: inprogress` und `currentSize: 0` — es gibt in dem Moment
|
||||
// noch keinen Strom, und jede Frage danach musste scheitern. Ein
|
||||
// noch keinen Stream, und jede Frage danach musste scheitern. Ein
|
||||
// Tuner ist ein Stück Hardware; er braucht Sekunden, keine
|
||||
// Millisekunden.
|
||||
if let operation = Self.grabOperationKey(in: data) {
|
||||
@@ -861,7 +861,7 @@ extension PlexServer {
|
||||
///
|
||||
/// Höchstens zwölf Sekunden. Länger zu warten hieße, den Nutzer vor einem
|
||||
/// schwarzen Bild sitzen zu lassen; gar nicht zu warten hieß bisher, nach
|
||||
/// einem Strom zu fragen, den es noch nicht gibt.
|
||||
/// einem Stream zu fragen, den es noch nicht gibt.
|
||||
private func waitForGrab(atKey key: String, limit: Int = 12) async -> String {
|
||||
for second in 1...limit {
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
@@ -1180,7 +1180,7 @@ extension PlexServer {
|
||||
return keys.filter { !$0.isEmpty && seen.insert($0).inserted }
|
||||
}
|
||||
|
||||
/// Fragt den Server, ob er diesen Strom zulässt — und warum nicht.
|
||||
/// Fragt den Server, ob er diesen Stream zulässt — und warum nicht.
|
||||
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
|
||||
@@ -1450,7 +1450,7 @@ public struct LiveTuneResult: Sendable {
|
||||
public let trace: [ChannelProbe]
|
||||
}
|
||||
|
||||
/// Was der Server zu einem Strom sagt.
|
||||
/// Was der Server zu einem Stream sagt.
|
||||
public enum LiveTVVerdict: Sendable, Equatable {
|
||||
case allowed
|
||||
/// Ausdrücklich abgelehnt, mit Begründung.
|
||||
|
||||
@@ -3,7 +3,7 @@ import Foundation
|
||||
extension PlexServer {
|
||||
// MARK: - Transcoding
|
||||
|
||||
/// Die Adresse des HLS-Stroms für diese Wiedergabe.
|
||||
/// Die Adresse des HLS-Streams für diese Wiedergabe.
|
||||
///
|
||||
/// HLS ist genau die Kost, für die AVPlayer gebaut ist: er wechselt die
|
||||
/// Bitrate während der Wiedergabe von selbst, je nachdem was die Leitung
|
||||
@@ -74,7 +74,7 @@ extension PlexServer {
|
||||
return components.url
|
||||
}
|
||||
|
||||
/// Baut die Adresse eines Stroms, den der Server schon bereitstellt.
|
||||
/// Baut die Adresse eines Streams, den der Server schon bereitstellt.
|
||||
///
|
||||
/// Für Live-TV. Token und Gerätekennung müssen in die Adresse, weil sie
|
||||
/// der Systemplayer abruft und der keine Kopfzeilen mitschickt.
|
||||
@@ -128,7 +128,7 @@ extension PlexServer {
|
||||
///
|
||||
/// Der Server richtet seine Entscheidung danach aus. Die Angaben stammen
|
||||
/// aus `DeviceCapabilities` — wären sie großzügiger als das, was iOS
|
||||
/// wirklich kann, schickte Plex einen Strom, der hier stumm bliebe oder
|
||||
/// wirklich kann, schickte Plex einen Stream, der hier stumm bliebe oder
|
||||
/// schwarz.
|
||||
private nonisolated var clientProfileItems: [URLQueryItem] {
|
||||
[
|
||||
@@ -282,7 +282,7 @@ extension PlexServer {
|
||||
/// Die Adresse für einen heruntergerechneten Download.
|
||||
///
|
||||
/// **Noch nicht an einem echten Server geprüft.** Der Weg nutzt den
|
||||
/// Universal-Transcoder mit `protocol=http`, der einen fortlaufenden Strom
|
||||
/// Universal-Transcoder mit `protocol=http`, der einen fortlaufenden Stream
|
||||
/// statt HLS liefert — anders als der offizielle Sync-Weg von Plex, der
|
||||
/// umständlich und schlecht dokumentiert ist.
|
||||
///
|
||||
@@ -290,7 +290,7 @@ extension PlexServer {
|
||||
/// bevor die Einstellung angeboten wird:
|
||||
/// 1. Ob Plex eine `Content-Length` mitschickt. Ohne sie gibt es keinen
|
||||
/// Fortschrittsbalken und kein Fortsetzen nach dem Pausieren.
|
||||
/// 2. Ob die entstehende Datei durchsuchbar ist. Ein Strom, der von vorn
|
||||
/// 2. Ob die entstehende Datei durchsuchbar ist. Ein Stream, der von vorn
|
||||
/// gedacht ist, muss es nicht sein — dann ließe sich im Download nicht
|
||||
/// springen.
|
||||
///
|
||||
@@ -321,7 +321,7 @@ extension PlexServer {
|
||||
|
||||
components.queryItems = request.queryItems
|
||||
// Überschreibt `protocol=hls` aus der Anfrage: für eine Datei
|
||||
// brauchen wir einen fortlaufenden Strom, keine Segmentliste.
|
||||
// brauchen wir einen fortlaufenden Stream, keine Segmentliste.
|
||||
.filter { $0.name != "protocol" && $0.name != "fastSeek" && $0.name != "copyts" }
|
||||
+ [
|
||||
URLQueryItem(name: "protocol", value: "http"),
|
||||
|
||||
@@ -84,7 +84,7 @@ public struct TranscodeRequest: Sendable, Equatable {
|
||||
// Ohne fastSeek muss der Transcoder beim Springen von vorn
|
||||
// beginnen — bei einem Zweistünder dauert das ewig.
|
||||
URLQueryItem(name: "fastSeek", value: "1"),
|
||||
// 0 heißt: wir fragen hier ausdrücklich nach einem Strom. Ob
|
||||
// 0 heißt: wir fragen hier ausdrücklich nach einem Stream. Ob
|
||||
// DirectPlay möglich wäre, hat der PlaybackDecider schon geprüft.
|
||||
URLQueryItem(name: "directPlay", value: "0"),
|
||||
// 1 erlaubt das bloße Umpacken, wenn der Bildcodec passt. Das
|
||||
|
||||
@@ -291,7 +291,7 @@ struct PlexGridMedia: Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Der Strom hinter einer Rastersendung.
|
||||
/// Der Stream hinter einer Rastersendung.
|
||||
struct PlexGridPart: Decodable {
|
||||
let key: String?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user