mirror of
https://github.com/yattee/yattee.git
synced 2025-08-09 20:24:06 +00:00
Add Piped support
This commit is contained in:
@@ -3,7 +3,7 @@ import Defaults
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable:next final_class
|
||||
class Stream: Equatable, Hashable {
|
||||
class Stream: Equatable, Hashable, Identifiable {
|
||||
enum ResolutionSetting: String, Defaults.Serializable, CaseIterable {
|
||||
case hd720pFirstThenBest, hd1080p, hd720p, sd480p, sd360p, sd240p, sd144p
|
||||
|
||||
@@ -21,20 +21,38 @@ class Stream: Equatable, Hashable {
|
||||
case .hd720pFirstThenBest:
|
||||
return "Default: adaptive"
|
||||
default:
|
||||
return "\(value.height)p".replacingOccurrences(of: " ", with: "")
|
||||
return value.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Resolution: String, CaseIterable, Comparable, Defaults.Serializable {
|
||||
case hd1080p, hd720p, sd480p, sd360p, sd240p, sd144p
|
||||
case hd1440p60, hd1440p, hd1080p60, hd1080p, hd720p60, hd720p, sd480p, sd360p, sd240p, sd144p, unknown
|
||||
|
||||
var height: Int {
|
||||
Int(rawValue.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())!
|
||||
var name: String {
|
||||
"\(height)p\(refreshRate != -1 ? ", \(refreshRate) fps" : "")"
|
||||
}
|
||||
|
||||
static func from(resolution: String) -> Resolution? {
|
||||
allCases.first { "\($0)".contains(resolution) }
|
||||
var height: Int {
|
||||
if self == .unknown {
|
||||
return -1
|
||||
}
|
||||
|
||||
let resolutionPart = rawValue.components(separatedBy: "p").first!
|
||||
return Int(resolutionPart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())!
|
||||
}
|
||||
|
||||
var refreshRate: Int {
|
||||
if self == .unknown {
|
||||
return -1
|
||||
}
|
||||
|
||||
let refreshRatePart = rawValue.components(separatedBy: "p")[1]
|
||||
return Int(refreshRatePart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) ?? -1
|
||||
}
|
||||
|
||||
static func from(resolution: String) -> Resolution {
|
||||
allCases.first { "\($0)".contains(resolution) } ?? .unknown
|
||||
}
|
||||
|
||||
static func < (lhs: Resolution, rhs: Resolution) -> Bool {
|
||||
@@ -43,14 +61,16 @@ class Stream: Equatable, Hashable {
|
||||
}
|
||||
|
||||
enum Kind: String, Comparable {
|
||||
case stream, adaptive
|
||||
case stream, adaptive, hls
|
||||
|
||||
private var sortOrder: Int {
|
||||
switch self {
|
||||
case .stream:
|
||||
case .hls:
|
||||
return 0
|
||||
case .adaptive:
|
||||
case .stream:
|
||||
return 1
|
||||
case .adaptive:
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,39 +79,98 @@ class Stream: Equatable, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
var audioAsset: AVURLAsset
|
||||
var videoAsset: AVURLAsset
|
||||
let id = UUID()
|
||||
|
||||
var resolution: Resolution
|
||||
var kind: Kind
|
||||
var instance: Instance!
|
||||
var audioAsset: AVURLAsset!
|
||||
var videoAsset: AVURLAsset!
|
||||
var hlsURL: URL!
|
||||
|
||||
var encoding: String
|
||||
var resolution: Resolution!
|
||||
var kind: Kind!
|
||||
|
||||
init(audioAsset: AVURLAsset, videoAsset: AVURLAsset, resolution: Resolution, kind: Kind, encoding: String) {
|
||||
var encoding: String!
|
||||
|
||||
init(
|
||||
instance: Instance? = nil,
|
||||
audioAsset: AVURLAsset? = nil,
|
||||
videoAsset: AVURLAsset? = nil,
|
||||
hlsURL: URL? = nil,
|
||||
resolution: Resolution? = nil,
|
||||
kind: Kind = .hls,
|
||||
encoding: String? = nil
|
||||
) {
|
||||
self.instance = instance
|
||||
self.audioAsset = audioAsset
|
||||
self.videoAsset = videoAsset
|
||||
self.hlsURL = hlsURL
|
||||
self.resolution = resolution
|
||||
self.kind = kind
|
||||
self.encoding = encoding
|
||||
}
|
||||
|
||||
var shortQuality: String {
|
||||
kind == .hls ? "adaptive" : resolution.name
|
||||
}
|
||||
|
||||
var quality: String {
|
||||
kind == .hls ? "adaptive (HLS)" : "\(resolution.name) \(kind == .stream ? "(\(kind.rawValue))" : "")"
|
||||
}
|
||||
|
||||
var description: String {
|
||||
"\(resolution.height)p"
|
||||
"\(quality) - \(instance?.description ?? "")"
|
||||
}
|
||||
|
||||
var assets: [AVURLAsset] {
|
||||
[audioAsset, videoAsset]
|
||||
}
|
||||
|
||||
var oneMeaningfullAsset: Bool {
|
||||
var videoAssetContainsAudio: Bool {
|
||||
assets.dropFirst().allSatisfy { $0.url == assets.first!.url }
|
||||
}
|
||||
|
||||
var singleAssetURL: URL? {
|
||||
if kind == .hls {
|
||||
return hlsURL
|
||||
} else if videoAssetContainsAudio {
|
||||
return videoAsset.url
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
static func == (lhs: Stream, rhs: Stream) -> Bool {
|
||||
lhs.resolution == rhs.resolution && lhs.kind == rhs.kind
|
||||
lhs.id == rhs.id
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(videoAsset.url)
|
||||
hasher.combine(videoAsset?.url)
|
||||
hasher.combine(audioAsset?.url)
|
||||
hasher.combine(hlsURL)
|
||||
}
|
||||
|
||||
func withAssetsFrom(_ instance: Instance) -> Stream {
|
||||
if kind == .hls {
|
||||
return Stream(instance: instance, hlsURL: hlsURL)
|
||||
} else {
|
||||
return Stream(
|
||||
instance: instance,
|
||||
audioAsset: AVURLAsset(url: assetURLFrom(instance: instance, url: (audioAsset ?? videoAsset).url)!),
|
||||
videoAsset: AVURLAsset(url: assetURLFrom(instance: instance, url: videoAsset.url)!),
|
||||
resolution: resolution,
|
||||
kind: kind,
|
||||
encoding: encoding
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func assetURLFrom(instance: Instance, url: URL) -> URL? {
|
||||
guard let instanceURLComponents = URLComponents(string: instance.url),
|
||||
var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return nil }
|
||||
|
||||
urlComponents.scheme = instanceURLComponents.scheme
|
||||
urlComponents.host = instanceURLComponents.host
|
||||
|
||||
return urlComponents.url
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user