Watchdog heisst Watchdog, Engine heisst Engine

Eingedeutschte Fachbegriffe in den Kommentaren — „Wachhund" für
Watchdog, „Motor" für Engine. Das liest sich albern und ist unklarer als
das Original; niemand sagt Wachhund, wenn er einen Watchdog meint.

Acht Stellen berichtigt. Gewöhnliche Sprache bleibt deutsch, der Stil
der Kommentare ändert sich nicht.

Dazu die Plex-Leiter messbar gemacht: `--leiter` baut dieselbe Anfrage
zweimal, mit und ohne `autoAdjustQuality=1`, und zählt die Stufen. Die
Zeile steht seit dem Umbau im Code und war nie geprüft — genau die Art
ungeprüfter Annahme über Serververhalten, die bei Jellyfin vier Runden
gekostet hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-27 17:47:31 +02:00
co-authored by Claude Opus 5
parent 314c1a3bfc
commit e324a474fd
10 changed files with 45 additions and 9 deletions
+1 -1
View File
@@ -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.
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
@@ -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,
@@ -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,
@@ -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")
@@ -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