使用 MPRemoteCommandCenter 为 AVPlayer 和 AVAudioPlayer 添加当前时间和持续时间的位置
Posted
技术标签:
【中文标题】使用 MPRemoteCommandCenter 为 AVPlayer 和 AVAudioPlayer 添加当前时间和持续时间的位置【英文标题】:Where to Add Current Time and Duration Time For AVPlayer and AVAudioPlayer using MPRemoteCommandCenter 【发布时间】:2022-01-10 12:04:44 【问题描述】:在我的应用程序的屏幕上,我有一个用于音乐的 AVAudioPlayer 和一个用于视频的 AVPlayer。用户可以换出不同的歌曲和不同的视频,但一次只能播放一首。他们可以在 avPlayer 上播放 audioPlayer 或观看视频。
我的 MPRemoteCommandCenter 在使用暂停/播放/ff/倒带时都可以正常工作。问题是我无法在锁定屏幕上显示当前时间或持续时间。我试过this,但没有说明将代码放在哪里。
这是我尝试过的,这样每次用户切换歌曲或视频时,我都会获得新项目的所有可用数据:
音频-
do
audioPlayer = try AVAudioPlayer(contentsOf: audioTrack)
audioPlayer?.delegate = self
audioPlayer?.prepareToPlay()
audioPlayer?.play()
setupNowPlayingForAudio()
catch
func setupNowPlayingForAudio()
guard let audioPlayer = audioplayer else return
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "My App Name"
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = Float(audioPlayer.currentTime)
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = Float(audioPlayer.duration)
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = audioPlayer.rate
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
视频-
playerStatusObserver = player?.observe(\.currentItem?.status, options: [.new, .old])
switch (player.status)
case .readyToPlay:
player?.play()
setupNowPlayingForVideo()
func setupNowPlayingForVideo()
guard let player = player, let playerItem = player.currentItem else return
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "My App Name"
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
MPRemoteCommandCenter 与 AVAudiosession 一起在 viewDidLoad 中设置
【问题讨论】:
【参考方案1】:我关注了这个answer,它说你必须将它添加到任何暂停/播放/ff/倒带按钮、滑块和任何监听播放器播放/停止的观察者。这是我的做法。这在锁定屏幕上对我来说很好。
这里是我为AudioPlayer
使用以下函数的地方-
do
audioPlayer = try AVAudioPlayer(contentsOf: audioTrack)
// ...
audioPlayer?.play()
setupNowPlaying(musicPlayer: audioPlayer)
catch
func audioPlayerPausePlayButton()
// ...
setupNowPlaying(musicPlayer: audioPlayer)
func audioPlayerFastFowardAndRewindButton()
// ... ff or rewind functions
setupNowPlaying(musicPlayer: audioPlayer)
这是我为AVPlayer
使用以下函数的地方-
playerStatusObserver = player?.observe(\.currentItem?.status, options: [.new, .old]) // ...
switch (player.status)
case .readyToPlay:
// ... this should occur on the MainQueue
self?.player?.play()
self?.setupNowPlaying(videoPlayer: self?.player)
// .. I also added it to any other observers that listen to the player stopping
func videoPlayerPausePlayButton()
// ...
setupNowPlaying(videoPlayer: player)
func videoPlayerFastFowardAndRewindButton()
// ...
player?.seek(to: whateverSeekTime) [weak self](_) in
self?.setupNowPlaying(videoPlayer: self?.player)
CommandCenter 在锁定屏幕上显示的字典值
func setupNowPlaying(musicPlayer: AVAudioPlayer? = nil, videoPlayer: AVPlayer? = nil)
var nowPlayingInfo = [String : Any]()
// audio
if let musicPlayer = musicPlayer, let musicUrl = musicPlayer.url
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = musicUrl
nowPlayingInfo[MPMediaItemPropertyTitle] = musicUrl.lastPathComponent
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.audio.rawValue
let currentTime: TimeInterval = musicPlayer.currentTime
let musicCurrentTimeCMTime = CMTime(seconds: currentTime, preferredTimescale: 1000)
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds(musicCurrentTimeCMTime)
let musicDuration: TimeInterval = musicPlayer.duration
let musicDurationCMTime = CMTime(seconds: musicDuration, preferredTimescale: 1000)
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = CMTimeGetSeconds(musicDurationCMTime)
if musicPlayer.isPlaying
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 1
else
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 0
// video
if let videoPlayer = videoPlayer, let currentItem = videoPlayer.currentItem
if let videoAsset = currentItem.asset as? AVURLAsset
let videoUrl = videoAsset.url
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = videoUrl
nowPlayingInfo[MPMediaItemPropertyTitle] = videoUrl.lastPathComponent
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.video.rawValue
if let videoDuration: CMTime = videoPlayer.currentItem?.duration
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = CMTimeGetSeconds(videoDuration)
let videoCurrentTime: CMTime = videoPlayer.currentTime()
let videoCurrentTimeAsSecs = CMTimeGetSeconds(videoCurrentTime)
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = videoCurrentTimeAsSecs
print("videoCurrentTimeAsSecs: ", videoCurrentTimeAsSecs)
if videoPlayer.isPlaying
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 1
else
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 0
nowPlayingInfo[MPMediaItemPropertyTitle] = "Your App Name"
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
【讨论】:
以上是关于使用 MPRemoteCommandCenter 为 AVPlayer 和 AVAudioPlayer 添加当前时间和持续时间的位置的主要内容,如果未能解决你的问题,请参考以下文章
使用 MPRemoteCommandCenter 时未调用播放/暂停回调
使用 MPRemoteCommandCenter 为 AVPlayer 和 AVAudioPlayer 添加当前时间和持续时间的位置
如何从 MPRemoteCommandCenter 禁用所有 MPRemoteCommand 对象
iOS 13+ 应用程序的 AVAudioPlayer AVPlayer AVQueuePlayer MPMusicPlayerController MPRemoteCommandCenter MPN