音频裸流传输
更新时间: 2024/09/18 16:26:13
在一些需要与硬件配合的应用场景中,比如使用教室硬件设备进行线上教学,在利用硬件自身能力进行音频采集、编码的基础上,还需要良好的抗弱网传输能力。若您拥有第三方音频编解码模块或有能力自研编解码,为了实现实时音频码流传输互通,NERTC SDK 为您提供抗弱网、抗丢包的纯传输通道。
功能介绍
依托网易云信底层实时传输网络 WE-CAN(Communication Acceleration Network),NERTC 运用全球节点及抗弱网算法,提供低延时、高稳定性的音视频码流传输通道,大大减少延时、丢包等网络问题对音视频传输质量和体验的影响。
NERTC SDK 支持音频裸流传输,您可以向 NERTC SDK 提供自定义的 OPUS 等格式的音频编码数据,并由 NERTC SDK 进行推流。
注意事项
使用 NERTC SDK 提供的裸流传输通道时,您需要自行管理音频流的采集、编解码、渲染和其他处理。
发送音频裸流
实现方法
- 在加入房间前,调用
setExternalAudioSource
方法开启外部音频主流输入或调用setExternalSubStreamAudioSource
方法开启外部音频辅流输入,并设置外部音频采集参数,相关参数说明如下:- enabled:是否开启外部音频输入,默认关闭。
- sample_rate:外部音频源的数据采样率,单位为赫兹(Hz)。建议设置为 8000,16000,32000,44100 或 48000。
- channels:外部音频源的数据声道数,可设置为单声道(1)或双声道(2)。
自定义外部音频采集接口只能在通话前调用,接口设置在通话结束后仍然有效;若您需要关闭该功能,请在下次通话前再次调用此方法关闭自定义音频采集。
- 调用
enableLocalAudio
开启媒体主流传输通道或调用enableLocalSubStreamAudio
方法开启媒体辅流传输通道。若您开启的是外部音频主流输入,请开启对应的媒体主流传输通道,辅流同理。
- 您需要自行处理音频数据的采集与编码。
- 调用
pushExternalAudioEncodedFrame
方法推送外部音频主流编码帧或调用pushExternalSubStreamAudioEncodedFrame
方法推送外部音频辅流编码帧,并通过NERtcAudioEncodedFrame
设置编码后的音频数据,包括音频数据类型、数据长度、声道数、样本数等。建议在推送外部音频编码帧时,不要同时调用
pushExternalAudioFrame
或pushExternalSubStreamAudioFrame
方法。
示例代码
以实现音频主流编码帧传输为例,示例代码如下:
// 开启外部音频源
auto ret = nrtc_engine->setExternalAudioSource(true, 16000, 1);
if (ret != nertc::kNERtcNoError) {
/// error handling
}
// 入会
ret = nrtc_engine->joinChannel(token, cname, uid);
if (ret != nertc::kNERtcNoError) {
/// error handling
}
//打开音频发送
ret = nrtc_engine->enableLocalAudio(true);
if (ret != nertc::kNERtcNoError) {
/// error handling
}
// 推送外部音频编码帧
int timediff = 20000; // us, opus need 20ms
uint64_t encoded_audio_ts = 0;
steady_clock::time_point last = steady_clock::now();
steady_clock::time_point now = steady_clock::now();
while (true) {
now = steady_clock::now();
long gap = duration_cast<microseconds>((now - last)).count();
if ( gap >= timediff) {
last = now - microseconds(gap - timediff);
nertc::NERtcAudioEncodedFrame audioFrame;
memset(&audioFrame, 0, sizeof(audioFrame));
audioFrame.sample_rate = sample_rate;
audioFrame.channels = channels;
audioFrame.samples_per_channel = sample_rate / 1000 * timediff / 1000;
audioFrame.payload_type = nertc::kNERtcAudioPayloadTypeOPUS; // OPUS
audioFrame.encoded_len = len;
audioFrame.data = data;
audioFrame.rms_level = rms_level; // 音量标记
audioFrame.timestamp_us = TimeMicros(); // 机器时间,us
audioFrame.encoded_timestamp = encoded_audio_ts;
encoded_audio_ts += audioFrame.samples_per_channel;
nrtc_engine->pushExternalAudioEncodedFrame(&audioFrame);
}
std::this_thread::sleep_for(milliseconds(1)); //1ms
}
接收音频裸流
实现方法
-
在初始化后,调用
setPreDecodeObserver
注册解码前媒体数据观测器。 -
远端发送音频流后,SDK 触发
onFrame
回调,通过pre_decode_frame
参数返回相关解码前媒体数据,包括用户的 UID、媒体数据类型、数据长度、音频帧数据时间间隔等。 -
您需要自行处理音频数据的解码与渲染。
示例代码
// 设置解码前数据回调观测器
class NERtcPreDecodeObserver:public nertc::INERtcPreDecodeObserver {
public:
void onFrame(NERtcPreDecodeFrameInfo* pre_decode_frame) override {
/*解码前媒体数据回调*/
}
};
NERtcPreDecodeObserver observer;
auto ret = nrtc_engine->setPreDecodeObserver(&observer);
if (ret != nertc::kNERtcNoError) {
/// error handling
}
API 参考
方法 | 功能描述 |
---|---|
setExternalAudioSource |
开启外部音频主流输入 |
setExternalSubStreamAudioSource |
开启外部音频辅流输入 |
pushExternalAudioEncodedFrame |
推送外部音频主流编码帧 |
pushExternalSubStreamAudioFrame |
推送外部音频辅流编码帧 |
setPreDecodeObserver |
注册解码前媒体数据观测器 |
事件 | 事件描述 |
---|---|
onFrame |
解码前媒体数据回调 |