Der Decider brauchte keine Änderung — nur eine andere Richtlinie. Genau dafür war er gebaut. Transcoding - TranscodeRequest baut die Parameter für /video/:/transcode/universal. directStream=1 lässt Plex nur umpacken, wenn der Bildcodec passt, statt pauschal neu zu kodieren. - Vor dem Start wird der Server gefragt (decision); sagt er nein, steht der Grund im Klartext da statt eines schwarzen Bildes. - Beim Verlassen wird der Transcoder angehalten. Ohne dieses Signal rechnet der Server minutenlang für niemanden weiter. - Die adaptive Bitrate kommt mit HLS: AVPlayer wechselt sie selbst. Qualitätseinstellungen - Getrennt für WLAN und Mobilfunk, fünf spürbare Stufen. Voreinstellung: zuhause Original, unterwegs 4 Mbit. - NetworkConditions erkennt Mobilfunk über isExpensive — das deckt auch den Hotspot ab, der technisch WLAN ist und trotzdem Volumen kostet. Spuren und Marken - Ton- und Untertitelwahl im Player, bevorzugte Sprache in den Einstellungen, nachsichtiger Sprachvergleich (de/deu/ger/de-DE). - Intro- und Abspann-Marken mit Überspringen-Knopf, optional automatisch. Bereits übersprungene Marken werden gemerkt, sonst käme man nach einem Rücksprung nie ins Intro zurück. - Nächste Folge inkl. Staffelwechsel; Specials in Staffel 0 werden nicht vorgezogen. Fortschritt - Alle zehn Sekunden an den Server, plus Schlussmeldung beim Verlassen. Erst die nimmt den Titel aus „wird gerade abgespielt" heraus. - markWatched/markUnwatched/rate/refreshLibrary stehen bereit. 86 Tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
39 lines
1.3 KiB
Swift
39 lines
1.3 KiB
Swift
import Foundation
|
|
import Network
|
|
import Observation
|
|
|
|
/// Beobachtet, worüber das Gerät gerade am Netz hängt.
|
|
///
|
|
/// Die Unterscheidung WLAN/Mobilfunk entscheidet, welche Bitratengrenze gilt.
|
|
/// `isExpensive` statt einer Abfrage auf den Schnittstellentyp: der Wert deckt
|
|
/// auch den Fall ab, dass das iPhone am persönlichen Hotspot eines anderen
|
|
/// Geräts hängt — technisch WLAN, in der Abrechnung Mobilfunk.
|
|
@MainActor
|
|
@Observable
|
|
public final class NetworkConditions {
|
|
public private(set) var isReachable = true
|
|
/// Mobilfunk oder Hotspot — alles, was Datenvolumen kostet.
|
|
public private(set) var isExpensive = false
|
|
/// Der Sparmodus für Daten ist an. Dann sollte die App von sich aus
|
|
/// sparsam sein, auch im WLAN.
|
|
public private(set) var isConstrained = false
|
|
|
|
private let monitor = NWPathMonitor()
|
|
|
|
public init() {
|
|
monitor.pathUpdateHandler = { [weak self] path in
|
|
Task { @MainActor [weak self] in
|
|
guard let self else { return }
|
|
isReachable = path.status == .satisfied
|
|
isExpensive = path.isExpensive
|
|
isConstrained = path.isConstrained
|
|
}
|
|
}
|
|
monitor.start(queue: DispatchQueue(label: "flixy.network"))
|
|
}
|
|
|
|
deinit {
|
|
monitor.cancel()
|
|
}
|
|
}
|