2022-04-17 09:33:49 +00:00
|
|
|
import CoreMedia
|
2021-10-24 09:16:04 +00:00
|
|
|
import Foundation
|
|
|
|
|
|
|
|
struct VideoURLParser {
|
|
|
|
let url: URL
|
|
|
|
|
|
|
|
var id: String? {
|
|
|
|
if urlComponents?.host == "youtu.be", let path = urlComponents?.path {
|
|
|
|
return String(path.suffix(from: path.index(path.startIndex, offsetBy: 1)))
|
|
|
|
}
|
|
|
|
|
|
|
|
return queryItemValue("v")
|
|
|
|
}
|
|
|
|
|
2022-04-17 09:33:49 +00:00
|
|
|
var time: CMTime? {
|
2021-10-24 09:16:04 +00:00
|
|
|
guard let time = queryItemValue("t") else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
let timeComponents = parseTime(time)
|
|
|
|
|
|
|
|
guard !timeComponents.isEmpty,
|
|
|
|
let hours = TimeInterval(timeComponents["hours"] ?? "0"),
|
|
|
|
let minutes = TimeInterval(timeComponents["minutes"] ?? "0"),
|
|
|
|
let seconds = TimeInterval(timeComponents["seconds"] ?? "0")
|
|
|
|
else {
|
|
|
|
if let time = TimeInterval(time) {
|
2022-04-17 09:33:49 +00:00
|
|
|
return .secondsInDefaultTimescale(time)
|
2021-10-24 09:16:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-04-17 09:33:49 +00:00
|
|
|
return .secondsInDefaultTimescale(seconds + (minutes * 60) + (hours * 60 * 60))
|
2021-10-24 09:16:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func queryItemValue(_ name: String) -> String? {
|
|
|
|
queryItems.first { $0.name == name }?.value
|
|
|
|
}
|
|
|
|
|
|
|
|
private var queryItems: [URLQueryItem] {
|
|
|
|
urlComponents?.queryItems ?? []
|
|
|
|
}
|
|
|
|
|
|
|
|
private var urlComponents: URLComponents? {
|
|
|
|
URLComponents(url: url, resolvingAgainstBaseURL: false)
|
|
|
|
}
|
|
|
|
|
|
|
|
private func parseTime(_ time: String) -> [String: String] {
|
|
|
|
let results = timeRegularExpression.matches(
|
|
|
|
in: time,
|
|
|
|
range: NSRange(time.startIndex..., in: time)
|
|
|
|
)
|
|
|
|
|
|
|
|
guard let match = results.first else {
|
|
|
|
return [:]
|
|
|
|
}
|
|
|
|
|
|
|
|
var components: [String: String] = [:]
|
|
|
|
|
|
|
|
for name in ["hours", "minutes", "seconds"] {
|
|
|
|
let matchRange = match.range(withName: name)
|
|
|
|
|
|
|
|
if let substringRange = Range(matchRange, in: time) {
|
|
|
|
let capture = String(time[substringRange])
|
|
|
|
components[name] = capture
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return components
|
|
|
|
}
|
|
|
|
|
|
|
|
private var timeRegularExpression: NSRegularExpression {
|
|
|
|
try! NSRegularExpression(
|
|
|
|
pattern: "(?:(?<hours>[0-9+])+h)?(?:(?<minutes>[0-9]+)m)?(?:(?<seconds>[0-9]*)s)?",
|
|
|
|
options: .caseInsensitive
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|