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加群领取哦~