mirror of
https://github.com/yattee/yattee.git
synced 2025-10-11 01:48:12 +00:00
Quality profiles
This commit is contained in:
112
Model/QualityProfile.swift
Normal file
112
Model/QualityProfile.swift
Normal file
@@ -0,0 +1,112 @@
|
||||
import Defaults
|
||||
import Foundation
|
||||
|
||||
struct QualityProfile: Hashable, Identifiable, Defaults.Serializable {
|
||||
static var bridge = QualityProfileBridge()
|
||||
static var defaultProfile = Self(id: "default", backend: .mpv, resolution: .hd720p60, formats: [.stream])
|
||||
static var highQualityProfile = Self(id: "highQuality", backend: .mpv, resolution: .best, formats: [.webm, .mp4, .av1, .avc1])
|
||||
|
||||
enum Format: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||
case hls
|
||||
case stream
|
||||
case mp4
|
||||
case avc1
|
||||
case av1
|
||||
case webm
|
||||
|
||||
var id: String {
|
||||
rawValue
|
||||
}
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .stream:
|
||||
return "Stream"
|
||||
case .webm:
|
||||
return "WebM"
|
||||
|
||||
default:
|
||||
return rawValue.uppercased()
|
||||
}
|
||||
}
|
||||
|
||||
var streamFormat: Stream.Format? {
|
||||
switch self {
|
||||
case .hls:
|
||||
return nil
|
||||
case .stream:
|
||||
return nil
|
||||
case .mp4:
|
||||
return .mp4
|
||||
case .webm:
|
||||
return .webm
|
||||
case .avc1:
|
||||
return .avc1
|
||||
case .av1:
|
||||
return .av1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var id = UUID().uuidString
|
||||
|
||||
var name: String?
|
||||
var backend: PlayerBackendType
|
||||
var resolution: ResolutionSetting
|
||||
var formats: [Format]
|
||||
|
||||
var description: String {
|
||||
if let name = name, !name.isEmpty { return name }
|
||||
return "\(backend.label) - \(resolution.description) - \(formats.map(\.description).joined(separator: ", "))"
|
||||
}
|
||||
|
||||
func isPreferred(_ stream: Stream) -> Bool {
|
||||
if formats.contains(.hls), stream.kind == .hls {
|
||||
return true
|
||||
}
|
||||
|
||||
let resolutionMatch = !stream.resolution.isNil && (resolution == .best || (resolution.value >= stream.resolution))
|
||||
|
||||
if resolutionMatch, formats.contains(.stream), stream.kind == .stream {
|
||||
return true
|
||||
}
|
||||
|
||||
let formatMatch = formats.compactMap(\.streamFormat).contains(stream.format)
|
||||
|
||||
return resolutionMatch && formatMatch
|
||||
}
|
||||
}
|
||||
|
||||
struct QualityProfileBridge: Defaults.Bridge {
|
||||
static let formatsSeparator = ","
|
||||
|
||||
typealias Value = QualityProfile
|
||||
typealias Serializable = [String: String]
|
||||
|
||||
func serialize(_ value: Value?) -> Serializable? {
|
||||
guard let value = value else { return nil }
|
||||
|
||||
return [
|
||||
"id": value.id,
|
||||
"name": value.name ?? "",
|
||||
"backend": value.backend.rawValue,
|
||||
"resolution": value.resolution.rawValue,
|
||||
"formats": value.formats.map { $0.rawValue }.joined(separator: Self.formatsSeparator)
|
||||
]
|
||||
}
|
||||
|
||||
func deserialize(_ object: Serializable?) -> Value? {
|
||||
guard let object = object,
|
||||
let id = object["id"],
|
||||
let backend = PlayerBackendType(rawValue: object["backend"] ?? ""),
|
||||
let resolution = ResolutionSetting(rawValue: object["resolution"] ?? "")
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let name = object["name"]
|
||||
let formats = (object["formats"] ?? "").components(separatedBy: Self.formatsSeparator).compactMap { QualityProfile.Format(rawValue: $0) }
|
||||
|
||||
return .init(id: id, name: name, backend: backend, resolution: resolution, formats: formats)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user