音频裸流传输

更新时间: 2024/08/05 15:02:55

在一些需要与硬件配合的应用场景中,比如使用教室硬件设备进行线上教学,在利用硬件自身能力进行音频采集、编码的基础上,还需要良好的抗弱网传输能力。若您拥有第三方音频编解码模块或有能力自研编解码,为了实现实时音频码流传输互通,NERTC SDK 为您提供抗弱网、抗丢包的纯传输通道。

功能介绍

依托网易云信底层实时传输网络 WE-CAN(Communication Acceleration Network),NERTC 运用全球节点及抗弱网算法,提供低延时、高稳定性的音视频码流传输通道,大大减少延时、丢包等网络问题对音视频传输质量和体验的影响。

NERTC SDK 支持音频裸流传输,您可以向 NERTC SDK 提供自定义的 OPUS 等格式的音频编码数据,并由 NERTC SDK 进行推流。

注意事项

使用 NERTC SDK 提供的裸流传输通道时,您需要自行管理音频流的采集、编解码、渲染和其他处理。

发送音频裸流

实现方法

  1. 在加入房间前,调用 setExternalAudioSource 方法开启外部音频主流输入或调用 setExternalSubStreamAudioSource 方法开启外部音频辅流输入,并设置外部音频采集参数,相关参数说明如下:
    • enabled:是否开启外部音频输入,默认关闭。
    • sample_rate:外部音频源的数据采样率,单位为赫兹(Hz)。建议设置为 8000,16000,32000,44100 或 48000。
    • channels:外部音频源的数据声道数,可设置为单声道(1)或双声道(2)。

    自定义外部音频采集接口只能在通话前调用,接口设置在通话结束后仍然有效;若您需要关闭该功能,请在下次通话前再次调用此方法关闭自定义音频采集。

  2. 调用 enableLocalAudio 开启媒体主流传输通道或调用 enableLocalSubStreamAudio 方法开启媒体辅流传输通道。

    若您开启的是外部音频主流输入,请开启对应的媒体主流传输通道,辅流同理。

  3. 您需要自行处理音频数据的采集与编码。
  4. 调用 pushExternalAudioEncodedFrame 方法推送外部音频主流编码帧或调用 pushExternalSubStreamAudioEncodedFrame 方法推送外部音频辅流编码帧,并通过 NERtcAudioEncodedFrame 设置编码后的音频数据,包括音频数据类型、数据长度、声道数、样本数等。

    建议在推送外部音频编码帧时,不要同时调用 pushExternalAudioFramepushExternalSubStreamAudioFrame 方法。

示例代码

以实现音频主流编码帧传输为例,示例代码如下:

// 开启外部音频源
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
}

接收音频裸流

实现方法

  1. 在初始化后,调用 setPreDecodeObserver 注册解码前媒体数据观测器。

  2. 远端发送音频流后,SDK 触发 onFrame 回调,通过 pre_decode_frame 参数返回相关解码前媒体数据,包括用户的 UID、媒体数据类型、数据长度、音频帧数据时间间隔等。

  3. 您需要自行处理音频数据的解码与渲染。

示例代码

// 设置解码前数据回调观测器
class NERtcPreDecodeObserverpublic 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 解码前媒体数据回调
此文档是否对你有帮助?
有帮助
去反馈
  • 功能介绍
  • 注意事项
  • 发送音频裸流
  • 实现方法
  • 示例代码
  • 接收音频裸流
  • 实现方法
  • 示例代码
  • API 参考