簡體   English   中英

如何將音頻重定向到 AppRTC iOS 示例中的揚聲器?

[英]How to redirect audio to speakers in the AppRTC iOS example?

我正在嘗試將音頻重定向到AppRTC iOS 示例中的揚聲器。

我試過了:

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

沒有錯誤,但它不起作用。 我怎樣才能解決這個問題?

我通過解決方案解決了它。 只聽 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;
  }
}

似乎仍然是一個問題,phuongle answer 對我有用。 斯威夫特 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 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")
    }
}

我最終找到了解決方案。

原因是您需要將AVAudioSession類別設置為AVAudioSessionCategoryPlayback 但是由於某種原因,在建立 webRTC 調用后,它被設置回AVAudioSessionCategoryPlayAndRecord 最后,我決定為AVAudioSessionRouteChangeNotification添加觀察者,並在每次檢測到不需要的類別更改時切換到AVAudioSessionCategoryPlayback 一些黑客解決方案,但最終奏效了。 你可以在這里查看

phuongle 的回答是正確的。 盡管當您啟用覆蓋時,即使用戶插入耳機,這實際上也會覆蓋音頻輸出。 當用戶使用耳機時,通過揚聲器播放音頻沒有多大意義。 為此,請使用以下代碼:

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

我已經面對這個問題一段時間了,我找到了解決方案。 問題是我們在 WebRTC 完成配置之前設置 AVAudioSessionCategory 引起的。 所以在開始本地視頻采集后設置AVAudioSessionCategory。

let rtcAudioSession = RTCAudioSession.sharedInstance()
let capturer = self.videoCapturer as? RTCCameraVideoCapturer

// set your captureDevice, frameRate
// ......

capturer.startCapture(with: captureDevice, format: format, fps: frameRate) { error in
     if error != nil {
       debugPrint("Capture error : ", error?.localizedDescription as Any)
     }
    
     // set local video renderer
     self.localVideoTrack?.add(renderer)
            
     // set audio configuration
     rtcAudioSession.lockForConfiguration()
     try? self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.defaultToSpeaker, .allowBluetoothA2DP, .allowBluetooth])
     try? self.rtcAudioSession.setMode(AVAudioSession.Mode.videoChat.rawValue)
     try? self.rtcAudioSession.overrideOutputAudioPort(.speaker)
     try? self.rtcAudioSession.setActive(true)
     rtcAudioSession.unlockForConfiguration()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM