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

在AppRTC iOS示例中,如何将音频重定向到扬声器?,ios,audio,avfoundation,webrtc,apprtcdemo,Ios,Audio,Avfoundation,Webrtc,Apprtcdemo,我正在尝试将音频重定向到中的扬声器 我试过: AVAudioSession* session = [AVAudioSession sharedInstance]; //error handling BOOL success; NSError* error; //set the audioSession category. //Needs to be Record or PlayAndRecord to use audioRouteOverride: success = [sessio

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

我试过:

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");

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

我最终找到了解决方案

原因是您需要将
AVAudioSession
类别设置为
AVAudioSessionCategoryPlayback
。但由于某种原因,在建立webRTC调用后,它被设置回
AVAudioSessionCategoryPlayAndRecord
。 最后,我决定为
AVAudioSessionRouteChangeNotification添加观察员,并在每次检测到不需要的类别更改时切换到
AVAudioSessionCategoryPlayback

一点黑客解决方案,但最终奏效了。你可以检查一下。

我用这个解决方案解决了它。 只需收听音频会话RouteChangeNotification

[[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;
  }
}
这是正确的。尽管当您启用覆盖时,这实际上会覆盖音频输出,即使用户插入耳机。当用户使用耳机时,通过扬声器播放音频并没有多大意义。为此,请使用以下代码:

- (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];
}

似乎仍然是个问题,丰乐的回答对我有效。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
    }
}

对于来到这里的任何人来说,在Swift中寻找一种解决方案,它也能解释(BT-)耳机带来的变化。下面的示例(Swift 5)就是这样做的。
部分采纳自@Teivaz

@objc func HandlerRouteChange(通知:通知){
guard let info=notification.userInfo,

将value=info[AVAudioSessionRouteChangeReasonKey]设为UInt, 让reason=AVAudioSession.RouteChangeReason(rawValue:value)else{return} 切换原因{ 案例.类别变更: 请尝试?AVAudioSession.sharedInstance()。重写音频端口(.speaker) 案例。旧设备不可用: 请尝试?AVAudioSession.sharedInstance()。重写音频端口(.speaker) 违约: l、 调试(“其他”) } }
您找到解决问题的方法了吗?“我现在面临着和你一样的问题。”约西布。对我不起作用…终于有了一个对我起作用的解决方案。非常感谢。这个解决方案很危险。每次有人更改路由时都会调用此通知,换句话说,它可能会在以后导致潜在问题。“AVAudioSessionRouteChangeReasonCategoryChange”而不是“AvaudioSessionRouteChangeReasonRouteConfiguration Change”修复了我的问题。谢谢