如何检测AVPlayerViewController中用户的字幕选择设置
好问题!我之前在做视频播放项目的时候刚好研究过这个,完全可以通过AVPlayerViewController和AVFoundation的相关API来检测用户的字幕选择,下面给你一步步拆解:
检测AVPlayerViewController的字幕设置方法
核心思路
AVPlayerViewController的preferredMediaSelection属性是关键,它存储了用户对音轨、字幕等媒体选项的选择。我们可以通过这个属性结合AVFoundation的AVMediaSelectionGroup、AVMediaSelectionOption类来判断用户的字幕状态(关闭、自动、特定语言)。
具体实现步骤
1. 获取字幕媒体组
首先需要从当前播放的资源中获取字幕对应的媒体组(对应AVMediaCharacteristicLegible类型),如果资源本身没有字幕,这一步会返回nil,需要提前判断。
2. 判断字幕选择状态
拿到字幕组后,我们可以对比用户选择的选项和系统提供的“关闭”选项、默认(自动)选项,来区分不同状态:
func checkSubtitleSelection(for playerVC: AVPlayerViewController) { guard let player = playerVC.player, let asset = player.currentItem?.asset else { print("当前没有播放的媒体资源") return } // 获取字幕对应的媒体组 guard let legibleGroup = asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else { print("该媒体没有字幕资源") return } // 获取用户当前选择的字幕选项 let selectedOption = playerVC.preferredMediaSelection.selectedMediaOption(in: legibleGroup) // 1. 判断是否为「关闭字幕」 let closedCaptionOption = AVMediaSelectionOption.mediaSelectionOptionWithoutMediaCharacteristics([.legible], mediaGroup: legibleGroup) if selectedOption == closedCaptionOption { print("用户选择了关闭字幕") return } // 2. 判断是否为「自动模式」 if selectedOption == legibleGroup.defaultMediaSelectionOption { print("用户选择了自动字幕模式") return } // 3. 特定语言字幕的情况 if let locale = selectedOption.locale { print("用户选择了字幕语言:\(locale.identifier)(比如zh-CN、en-US)") } else if let displayName = selectedOption.displayName { print("用户选择了字幕:\(displayName)") } }
3. 监听字幕设置的变化
如果需要实时监听用户在播放过程中更改字幕设置的操作,可以通过KVO监听preferredMediaSelection的变化:
// 在合适的地方添加监听(比如viewDidLoad) playerViewController.addObserver(self, forKeyPath: #keyPath(AVPlayerViewController.preferredMediaSelection), options: [.new], context: nil) // 实现KVO回调方法 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == #keyPath(AVPlayerViewController.preferredMediaSelection), let playerVC = object as? AVPlayerViewController else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } // 调用检测方法 checkSubtitleSelection(for: playerVC) } // 记得在销毁时移除监听 deinit { playerViewController.removeObserver(self, forKeyPath: #keyPath(AVPlayerViewController.preferredMediaSelection)) }
注意事项
- 有些媒体资源的“自动”选项可能会根据系统语言自动匹配字幕,这时候
defaultMediaSelectionOption就是对应系统语言的字幕选项,判断逻辑依然有效。 - 如果需要兼容更早版本的iOS,注意部分API的可用性(比如
mediaSelectionOptionWithoutMediaCharacteristics:是iOS 9+可用)。 - 字幕选项的
displayName是本地化后的名称,比如中文环境下会显示“中文”“英文”,而locale.identifier是标准的语言代码,更适合做逻辑判断。
内容的提问来源于stack exchange,提问作者picciano




