„Automatisch" misst jetzt, statt die Einstellung durchzureichen
Bisher hieß `PlayerQuality.automatic` wörtlich: nimm die Zahl, die für WLAN oder Mobilfunk hinterlegt ist. Keine Messung, kein Nachregeln — die Entscheidung fiel einmal beim Start und galt bis zum Ende. `StreamHealth` beurteilt den Strom jetzt fortlaufend aus Proben im Sekundentakt. Ein reiner Typ: kein AVFoundation, keine Uhr, kein Netz. Damit lässt sich eine schlechte Zugfahrt als Zahlenreihe hinschreiben und nachsehen, was sie auslöst — zehn Tests tun genau das. **Welches Signal wann meldet**, ist der eigentliche Inhalt. Der Pufferverlauf ist der einzige echte Frühwarner: schrumpft er schneller, als die Zeit vergeht, kommt weniger herein als hinausgeht, und das sieht man zehn bis zwanzig Sekunden vor dem Rückler. `isLikelyToKeepUp` ist früh, aber sprunghaft — es zählt erst, wenn es anhält. Der Rücklerzähler meldet zu spät zum Regeln und bleibt trotzdem der Massstab, an dem sich hinterher ablesen lässt, ob es besser wurde. Die **gemessene** Bitrate steht bewusst nicht drin: auf einer kleinen Sprosse holt der Player wenig, ohne dass die Leitung schlecht wäre. Ausdrücklich kein Bandbreitentest. Der kostet Daten, ist beim Vorliegen veraltet und misst die Vergangenheit. Der Pufferverlauf ist die bessere Messung, weil er die einzige Größe misst, auf die es ankommt: lädt es schneller, als es läuft. Gehandelt wird über `preferredPeakBitRate` — der billige Hebel, der ohne Neuaufbau wirkt. Gezielt wird dabei auf eine Sprosse, **die es in `AVAsset.variants` wirklich gibt**: ein Wert zwischen zweien wählt dieselbe wie die untere und machte jede Anzeige darüber zur Lüge. Absichtlich unsymmetrisch — runter sofort, hinauf frühestens nach einer Minute Ruhe. Und getrennt von `quality`: die Automatik ruft **nicht** `select(quality:)`. Die Methode schreibt `rememberedQuality` fort und setzte eine manuelle Stufe — womit die Automatik sich selbst abschaltete und eine schlechte Zugfahrt dauerhaft das Wohnzimmer verschlechterte. Hat die Playlist nur eine Stufe, greift der Hebel ins Leere. Das ist kein Fehler, sondern der Fall, für den die Sicherheitsleine gebaut wird — bis dahin steht er wenigstens im Protokoll. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cdff53fa0d
commit
52d6ebba43
@@ -201,6 +201,13 @@ public final class AVPlayerEngine: VideoPlayerEngine {
|
||||
continuation?.yield(.timeChanged(time))
|
||||
}
|
||||
|
||||
public func setPeakBitrate(_ kilobits: Int?) {
|
||||
guard let item = player.currentItem else { return }
|
||||
// Null heißt bei AVFoundation „keine Grenze". Kein Sonderfall, nur
|
||||
// eine andere Schreibweise für dasselbe.
|
||||
item.preferredPeakBitRate = kilobits.map { Double($0) * 1_000 } ?? 0
|
||||
}
|
||||
|
||||
public func setRate(_ rate: Double) {
|
||||
player.rate = Float(rate)
|
||||
}
|
||||
|
||||
@@ -98,6 +98,20 @@ public protocol VideoPlayerEngine: AnyObject {
|
||||
/// Leitung schlecht ist?" eine Vermutung.
|
||||
var statistics: PlaybackStatistics? { get }
|
||||
|
||||
/// Deckelt, welche Sprosse der Player höchstens ziehen darf.
|
||||
///
|
||||
/// **Der billige Hebel.** Er wirkt ohne Neuaufbau: kein Anhalten am
|
||||
/// Server, keine neue Aushandlung, kein Sprung zurück an die alte Stelle.
|
||||
/// `nil` hebt die Grenze auf.
|
||||
///
|
||||
/// Zwei Einschränkungen gehören dazugesagt. Der Wert greift erst an der
|
||||
/// nächsten Schnipselgrenze, also mit einigen Sekunden Verzug — ein Grund
|
||||
/// mehr, nicht bei jedem Ausschlag daran zu drehen. Und **bei einer
|
||||
/// Playlist mit einer einzigen Stufe tut er nichts**: der Player spielt
|
||||
/// sie auch dann, wenn sie über der Grenze liegt. Der Wert ist ein
|
||||
/// Wunsch, keine Vorschrift.
|
||||
func setPeakBitrate(_ kilobits: Int?)
|
||||
|
||||
/// Gibt Puffer und Dekoder frei. Muss beim Verlassen des Players laufen,
|
||||
/// sonst behält besonders VLCKit den Speicher.
|
||||
func teardown()
|
||||
@@ -203,6 +217,10 @@ extension VideoPlayerEngine {
|
||||
/// Engines, die nichts melden, melden nichts — statt jeden zu zwingen.
|
||||
public var statistics: PlaybackStatistics? { nil }
|
||||
|
||||
/// Wer keine Leiter hat, kann auch nichts deckeln. Kein Fehler, nur
|
||||
/// nichts zu tun — bei einer Datei gibt es keine Stufen.
|
||||
public func setPeakBitrate(_ kilobits: Int?) {}
|
||||
|
||||
/// Wer nichts dazu sagt, kann es nicht.
|
||||
public var supportsAirPlay: Bool { false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user