feat: choose YouTube quality with a 1080p default
This commit is contained in:
@@ -167,6 +167,40 @@ struct YouTubeResolverChecks {
|
||||
try require(try decode(emptyHeaders).video.headers.isEmpty, "absent headers serialize to an empty block")
|
||||
}
|
||||
|
||||
static func qualities() throws {
|
||||
func video(_ height: Int, audio: Bool = false, range: String = "SDR", transport: String = "https") -> [String: Any] {
|
||||
["height": height, "vcodec": "h264", "acodec": audio ? "aac" : "none",
|
||||
"dynamic_range": range, "protocol": transport, "url": "https://media.example/\(height)p"]
|
||||
}
|
||||
let audio: [String: Any] = ["vcodec": "none", "acodec": "aac", "url": "https://media.example/audio"]
|
||||
var object: [String: Any] = [
|
||||
"requested_formats": [video(1080), audio],
|
||||
"formats": [video(2160), video(1440), video(1080), video(1080, audio: true), video(720),
|
||||
video(480), video(4320, range: "HDR10"), video(360, transport: "http_dash_segments"),
|
||||
video(0), audio]
|
||||
]
|
||||
let normal = try decode(object)
|
||||
try require(normal.height == 1080 && normal.availableHeights == [2160, 1440, 1080, 720, 480],
|
||||
"quality choices are unique playable SDR resolutions, including manual choices above the default cap")
|
||||
object["requested_formats"] = [video(720), audio]
|
||||
try require(try decode(object).height == 720, "a lower available resolution is accepted by the default policy")
|
||||
object["requested_formats"] = [video(2160), audio]
|
||||
try reject("4K stream selected by the default policy") { _ = try decode(object) }
|
||||
let data = try JSONSerialization.data(withJSONObject: object)
|
||||
let high = try YouTubeResolver.decode(data, webpageURL: page, height: 2160)
|
||||
try require(high.height == 2160 && high.video.url == "https://media.example/2160p",
|
||||
"explicit selection permits supported 4K video")
|
||||
try reject("requested resolution silently replaced by another") {
|
||||
_ = try YouTubeResolver.decode(data, webpageURL: page, height: 1440)
|
||||
}
|
||||
object["requested_formats"] = [video(720, audio: true)]
|
||||
object["formats"] = [video(2160), video(720, audio: true)]
|
||||
try require(try decode(object).availableHeights == [720],
|
||||
"video-only resolutions without a playable separate audio stream are not offered")
|
||||
object["requested_formats"] = [video(-720, audio: true)]
|
||||
try reject("invalid selected video dimensions") { _ = try decode(object) }
|
||||
}
|
||||
|
||||
static func malformedMetadata() throws {
|
||||
try reject("non-JSON extractor output") { _ = try decode("not JSON") }
|
||||
for json in ["null", "[]", "{}", #"{"requested_formats":[]}"#] {
|
||||
@@ -366,6 +400,49 @@ struct YouTubeResolverChecks {
|
||||
"cancelling an old request cannot terminate or replace a newer resolution")
|
||||
}
|
||||
|
||||
static func actualQualitySelection(root: URL, runtime: URL) async throws {
|
||||
let directories = (ProcessInfo.processInfo.environment["PATH"] ?? "").split(separator: ":").map(String.init)
|
||||
+ ["/opt/homebrew/bin", "/usr/local/bin"]
|
||||
guard let executable = directories.map({ URL(fileURLWithPath: $0).appendingPathComponent("yt-dlp") })
|
||||
.first(where: { FileManager.default.isExecutableFile(atPath: $0.path) }) else {
|
||||
print("Skipping actual yt-dlp quality selection: yt-dlp is not installed")
|
||||
return
|
||||
}
|
||||
func video(_ height: Int, combined: Bool = false) -> [String: Any] {
|
||||
["format_id": "\(height)", "height": height, "width": height * 16 / 9, "ext": "mp4",
|
||||
"vcodec": "h264", "acodec": combined ? "aac" : "none", "dynamic_range": "SDR",
|
||||
"protocol": "https", "url": "https://media.example/\(height).mp4", "preference": height == 720 ? 100 : 0]
|
||||
}
|
||||
var object: [String: Any] = [
|
||||
"id": "jNQXAC9IVRw", "title": "Quality ordering", "duration": 12,
|
||||
"webpage_url": page.absoluteString, "extractor": "youtube", "extractor_key": "Youtube",
|
||||
"formats": [video(2160), video(1080, combined: true), video(720),
|
||||
["format_id": "audio", "ext": "m4a", "vcodec": "none", "acodec": "aac",
|
||||
"protocol": "https", "url": "https://media.example/audio.m4a"]]
|
||||
]
|
||||
let extractor = try Extractor(root: root, name: "actual quality selection")
|
||||
let quotedExecutable = "'" + executable.path.replacingOccurrences(of: "'", with: "'\\''") + "'"
|
||||
let script = """
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
base=${0%/*}
|
||||
args=("$@")
|
||||
exec \(quotedExecutable) --load-info-json "$base/response.json" "${args[@]:0:${#args[@]}-2}"
|
||||
"""
|
||||
try Data(script.utf8).write(to: extractor.executable)
|
||||
try JSONSerialization.data(withJSONObject: object).write(to: extractor.marker("response.json"))
|
||||
let normal = try await YouTubeResolver.resolve(page, executableURL: extractor.executable, runtimeURL: runtime)
|
||||
try require(normal.height == 1080 && normal.audio == nil, "1080p combined video wins over preferred 720p and capped-out 4K")
|
||||
let high = try await YouTubeResolver.resolve(page, height: 2160, executableURL: extractor.executable, runtimeURL: runtime)
|
||||
try require(high.height == 2160 && high.audio != nil, "explicit 4K selects the higher video with separate audio")
|
||||
var formats = object["formats"] as! [[String: Any]]
|
||||
formats.removeAll { ($0["height"] as? Int) == 1080 }
|
||||
object["formats"] = formats
|
||||
try JSONSerialization.data(withJSONObject: object).write(to: extractor.marker("response.json"))
|
||||
let lower = try await YouTubeResolver.resolve(page, executableURL: extractor.executable, runtimeURL: runtime)
|
||||
try require(lower.height == 720, "default falls downward when 1080p is absent, never upward to available 4K")
|
||||
}
|
||||
|
||||
static func main() async throws {
|
||||
// A broken pipe/cancellation implementation must fail, not leave this check hanging.
|
||||
let watchdog = Task {
|
||||
@@ -382,7 +459,9 @@ struct YouTubeResolverChecks {
|
||||
try videoURLs()
|
||||
try metadata()
|
||||
try malformedMetadata()
|
||||
try qualities()
|
||||
try await subprocesses(root: root, runtime: runtime)
|
||||
try await actualQualitySelection(root: root, runtime: runtime)
|
||||
print("YouTube resolver checks passed")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user