Improve streams extraction

This commit is contained in:
Arkadiusz Fal 2022-06-17 12:52:10 +02:00
parent 15cdde17a6
commit e6e18de106
3 changed files with 37 additions and 43 deletions

View File

@ -4,6 +4,7 @@ import Siesta
import SwiftyJSON import SwiftyJSON
final class PipedAPI: Service, ObservableObject, VideosAPI { final class PipedAPI: Service, ObservableObject, VideosAPI {
static var disallowedVideoCodecs = ["av01"]
static var authorizedEndpoints = ["subscriptions", "subscribe", "unsubscribe", "user/playlists"] static var authorizedEndpoints = ["subscriptions", "subscribe", "unsubscribe", "user/playlists"]
@Published var account: Account! @Published var account: Account!
@ -500,17 +501,19 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
let videoStreams = content.dictionaryValue["videoStreams"]?.arrayValue ?? [] let videoStreams = content.dictionaryValue["videoStreams"]?.arrayValue ?? []
videoStreams.forEach { videoStream in videoStreams.forEach { videoStream in
guard let audioAssetUrl = audioStream.dictionaryValue["url"]?.url, let videoCodec = videoStream.dictionaryValue["codec"]?.string ?? ""
let videoAssetUrl = videoStream.dictionaryValue["url"]?.url if Self.disallowedVideoCodecs.contains(where: videoCodec.contains) {
else {
return return
} }
let audioAsset = AVURLAsset(url: audioAssetUrl) let audioAsset = AVURLAsset(url: audioStream.dictionaryValue["url"]!.url!)
let videoAsset = AVURLAsset(url: videoAssetUrl) let videoAsset = AVURLAsset(url: videoStream.dictionaryValue["url"]!.url!)
let videoOnly = videoStream.dictionaryValue["videoOnly"]?.boolValue ?? true let videoOnly = videoStream.dictionaryValue["videoOnly"]?.boolValue ?? true
let resolution = Stream.Resolution.from(resolution: videoStream.dictionaryValue["quality"]!.stringValue) let quality = videoStream.dictionaryValue["quality"]?.string ?? "unknown"
let qualityComponents = quality.components(separatedBy: "p")
let fps = Int(qualityComponents[1].isEmpty ? "30" : qualityComponents[1])
let resolution = Stream.Resolution.from(resolution: quality, fps: fps)
let videoFormat = videoStream.dictionaryValue["format"]?.stringValue let videoFormat = videoStream.dictionaryValue["format"]?.stringValue
if videoOnly { if videoOnly {

View File

@ -5,32 +5,30 @@ import Foundation
// swiftlint:disable:next final_class // swiftlint:disable:next final_class
class Stream: Equatable, Hashable, Identifiable { class Stream: Equatable, Hashable, Identifiable {
enum Resolution: String, CaseIterable, Comparable, Defaults.Serializable { enum Resolution: String, CaseIterable, Comparable, Defaults.Serializable {
case hd4320p60
case hd4320p
case hd2160p60 case hd2160p60
case hd2160p50 case hd2160p50
case hd2160p48 case hd2160p48
case hd2160p case hd2160p30
case hd1440p60 case hd1440p60
case hd1440p50 case hd1440p50
case hd1440p48 case hd1440p48
case hd1440p case hd1440p30
case hd1080p60 case hd1080p60
case hd1080p50 case hd1080p50
case hd1080p48 case hd1080p48
case hd1080p case hd1080p30
case hd720p60 case hd720p60
case hd720p50 case hd720p50
case hd720p48 case hd720p48
case hd720p case hd720p30
case sd480p case sd480p30
case sd360p case sd360p30
case sd240p case sd240p30
case sd144p case sd144p30
case unknown case unknown
var name: String { var name: String {
"\(height)p\(refreshRate != -1 ? ", \(refreshRate) fps" : "")" "\(height)p\(refreshRate != -1 && refreshRate != 30 ? ", \(refreshRate) fps" : "")"
} }
var height: Int { var height: Int {
@ -48,11 +46,16 @@ class Stream: Equatable, Hashable, Identifiable {
} }
let refreshRatePart = rawValue.components(separatedBy: "p")[1] let refreshRatePart = rawValue.components(separatedBy: "p")[1]
if refreshRatePart.isEmpty {
return 30
}
return Int(refreshRatePart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) ?? -1 return Int(refreshRatePart.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) ?? -1
} }
static func from(resolution: String) -> Resolution { static func from(resolution: String, fps: Int? = nil) -> Resolution {
allCases.first { "\($0)".contains(resolution) } ?? .unknown allCases.first { $0.rawValue.contains(resolution) && $0.refreshRate == (fps ?? 30) } ?? .unknown
} }
static func < (lhs: Resolution, rhs: Resolution) -> Bool { static func < (lhs: Resolution, rhs: Resolution) -> Bool {
@ -157,7 +160,7 @@ class Stream: Equatable, Hashable, Identifiable {
} }
var quality: String { var quality: String {
if resolution == .hd2160p { if resolution == .hd2160p30 {
return "4K (2160p)" return "4K (2160p)"
} }
@ -165,13 +168,7 @@ class Stream: Equatable, Hashable, Identifiable {
} }
var shortQuality: String { var shortQuality: String {
if resolution == .hd4320p60 || resolution == .hd4320p { if resolution.height == 2160 {
return "8K"
} else if resolution == .hd2160p60 ||
resolution == .hd2160p50 ||
resolution == .hd2160p48 ||
resolution == .hd2160p
{
return "4K" return "4K"
} else if kind == .hls { } else if kind == .hls {
return "HLS" return "HLS"

View File

@ -93,25 +93,23 @@ extension Defaults.Keys {
enum ResolutionSetting: String, CaseIterable, Defaults.Serializable { enum ResolutionSetting: String, CaseIterable, Defaults.Serializable {
case best case best
case hd4320p60
case hd4320p
case hd2160p60 case hd2160p60
case hd2160p case hd2160p30
case hd1440p60 case hd1440p60
case hd1440p case hd1440p30
case hd1080p60 case hd1080p60
case hd1080p case hd1080p30
case hd720p60 case hd720p60
case hd720p case hd720p30
case sd480p case sd480p30
case sd360p case sd360p30
case sd240p case sd240p30
case sd144p case sd144p30
var value: Stream.Resolution { var value: Stream.Resolution {
switch self { switch self {
case .best: case .best:
return .hd4320p60 return .hd2160p60
default: default:
return Stream.Resolution(rawValue: rawValue)! return Stream.Resolution(rawValue: rawValue)!
} }
@ -121,13 +119,9 @@ enum ResolutionSetting: String, CaseIterable, Defaults.Serializable {
switch self { switch self {
case .best: case .best:
return "Best available quality" return "Best available quality"
case .hd4320p60:
return "8K, 60fps"
case .hd4320p:
return "8K"
case .hd2160p60: case .hd2160p60:
return "4K, 60fps" return "4K, 60fps"
case .hd2160p: case .hd2160p30:
return "4K" return "4K"
default: default:
return value.name return value.name