Bei Jellyfin galt zuhause als unterwegs

Beinahe-Regression, gefunden bevor sie jemanden traf: `isLocalConnection`
kam aus `session.server?.connection.local`, und `server` ist ein
`PlexServer` — bei Jellyfin immer `nil`. Jede Jellyfin-Wiedergabe galt
damit als entfernt, auch zuhause am Kabel. Der neue Deckel hätte dort ein
67-Mbit-Remux ohne Not auf acht Megabit heruntergerechnet.

Jetzt wird gefragt statt geraten: `/System/Endpoint` beantwortet es mit
**demselben** Aufruf, mit dem Jellyfin auch selbst entscheidet, ob es eine
Bitratenleiter ausliefert. Ein Blick auf die Adresse hätte nicht genügt —
wer über einen Reverse Proxy geht, erreicht seinen Server auch von der
Couch aus unter einem öffentlichen Namen, und über ein VPN kommt eine
private Adresse von weit her.

Gefragt wird bei beiden Wegen, beim Anmelden und beim Wiederherstellen:
dasselbe Konto kann heute zuhause und morgen im Zug aufwachen.

Im Zweifel `false` — lieber einmal zu vorsichtig gedeckelt als eine
Wiedergabe, die über eine Fernverbindung gar nicht erst anläuft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-27 18:37:16 +02:00
co-authored by Claude Opus 5
parent fd11a9eebe
commit 24d7423f9c
3 changed files with 47 additions and 1 deletions
@@ -30,6 +30,31 @@ public struct JellyfinBackend: MediaBackend {
// MARK: - Blättern
/// Ob der Server diese Verbindung als „im eigenen Netz" ansieht.
///
/// **Gefragt, nicht geraten.** Ein Blick auf die Adresse taugt nicht: wer
/// über einen Reverse Proxy geht, erreicht seinen Server auch von der
/// Couch aus unter einem öffentlichen Namen. Umgekehrt kann eine private
/// Adresse über ein VPN von weit her kommen.
///
/// `/System/Endpoint` beantwortet es mit **demselben** Aufruf, mit dem
/// Jellyfin auch selbst entscheidet, ob es eine Bitratenleiter ausliefert.
/// Näher an der Wahrheit kommt man nicht heran.
///
/// Bei Zweifeln `false`: lieber einmal zu vorsichtig gedeckelt als eine
/// Wiedergabe, die über eine Fernverbindung gar nicht erst anläuft.
public func isInLocalNetwork() async -> Bool {
struct Lage: Decodable {
let isInNetwork: Bool
private enum CodingKeys: String, CodingKey { case isInNetwork = "IsInNetwork" }
}
let lage = try? await client.send(
JellyfinRequest(path: "/System/Endpoint"),
as: Lage.self
)
return lage?.isInNetwork ?? false
}
public func libraries() async throws(MediaBackendError) -> [MediaLibrary] {
let page = try await client.send(
JellyfinRequest(path: "/Users/\(account.userID)/Views"),