【问题标题】:AVAudioSession switching between mixed and non-mixed modesAVAudioSession 在混合和非混合模式之间切换
【发布时间】:2015-10-28 08:44:49
【问题描述】:

我有一个可以显示视频的应用,我想要以下行为。

  • 当视频首次出现在屏幕上并开始播放时,其音频应与可能已经在播放的其他应用程序的音频混合。例如,如果用户正在收听 Spotify,他们应该会听到来自 Spotify 和正在播放的视频的音频。

  • 如果用户点击特定按钮,其他应用的音频应静音,以便仅播放视频中的音频。

  • 如果用户再次点击该按钮,来自其他应用的音频应该会恢复,并且视频的音频应该与来自其他应用的音频再次混合。

基本上,我希望能够在“混合”和“非混合”之间切换应用的音频模式。

这里有一些代码显示了我如何修改AVAudioSession 以尝试获得此功能。

开启混音模式

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryAmbient
         withOptions:AVAudioSessionCategoryOptionMixWithOthers
               error:nil];
[session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

关闭混音模式

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback
         withOptions:0
               error:nil];
[session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

我遇到的问题是,在之前关闭音频混合后打开音频混合,并没有通知其他应用他们可以再次恢复播放音频。我真的,真的很想要那种行为。这是不可能的事情吗?

似乎通知其他应用可以恢复的唯一方法是将我的应用的音频会话设置为“非活动”。不幸的是,在播放视频时这样做会导致控制台中打印出一条警告,说我应该在停用音频会话之前停止播放音频。这也有基本破坏 AVPlayer 的效果,因为它不能再播放任何音频了。

有人知道如何解决这些问题吗?任何解决方案都会受到欢迎,即使是非常复杂或使用私有 API 的解决方案。

【问题讨论】:

    标签: ios video avfoundation avplayer avaudiosession


    【解决方案1】:

    因此,正如其他答案指出的那样,您可以“暂停”另一个应用程序的音频。但是,您可以使用.duckWithOthers 将其关闭。音频完成后,您可以将该选项重置回.mixWithOthers 并通知其他应用它们的音量可以恢复到完整级别。

    假设您的音频在您的 ViewController 出现时开始,并在您的 ViewController 消失时停止。然后就可以使用下面的代码了:

    override func viewWillAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        // Use duckOthers so the audio in your VC is slightly louder than the background audio such as Spotify
        updateAVAudioSessionOptions(to: .duckOthers)
      }
    
      override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    
        // Reset to mixWithOthers since we are no longer playing audio
        updateAVAudioSessionOptions(to: .mixWithOthers)
    
        // probably a good idea to stop the audio as well
        player.pause() 
      }
    
      private func updateAVAudioSessionOptions(to options: AVAudioSession.CategoryOptions) {
        do {
          try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: options)
    
          if options == .mixWithOthers {
            // Notify other apps that they volume can be restored to the full level
            try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
          }
    
        } catch let error {
          print("Error: \(error)")
        }
      }
    

    【讨论】:

      【解决方案2】:

      我认为你运气不好。即使AVAudioSessionCategoryOptionDuckOthers 听起来应该适合您的用例,它也要求您停用会话以使其他应用的音量恢复正常,但正如您所见,这会导致错误。

      【讨论】:

      • 是的,我担心是这样。以某种方式欺骗 iOS 将“中断恢复”通知发送给其他进程怎么样?
      • 你认为扩展有自己的音频会话吗?
      【解决方案3】:

      也许您应该在“关闭混合模式”块中将“是”更改为“否”。

      [session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
      

      【讨论】:

      • 问题是,我无法在播放视频时将音频会话设置为非活动状态。 AVPlayer 对此并不酷,之后它不会播放声音。您需要暂停并再次播放视频才能从中恢复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-20
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 2018-05-14
      • 1970-01-01
      相关资源
      最近更新 更多