有没有办法在音频 B 也开始播放后修复音频 A 的播放?

Posted

技术标签:

【中文标题】有没有办法在音频 B 也开始播放后修复音频 A 的播放?【英文标题】:Is there a way to fix audio A from playing after audio B has also started playing? 【发布时间】:2019-07-09 21:56:05 【问题描述】:

我正在构建一个应用程序,用户可以在其中选择要播放的音频文件。这通常有效,即使屏幕锁定也能播放。问题是,在用户更改音频文件后,第一个音频文件仍在后台播放,并与用户想要收听的文件重叠。

let player: AVPlayer = 
        let avPlay = AVPlayer()
        avPlay.allowsExternalPlayback = false
        avPlay.automaticallyWaitsToMinimizeStalling = false
        return avPlay
    ()

fileprivate func setupLockScreenCurrentTime()
        var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo
//      nowPlayingInfo = nil

        guard let currentItem = player.currentItem elsereturn
        let durationInSecs = CMTimeGetSeconds(currentItem.duration)
//      let elapsed = CMTimeGetSeconds(player.currentTime())
        nowPlayingInfo?[MPMediaItemPropertyPlaybackDuration] = durationInSecs

        MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
    
fileprivate func playSermon()
        let credential = URLCredential(user: "1234user" , password: "password", persistence: .forSession)
        let protectionSpace = URLProtectionSpace(host: "example.com", port: 443, protocol: "https", realm: "Restricted", authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
        URLCredentialStorage.shared.setDefaultCredential(credential, for: protectionSpace)
        let ssurl = SermonHelper.sharedInstance.url
        let urlNew:String = ssurl.replacingOccurrences(of: " ", with: "%20")
        guard let url = URL(string: urlNew) else return
        let playerItem = AVPlayerItem(url: url)
        player.replaceCurrentItem(with: playerItem)
        player.isMuted = false
        player.play()
        observePlayerCurrentTime()

    

fileprivate func setupRemoteControl()
        UIApplication.shared.beginReceivingRemoteControlEvents()

        let commandCenter = MPRemoteCommandCenter.shared()
        commandCenter.playCommand.isEnabled = true
        commandCenter.playCommand.addTarget  (_) -> MPRemoteCommandHandlerStatus in
            self.player.play()
            self.enlargeEpisodeImageView()
            self.playPauseButton.setImage(UIImage(named: "my_pause2"), for: .normal)
            self.setupElapsedTime(rate: 1)
            return .success
        

        commandCenter.pauseCommand.isEnabled = true
        commandCenter.pauseCommand.addTarget  (_) -> MPRemoteCommandHandlerStatus in
            self.player.pause()
            self.shrinkEpisodeImageView()
            self.playPauseButton.setImage(UIImage(named: "my_play2"), for: .normal)
            self.setupElapsedTime(rate: 0)
            return .success
        

        commandCenter.togglePlayPauseCommand.isEnabled = true
        commandCenter.togglePlayPauseCommand.addTarget  (_) -> MPRemoteCommandHandlerStatus in
            if self.player.timeControlStatus == .playing 
                self.player.pause()
                self.shrinkEpisodeImageView()
                self.playPauseButton.setImage(UIImage(named: "my_play2"), for: .normal)
            
            else 
                self.player.play()
                self.enlargeEpisodeImageView()
                self.playPauseButton.setImage(UIImage(named: "my_pause2"), for: .normal)
            
            return .success
        
        commandCenter.skipForwardCommand.isEnabled = true
        commandCenter.skipForwardCommand.addTarget  (_) -> MPRemoteCommandHandlerStatus in
            self.seekToCurrentTime(delta: 15)
            let t = CMTimeAdd(self.player.currentTime(), CMTimeMake(15, 1))
            MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds(t)
            return .success
        

        commandCenter.skipBackwardCommand.isEnabled = true
        commandCenter.skipBackwardCommand.addTarget  (_) -> MPRemoteCommandHandlerStatus in
            self.seekToCurrentTime(delta: -15)
            let n = CMTimeAdd(self.player.currentTime(), CMTimeMake(-15, 1))
            MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds(n)
            return .success
        
    

我希望正在播放的音频被用户选择的新音频文件替换,但我从同时播放的两个文件中获取音频。

【问题讨论】:

【参考方案1】:

当您在将当前声音替换为playSermon() 中的新声音之前停止播放当前声音时,代码中的任何位置都不会显示。尝试这样做。这很可能会解决您的问题。

【讨论】:

我假设在playSermon() 中使用player.replaceCurrentItem(with: playerItem) 可以实现这一目标。如果不是,你的建议是什么?谢谢。 在你替换 playSermon() 中的项目之前暂停播放器。 您的意思是即使在您暂停播放器后声音仍在播放?如果您确实省略了替换代码会怎样? 我认为问题在于,无论何时初始化视图控制器,都会创建一个 AVPlayer 的新实例。有没有一种安全的方法可以阻止这种情况发生。 那么你不应该在你的视图控制器中实例化 AVPlayer。我通常做的是创建一个类来处理 AVPlayer 的创建和销毁,其中包含一个指向我想要控制的所有 AVPlayer 的数组。

以上是关于有没有办法在音频 B 也开始播放后修复音频 A 的播放?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在播放后暂停音频? [复制]

iOS音频问题通用配置

iPhone声音:在播放时调整音频文件的播放速度

有没有办法制作只能播放一次的音频文件?

为啥对方接听电话后会自动播放音频?

需要帮助修复我的javascript“for循环”以播放音频播放列表[重复]