diff --git a/Flixy/Views/Player/PlayerModel.swift b/Flixy/Views/Player/PlayerModel.swift index 0187a23..0fb0d94 100644 --- a/Flixy/Views/Player/PlayerModel.swift +++ b/Flixy/Views/Player/PlayerModel.swift @@ -847,7 +847,7 @@ final class PlayerModel { /// Führt Buch über das Stocken — die **zweite** Uhr. /// - /// Der Wachhund darunter ist ein Totmann: vierzig Sekunden am Stück ohne + /// Der Watchdog darunter ist ein Totmann: vierzig Sekunden am Stück ohne /// Daten, dann Schluss. Er setzt sich bei jedem kurzen Erholen zurück, /// und genau das ist sein blinder Fleck: zehn Rückler à dreißig Sekunden /// lösen ihn nie aus, obwohl die halbe Stunde unbrauchbar war. diff --git a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/DowngradeRule.swift b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/DowngradeRule.swift index d65ff69..4112e1a 100644 --- a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/DowngradeRule.swift +++ b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/DowngradeRule.swift @@ -5,7 +5,7 @@ import Foundation /// Der billige Hebel ist `preferredPeakBitRate`: er wirkt ohne Neuaufbau. /// Wenn er nichts ausrichtet — weil die Playlist nur eine Stufe hat oder weil /// schon die unterste läuft —, bleibt nur der Neuaufbau mit kleinerer Bitrate: -/// Transcoder anhalten, Motor abreißen, neu aushandeln, zurückspringen. Das +/// Transcoder anhalten, Engine abreißen, neu aushandeln, zurückspringen. Das /// sind Sekunden mit schwarzem Bild. /// /// **Ein Notnagel, keine Regelschleife.** Zu oft ausgelöst erzeugt er genau diff --git a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/PlaybackDecision.swift b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/PlaybackDecision.swift index 568b389..e9977aa 100644 --- a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/PlaybackDecision.swift +++ b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/PlaybackDecision.swift @@ -48,7 +48,7 @@ public struct PlaybackDecision: Sendable, Equatable { switch method { case .directPlay(let engine): engine // Der Transcoder liefert HLS, und damit ist AVPlayer der richtige - // Motor. **Nicht** aber, wie hier früher stand, „inklusive + // Engine. **Nicht** aber, wie hier früher stand, „inklusive // automatischem Bitratenwechsel": den gibt es nur, wenn die Playlist // mehrere Stufen führt, und das muss ausdrücklich bestellt werden. case .transcode: .avPlayer diff --git a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/StallLedger.swift b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/StallLedger.swift index 9fab3d7..37deacb 100644 --- a/Packages/FlixyKit/Sources/FlixyPlayback/Decision/StallLedger.swift +++ b/Packages/FlixyKit/Sources/FlixyPlayback/Decision/StallLedger.swift @@ -2,7 +2,7 @@ import Foundation /// Buch über das Stocken, mit gleitendem Fenster. /// -/// **Warum es das gibt.** Der Wachhund im Player kannte nur eine Frage: steht +/// **Warum es das gibt.** Der Watchdog im Player kannte nur eine Frage: steht /// es seit vierzig Sekunden am Stück? Bei jedem kurzen Erholen setzte er sich /// zurück — zehn Rückler à dreißig Sekunden lösten nichts aus, obwohl die /// halbe Stunde unbrauchbar war. Genau dieser Fall ist der, über den geklagt diff --git a/Packages/FlixyKit/Sources/FlixyPlayback/Engine/AVPlayerEngine.swift b/Packages/FlixyKit/Sources/FlixyPlayback/Engine/AVPlayerEngine.swift index 56d8905..747f8fc 100644 --- a/Packages/FlixyKit/Sources/FlixyPlayback/Engine/AVPlayerEngine.swift +++ b/Packages/FlixyKit/Sources/FlixyPlayback/Engine/AVPlayerEngine.swift @@ -90,7 +90,7 @@ public final class AVPlayerEngine: VideoPlayerEngine { teardownObservers() state = .loading - // Die Buchführung gehört zur Quelle, nicht zum Motor: ein neuer Titel + // Die Buchführung gehört zur Quelle, nicht zur Engine: ein neuer Titel // fängt bei null an, sonst schleppte die Zahl den vorigen Film mit. variantBitrates = [] wantsToPlay = false diff --git a/Packages/FlixyKit/Sources/FlixyPlayback/Engine/VideoPlayerEngine.swift b/Packages/FlixyKit/Sources/FlixyPlayback/Engine/VideoPlayerEngine.swift index 7382813..d8d1fdd 100644 --- a/Packages/FlixyKit/Sources/FlixyPlayback/Engine/VideoPlayerEngine.swift +++ b/Packages/FlixyKit/Sources/FlixyPlayback/Engine/VideoPlayerEngine.swift @@ -21,7 +21,7 @@ public struct PlaybackSource: Sendable, Equatable { /// wackelige Leitung ist es zu wenig: der Systemwert ist auf schnellen /// Start ausgelegt, nicht darauf, einen Aussetzer zu überstehen. /// - /// **Wer das entscheidet, muss mehr wissen als der Motor.** Ob es ein + /// **Wer das entscheidet, muss mehr wissen als die Engine.** Ob es ein /// Sender ist, ob die Datei lokal liegt — das weiß der Player, nicht die /// Engine. Deshalb reist die Zahl mit der Quelle, statt dass die Engine /// rät. diff --git a/Packages/FlixyKit/Sources/FlixyProbe/main.swift b/Packages/FlixyKit/Sources/FlixyProbe/main.swift index 244bd7a..c0be70e 100644 --- a/Packages/FlixyKit/Sources/FlixyProbe/main.swift +++ b/Packages/FlixyKit/Sources/FlixyProbe/main.swift @@ -150,6 +150,42 @@ let firstMovie = await { () async -> PlexItem? in return try? await server.items(inLibrary: movieLibrary, limit: 1).items.first }() +// MARK: - Die Leiter bei Plex + +// Dieselbe Frage wie bei Jellyfin, und aus demselben Grund gestellt: bei Plex +// steht `autoAdjustQuality=1` im Code, und ob sein Transcoder daraufhin +// mehrere Stufen liefert, war nie geprüft. Eine ungeprüfte Annahme über +// Serververhalten hat uns bei Jellyfin vier Runden gekostet. +if CommandLine.arguments.contains("--leiter") { + guard let movie = firstMovie else { + print("Keine Datei zum Prüfen gefunden.") + exit(0) + } + print("Leiter-Probe mit: \(movie.title)\n") + + let ohne = TranscodeRequest( + ratingKey: movie.ratingKey, + maximumBitrate: 8_000, + isLocal: connection.local + ) + let mit = ohne.askingForLadder() + + for (name, anfrage) in [("ohne autoAdjustQuality", ohne), ("mit autoAdjustQuality=1", mit)] { + print("=== \(name) ===") + guard let url = server.transcodeURL(for: anfrage) else { + print(" Keine Adresse zu bauen.\n") + continue + } + print(await prüfePlaylist(url)) + print() + } + + // Aufräumen: beide Anfragen haben am Server einen Transcoder angeworfen. + await server.stopTranscode(sessionIdentifier: ohne.sessionIdentifier) + print("Transcoder angehalten.") + exit(0) +} + if let movie = firstMovie { let request = TranscodeRequest( ratingKey: movie.ratingKey, diff --git a/Packages/FlixyKit/Sources/PlexKit/Endpoints/TranscodeRequest.swift b/Packages/FlixyKit/Sources/PlexKit/Endpoints/TranscodeRequest.swift index c6bbb3f..61588c6 100644 --- a/Packages/FlixyKit/Sources/PlexKit/Endpoints/TranscodeRequest.swift +++ b/Packages/FlixyKit/Sources/PlexKit/Endpoints/TranscodeRequest.swift @@ -65,7 +65,7 @@ public struct TranscodeRequest: Sendable, Equatable { /// Dieselbe Sitzungskennung: es ist **eine** Wiedergabe, und der Server /// soll sie nicht für zwei halten — sonst bliebe beim Aufräumen ein /// Transcoder stehen. - func askingForLadder() -> TranscodeRequest { + public func askingForLadder() -> TranscodeRequest { TranscodeRequest( ratingKey: ratingKey, mediaIndex: mediaIndex, diff --git a/Packages/FlixyKit/Tests/FlixyPlaybackTests/StallLedgerTests.swift b/Packages/FlixyKit/Tests/FlixyPlaybackTests/StallLedgerTests.swift index b9c840d..7e80caa 100644 --- a/Packages/FlixyKit/Tests/FlixyPlaybackTests/StallLedgerTests.swift +++ b/Packages/FlixyKit/Tests/FlixyPlaybackTests/StallLedgerTests.swift @@ -6,7 +6,7 @@ import Foundation struct StallLedgerTests { /// Der Fall, wegen dem es den Typ gibt. /// - /// Zehn Rückler à dreißig Sekunden lösten beim alten Wachhund nichts aus, + /// Zehn Rückler à dreißig Sekunden lösten beim alten Watchdog nichts aus, /// weil er sich bei jedem Erholen zurücksetzte. Hier muss sichtbar /// werden, dass die Wiedergabe unbrauchbar ist. @Test("Viele kurze Rückler bleiben sichtbar") diff --git a/Packages/FlixyVLC/Sources/FlixyVLC/VLCPlayerEngine.swift b/Packages/FlixyVLC/Sources/FlixyVLC/VLCPlayerEngine.swift index ee3307f..ef6199b 100644 --- a/Packages/FlixyVLC/Sources/FlixyVLC/VLCPlayerEngine.swift +++ b/Packages/FlixyVLC/Sources/FlixyVLC/VLCPlayerEngine.swift @@ -227,7 +227,7 @@ extension VLCPlayerEngine: VLCMediaPlayerDelegate { /// Aufzählung führt nur `opening`, `playing`, `paused`, `stopped` und /// `error`. Weil diese Methode bisher fehlte, ging der Zustand /// `.buffering` auf dem VLC-Weg **nie** an — und damit löste der - /// Wachhund im Player dort nie aus. Ein hängender Strom lief stumm ins + /// Watchdog im Player dort nie aus. Ein hängender Strom lief stumm ins /// Nichts, ohne Kreisel, ohne Meldung, ohne Abbruch. /// /// Nur aus dem Spielen heraus gewertet. Die Dokumentation sagt, dass vor