Files
Flaro/Packages/FlixyKit/Sources/FlixyPlayback/Decision/NetworkConditions.swift
T
GuidoandClaude Opus 5 55bcfe2fbf Phase 2: Transcoding, adaptive Bitrate, Spuren, Marker, Sync
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>
2026-09-11 17:24:17 +02:00

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()
}
}