
1、起因
在 APP 中用 OWT(Open WebRTC Tookit) 实现直播功能时,发现,只要加入到创建好的房间,订阅了房间中的流之后,就会获取用户的麦克风权限。这样对只是想看直播并不想上麦讲话的用户很不友好,我们想要的效果是,只有用户上麦时才去获取麦克风权限,其他时间不获取麦克风权限。
2、原因
翻阅源码发现,在WebRTC官方SDK中,如果为RTCPeerConnection添加了AudioTrack,WebRTC就会尝试去初始化音频的输入输出。 Audio通道建立成功之后WebRTC会自动完成声音的采集传输播放。 RTCAudioSession提供了一个useManualAudio属性,将它设置为true,那么音频的输入输出开关将由isAudioEnabled属性控制。 但是,isAudioEnabled只能同时控制音频的输入输出,无法分开控制。 我们的产品现在需要关闭麦克风的功能,在只是订阅流的时候,不需要麦克风。需要推流(连麦等功能),必须要使用麦克风的时候,才需要去获取麦克风权限。
从WebRTC官方回复来看,WebRTC 是专门为全双工VoIP通话应用而设计的,所以必须是需要初始化麦克风的,而且是没有提供修改的API。

3、解决方案
目前官方没有提供API,底层相关代码还没有实现
// sdk/objc/native/src/audio/audio_device_ios.mm
int32_t AudioDeviceIOS::SetMicrophoneMute(bool enable) {
RTC_NOTREACHED() << "Not implemented";
return -1;
}
分析源码,可以在VoiceProcessingAudioUnit中找到Audio Unit的使用。 OnDeliverRecordedData回调函数拿到音频数据后通过VoiceProcessingAudioUnitObserver通知给AudioDeviceIOS
// sdk/objc/native/src/audio/voice_processing_audio_unit.mm
OSStatus VoiceProcessingAudioUnit::OnDeliverRecordedData(
void* in_ref_con,
AudioUnitRenderActionFlags* flags,
const AudioTimeStamp* time_stamp,
UInt32 bus_number,
UInt32 num_frames,
AudioBufferList* io_data) {
VoiceProcessingAudioUnit* audio_unit =
static_cast<VoiceProcessingAudioUnit*>(in_ref_con);
return audio_unit->NotifyDeliverRecordedData(flags, time_stamp, bus_number,
num_frames, io_data);
}
3.1 I/O Unit的特征

上图I/O Unit有两个element,但它们是独立的,例如,你可以根据应用程序的需要使用enable I/O属性(kAudioOutputUnitProperty_EnableIO)来独立启用或禁用某个element。每个element都有Input scope和Output scope。
-
I/O Unit的element 1连接音频的输入硬件,在上图中由麦克风表示。开发者只能访问控制Output scope -
I/O Unit的element 0连接音频的输出硬件,在上图中由扬声器表示。开发者只能访问控制Input scope
input element is element 1(单词Input的字母“I”,类似1) output element is element 0 (单词Output的字母“O”,类型0)
【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~


通过分析Audio Unit发现,其实要关闭麦克风也很简单,只需要在初始化音频单元配置的时候关闭掉输入。下面代码新增了一个isMicrophoneMute 变量,这个变量在RTCAudioSessionConfiguration中设置。
3.2 代码示例:
c++
// sdk/objc/native/src/audio/voice_processing_audio_unit.mm
bool VoiceProcessingAudioUnit::Init() {
RTC_DCHECK_EQ(state_, kInitRequired);
// Create an audio component description to identify the Voice Processing
// I/O audio unit.
AudioComponentDescription vpio_unit_description;
vpio_unit_description.componentType = kAudioUnitType_Output;
vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple;
&

本文探讨了在使用WebRTC时如何避免在订阅流时获取麦克风权限的问题。起因是APP在加入直播房间并订阅流后会自动请求麦克风权限,而目标是仅在用户上麦时才请求。原因是WebRTC SDK在添加AudioTrack时会初始化音频输入输出。解决方案是通过分析源码,控制音频单元的输入,在初始化时关闭麦克风输入,并实现动态连麦与下麦功能,通过消息传递控制音频状态。

3978

被折叠的 条评论
为什么被折叠?



