自定义音频采集

ARTC SDK提供了灵活的自定义音频采集功能,此功能不仅支持用户自行管理音频设备,还允许在阿里云管理音频采集机制与用户管理音频采集机制之间的动态切换。

前提条件

在设置视频配置之前,请确保达成以下条件:

功能实现

image

1.打开或关闭内部采集

Android

/* 动态关闭阿里内部采集 */
String parameter = "{\"audio\":{\"enable_system_audio_device_record\":\"FALSE\"}}";
mAliRtcEngine.setParameter(parameter);

/* 动态打开阿里内部采集 */
String parameter = "{\"audio\":{\"enable_system_audio_device_record\":\"TRUE\"}}"; 
mAliRtcEngine.setParameter(parameter);

iOS

/* 动态关闭阿里内部采集 */
[_engine setParameter:@"{\"audio\":{\"enable_system_audio_device_record\":\"FALSE\"}}"];

/* 动态打开阿里内部采集 */
[_engine setParameter:@"{\"audio\":{\"enable_system_audio_device_record\":\"TRUE\"}}"];

Windows

/* Windows支持创建时指定开启/关闭音频采集 */
/* 关闭阿里内部采集 */
char* extra = "{\"user_specified_enable_use_virtual_audio_device\":\"TRUE\", \"user_specified_use_external_audio_record\":\"TRUE\"}";
mAliRtcEngine = AliRtcEngine.Create(extra);

/* 开启阿里内部采集 */
char* extra = "{\"user_specified_enable_use_virtual_audio_device\":\"FALSE\", \"user_specified_use_external_audio_record\":\"FALSE\"}";
mAliRtcEngine = AliRtcEngine.Create(extra);

2.添加外部音频流

Android

/* 根据自己的业务设置对应的参数 */
AliRtcEngine.AliRtcExternalAudioStreamConfig config = new AliRtcEngine.AliRtcExternalAudioStreamConfig();
config.sampleRate = 48000;
config.channels = 1;
config.publishVolume = 100;
config.playoutVolume = isLocalPlayout ? 100 : 0;
config.enable3A = true;

int result = mAliRtcEngine.addExternalAudioStream(config);
if (result <= 0) {
    // 添加失败
    return;
}
mExternalAudioStreamId = result;

iOS

/* 根据自己的业务设置对应的参数 */
AliRtcExternalAudioStreamConfig *config = [AliRtcExternalAudioStreamConfig new];
//需要和外部PCM音频流的声道数相同,如果是单声道设置成1,双声道设置成2
config.channels = _pcmChannels;
//需要和外部PCM音频流的采样率相同
config.sampleRate = _pcmSampleRate;
config.playoutVolume = 0;
config.publishVolume = 100;
_externalPlayoutStreamId = [self.engine addExternalAudioStream:config];

Windows

/* 获取媒体引擎 */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;
    
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);
/* 根据自己的业务设置对应的参数 */
AliEngineExternalAudioStreamConfig config;
config.playoutVolume = currentAudioPlayoutVolume;
config.publishVolume = currentAudioPublishVolume;
config.channels = 1;
config.sampleRate = 48000;
config.publishStream = 0;
audioStreamID = mAliRtcMediaEngine->AddExternalAudioStream(config);

mAliRtcMediaEngine->Release();

3.向音频流内送入PCM数据

Android

// 推送音频数据
AliRtcEngine.AliRtcAudioFrame sample = new AliRtcEngine.AliRtcAudioFrame();
sample.data = buffer;
sample.numSamples = BUFFER_SAMPLE_COUNT;
sample.numChannels = CHANNEL; //需要和外部PCM音频流的声道数相同,如果是单声道设置成1,双声道设置成2
sample.sampleRate = SAMPLE_RATE; //需要和外部PCM音频流的采样率相同
sample.bytesPerSample = (int) BYTE_PER_SAMPLE;

int ret = mAliRtcEngine.pushExternalAudioStreamRawData(mExternalAudioStreamId, sample);

if (ErrorCodeEnum.ERR_SDK_AUDIO_INPUT_BUFFER_FULL == ret) {
    Thread.sleep(BUFFER_FULL_DURATION);
} else {
    Thread.sleep(BUFFER_DURATION);
}

iOS

AliRtcAudioFrame *sample = [AliRtcAudioFrame new];
sample.dataPtr = _pcmLocalData;
sample.samplesPerSec = _pcmLocalSampleRate;
sample.bytesPerSample = sizeof(int16_t);
sample.numOfChannels = _pcmLocalChannels;
//_pcmLocalData.length是外部PCM音频流的buffer的大小
sample.numOfSamples =  (int) (_pcmLocalData.length / (2 * _pcmLocalChannels));
int rc = [self.engine pushExternalAudioStream:_externalPlayoutStreamId rawData:sample];
if(rc == 0x01070101) {
    sleep(20);
} else if(ret < 0) {
    /* 异常, 检查参数和推流状态 */
}

Windows

/* 获取媒体引擎 */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;
    
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);

AliEngineAudioRawData rawData;
rawData.dataPtr = frameInfo.audio_data[0];
rawData.numOfSamples = (int) (frameInfo.audio_data[0].length / (2 * frameInfo.audio_channels));
rawData.bytesPerSample = 2;
rawData.numOfChannels = frameInfo.audio_channels;
rawData.samplesPerSec = frameInfo.audio_sample_rate;
int ret = mAliRtcMediaEngine->PushExternalAudioStreamRawData(audioStreamID, rawData);
mAliRtcMediaEngine->Release();

4.移除外部音频流

Android

mAliRtcEngine.removeExternalAudioStream(mExternalAudioStreamId);

iOS

[self.engine removeExternalAudioStream:_externalPublishStreamId];

Windows

/* 获取媒体引擎 */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;
    
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);

mAliRtcMediaEngine->RemoveExternalAudioStream(audioStreamID);
mAliRtcMediaEngine->Release();