做錄音時首先需要獲取本地采集的pcm數(shù)據(jù)和所有遠端用戶合成后的pcm數(shù)據(jù),也就是播放時投遞給揚聲器的pcm數(shù)據(jù)景馁,本文講解一下如何獲取webrtc的原始音頻數(shù)據(jù)。
webrtc版本說明
本文使用的webrtc api依賴于webrtc分支版本<=branch57
在branch57以及以前的版本應(yīng)該都能測試通過绰精。
在branch>=58中VoEExternalMedia可能會被移除。
使用的接口
使用的接口為webrtc::VoEExternalMedia類
所在文件為:webrtc/voice_engine/include/voe_external_media.h
首先需要實現(xiàn)一個數(shù)據(jù)回調(diào)使用的callback類:
class AudioMixDataCallBack :public webrtc::VoEMediaProcess
{
public:
virtual void Process(int channel,
webrtc::ProcessingTypes type,
int16_t audio10ms[],
size_t length,
int samplingFreq,
bool isStereo)
{
if (type == webrtc::kPlaybackAllChannelsMixed)
{
printf("get remote mix pcm data\n");
}
if (type == webrtc::kRecordingAllChannelsMixed)
{
printf("get local record pcm data\n");
//本地聲音是連續(xù)的笨使,如果做錄音mp3應(yīng)該以本地回調(diào)為時間參考
//在本地回調(diào)時錄音
}
}
};
如何拿到數(shù)據(jù)
開啟webrtc數(shù)據(jù)回調(diào):
AudioMixDataCallBack* p = new AudioMixDataCallBack();
webrtc::VoEExternalMedia* externalMedia =
webrtc::VoEExternalMedia::GetInterface(g_voe->engine());
//回調(diào)本地錄制數(shù)據(jù)
externalMedia->RegisterExternalMediaProcessing(-1,
webrtc::kRecordingAllChannelsMixed,
*p);
//回調(diào)所有遠端的合成數(shù)據(jù)
externalMedia->RegisterExternalMediaProcessing(-1,
webrtc::kPlaybackAllChannelsMixed,
*p);
return 0;
注意拿到混合后的數(shù)據(jù)要求RegisterExternalMediaProcessing的第一個參數(shù)channelId設(shè)置為-1
在webrtc branch55,branch56中根據(jù)以上方法就可以拿到數(shù)據(jù)了僚害,但是在branch57中需要修改一下webrtc的代碼才能拿到數(shù)據(jù)。
修改的文件為:webrtc/audio/audio_state.cc
AudioState::AudioState(const AudioState::Config& config)
: config_(config),
voe_base_(config.voice_engine),
audio_transport_proxy_(voe_base_->audio_transport(),
voe_base_->audio_processing(),
config_.audio_mixer) {
process_thread_checker_.DetachFromThread();
RTC_DCHECK(config_.audio_mixer);
// Only one AudioState should be created per VoiceEngine.
RTC_CHECK(voe_base_->RegisterVoiceEngineObserver(*this) != -1);
auto* const device = voe_base_->audio_device_module();
RTC_DCHECK(device);
// This is needed for the Chrome implementation of RegisterAudioCallback.
//注釋下面兩行代碼
// device->RegisterAudioCallback(nullptr);
// device->RegisterAudioCallback(&audio_transport_proxy_);
}
正確的調(diào)用堆棧
branch57中如果不注釋以上兩行代碼最爬,會導致播放線程不會到VoEBaseImpl::NeedMorePlayData()拿播放數(shù)據(jù),導致我們設(shè)置的回調(diào)不會執(zhí)行爱致。
修改后audio render線程在播放聲音之前會把混音后的數(shù)據(jù)回調(diào)到我們定義的AudioMixDataCallBack中
調(diào)用堆棧為:
AudioMixDataCallBack::Process()
AudioMixDataCallBack::Process()
webrtc::voe::OutputMixer::DoOperationsOnCombinedSignal()
webrtc::VoEBaseImpl::GetPlayoutData()
webrtc::VoEBaseImpl::NeedMorePlayData()
webrtc::VoEBaseImpl::NeedMorePlayData()
webrtc::AudioDeviceBuffer::RequestPlayoutData()
webrtc::AudioDeviceMac::RenderWorkerThread()
webrtc-test`webrtc::AudioDeviceMac::RunRender()
后續(xù)工作
據(jù)說VoEExternalMedia類將會在新版webrtc中刪除寒随,在最新版本的webrtc中如何拿到數(shù)據(jù)目前還沒有研究糠悯。
關(guān)鍵詞:webrtc 錄音 pcm數(shù)據(jù) audio 混音