[英]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.