audio track please work holy moly

This commit is contained in:
Francesco 2025-06-08 16:53:42 +02:00
parent a66ac56246
commit eb70b83bb1

View file

@ -2105,9 +2105,13 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
return firstHeight > secondHeight return firstHeight > secondHeight
} }
self.qualities = sortedQualities self.qualities = sortedQualities
self.audioTracks = audioTracks
self.audioTrackButton.isHidden = self.audioTracks.isEmpty if !audioTracks.isEmpty {
self.audioTrackButton.menu = self.audioTrackSelectionMenu() self.audioTracks = audioTracks
self.audioTrackButton.isHidden = false
self.audioTrackButton.menu = self.audioTrackSelectionMenu()
}
completion() completion()
} }
}.resume() }.resume()
@ -2144,6 +2148,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
let currentTime = player.currentTime() let currentTime = player.currentTime()
let wasPlaying = player.rate > 0 let wasPlaying = player.rate > 0
let currentRate = player.rate
let audioTrackToApply = lastSelectedAudioTrack let audioTrackToApply = lastSelectedAudioTrack
player.pause() player.pause()
@ -2162,28 +2167,31 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
let asset = AVURLAsset(url: url, options: ["AVURLAssetHTTPHeaderFieldsKey": request.allHTTPHeaderFields ?? [:]]) let asset = AVURLAsset(url: url, options: ["AVURLAssetHTTPHeaderFieldsKey": request.allHTTPHeaderFields ?? [:]])
let playerItem = AVPlayerItem(asset: asset) let playerItem = AVPlayerItem(asset: asset)
asset.loadValuesAsynchronously(forKeys: ["playable"]) { [weak self] in asset.loadValuesAsynchronously(forKeys: ["playable", "tracks"]) { [weak self] in
DispatchQueue.main.async { DispatchQueue.main.async {
guard let self = self else { return } guard let self = self else { return }
let observer = playerItem.observe(\.status, options: [.new]) { [weak self] item, _ in
let statusObserver = playerItem.observe(\.status, options: [.new]) { [weak self] item, _ in
guard let self = self else { return } guard let self = self else { return }
if item.status == .readyToPlay { if item.status == .readyToPlay {
if let audioTrackName = audioTrackToApply, self.player.seek(to: currentTime) { [weak self] _ in
let group = item.asset.mediaSelectionGroup(forMediaCharacteristic: .audible), guard let self = self else { return }
let option = group.options.first(where: { $0.displayName == audioTrackName }) {
item.select(option, in: group) if let audioTrackName = audioTrackToApply {
} self.applyAudioTrack(named: audioTrackName, to: item)
}
self.player.seek(to: currentTime)
if wasPlaying { if wasPlaying {
self.player.play() self.player.playImmediately(atRate: currentRate)
}
} }
} }
} }
self.player.replaceCurrentItem(with: playerItem)
self.player.replaceCurrentItem(with: playerItem)
self.currentQualityURL = url self.currentQualityURL = url
UserDefaults.standard.set(urlString, forKey: "lastSelectedQuality") UserDefaults.standard.set(urlString, forKey: "lastSelectedQuality")
self.qualityButton.menu = self.qualitySelectionMenu() self.qualityButton.menu = self.qualitySelectionMenu()
@ -2191,8 +2199,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
DropManager.shared.showDrop(title: "Quality: \(selectedQuality)", subtitle: "", duration: 0.5, icon: UIImage(systemName: "eye")) DropManager.shared.showDrop(title: "Quality: \(selectedQuality)", subtitle: "", duration: 0.5, icon: UIImage(systemName: "eye"))
} }
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
observer.invalidate() statusObserver.invalidate()
} }
} }
} }
@ -2230,6 +2238,29 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
return UIMenu(title: "Video Quality", children: menuItems) return UIMenu(title: "Video Quality", children: menuItems)
} }
private func applyAudioTrack(named name: String, to playerItem: AVPlayerItem) {
if let group = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .audible),
let option = group.options.first(where: { $0.displayName == name }) {
playerItem.select(option, in: group)
Logger.shared.log("Applied audio track: \(name)", type: "Debug")
return
}
if let group = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .audible),
let savedTrack = audioTracks.first(where: { $0.name == name }) {
for option in group.options {
if option.displayName.contains(savedTrack.name) ||
(option.locale?.identifier.contains(savedTrack.groupID) == true) {
playerItem.select(option, in: group)
Logger.shared.log("Applied similar audio track: \(option.displayName)", type: "Debug")
return
}
}
}
Logger.shared.log("Could not find matching audio track: \(name)", type: "Warning")
}
private func checkForHLSStream() { private func checkForHLSStream() {
guard let url = URL(string: streamURL) else { return } guard let url = URL(string: streamURL) else { return }
let streamType = module.metadata.streamType.lowercased() let streamType = module.metadata.streamType.lowercased()
@ -2241,8 +2272,11 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
parseM3U8(url: url) { [weak self] in parseM3U8(url: url) { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if let last = UserDefaults.standard.string(forKey: "lastSelectedQuality"),
self.qualities.contains(where: { $0.1 == last }) { if self.qualities.count > 1,
let last = UserDefaults.standard.string(forKey: "lastSelectedQuality"),
self.qualities.contains(where: { $0.1 == last }),
last != url.absoluteString {
self.switchToQuality(urlString: last) self.switchToQuality(urlString: last)
} }
@ -2256,6 +2290,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
} else { } else {
isHLSStream = false isHLSStream = false
qualityButton.isHidden = true qualityButton.isHidden = true
audioTrackButton.isHidden = true
updateMenuButtonConstraints() updateMenuButtonConstraints()
} }
} }