如何在 AppRTC iOS 示例中将音频重定向到扬声器?

Posted

技术标签:

【中文标题】如何在 AppRTC iOS 示例中将音频重定向到扬声器?【英文标题】:How to redirect audio to speakers in the AppRTC iOS example? 【发布时间】:2014-07-06 11:58:23 【问题描述】:

我正在尝试将音频重定向到 AppRTC ios example 中的扬声器。

我试过了:

AVAudioSession* session = [AVAudioSession sharedInstance];

//error handling
BOOL success;
NSError* error;

//set the audioSession category. 
//Needs to be Record or PlayAndRecord to use audioRouteOverride:  

success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                         error:&error];

if (!success)  NSLog(@"AVAudioSession error setting category:%@",error);

//set the audioSession override
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
                                      error:&error];
if (!success)  NSLog(@"AVAudioSession error overrideOutputAudioPort:%@",error);

//activate the audio session
success = [session setActive:YES error:&error];
if (!success) NSLog(@"AVAudioSession error activating: %@",error);
else NSLog(@"audioSession active");

没有错误,但它不起作用。我该如何解决这个问题?

【问题讨论】:

您找到解决问题的方法了吗?我现在和你面临同样的问题。 @JosipB。 github.com/alongubkin/audiotoggle 对我不起作用... 【参考方案1】:

我通过解决方案解决了它。 只听AVAudioSessionRouteChangeNotification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didSessionRouteChange:) name:AVAudioSessionRouteChangeNotification object:nil];

并使用 didSessionRouteChange 选择器,如下所示:

- (void)didSessionRouteChange:(NSNotification *)notification

  NSDictionary *interuptionDict = notification.userInfo;
  NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];

  switch (routeChangeReason) 
      case AVAudioSessionRouteChangeReasonCategoryChange: 
          // Set speaker as default route
          NSError* error;
          [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
      
      break;

    default:
      break;
  

【讨论】:

终于找到了一个适合我的解决方案。非常感谢。 这个解决方案很危险。每次有人更改路线时都会调用此通知,换句话说,它可能会在以后导致潜在的问题。【参考方案2】:

似乎仍然是一个问题,phuongle 答案对我有用。 Swift 4 版本:

NotificationCenter.default.addObserver(forName: .AVAudioSessionRouteChange, object: nil, queue: nil, using: routeChange)    

private func routeChange(_ n: Notification) 
    guard let info = n.userInfo,
        let value = info[AVAudioSessionRouteChangeReasonKey] as? UInt,
        let reason = AVAudioSessionRouteChangeReason(rawValue: value) else  return 
    switch reason 
    case .categoryChange: try? AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
    default: break
    

【讨论】:

【参考方案3】:

对于任何来到这里的人,都在 Swift 中寻找解决方案,该解决方案还考虑了从 (BT-) 耳机返回的变化。下面的示例 (Swift 5) 就是这样做的。 部分来自@Teivaz

@objc func handleRouteChange(notification: Notification) 
    guard let info = notification.userInfo,
        let value = info[AVAudioSessionRouteChangeReasonKey] as? UInt,
        let reason = AVAudioSession.RouteChangeReason(rawValue: value) else  return 

    switch reason 
    case .categoryChange:
        try? AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
    case .oldDeviceUnavailable:
        try? AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
    default:
        l.debug("other")
    

【讨论】:

【参考方案4】:

我最终找到了解决办法。

原因是您需要将AVAudioSession 类别设置为AVAudioSessionCategoryPlayback。但由于某种原因,在建立 webRTC 调用后,它被设置回AVAudioSessionCategoryPlayAndRecord。 最后,我决定为AVAudioSessionRouteChangeNotification 添加观察者,并在每次检测到不需要的类别更改时切换到AVAudioSessionCategoryPlayback。 一些黑客解决方案,但最终奏效了。您可以查看here。

【讨论】:

【参考方案5】:

phuongle's answer 是正确的。虽然当您启用覆盖时,即使用户插入耳机,这实际上也会覆盖音频输出。当用户使用耳机时,通过扬声器播放音频没有多大意义。为此,请使用以下代码:

- (void)didSessionRouteChange:(NSNotification *)notification

    NSDictionary *interuptionDict = notification.userInfo;
    const NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];

    if (routeChangeReason == AVAudioSessionRouteChangeReasonRouteConfigurationChange) 
        [self enableLoudspeaker];
    


- (void)enableLoudspeaker 
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    AVAudioSessionCategoryOptions options = audioSession.categoryOptions;
    if (options & AVAudioSessionCategoryOptionDefaultToSpeaker) return;
    options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
    [audioSession setActive:YES error:nil];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil];

【讨论】:

"AVAudioSessionRouteChangeReasonCategoryChange" 而不是 "AVAudioSessionRouteChangeReasonRouteConfigurationChange" 解决了我的问题。谢谢

以上是关于如何在 AppRTC iOS 示例中将音频重定向到扬声器?的主要内容,如果未能解决你的问题,请参考以下文章

覆盖 iOS 音频输出

如何在python中将重定向url保存到csv文件

如何在 Laravel 4 中将一个路由重定向到 HTTPS,将所有其他路由重定向到 HTTP?

如何在python中将请求重定向到不同的url

如何使用 JACK 将音频输出重定向到输入?

如何在 Django 分页中将 ?page=1 重定向到 /?