功能描述

音视频传输过程中,我们可以对采集到的音视频数据进行前处理和后处理,获取想要的播放效果。

对于有自行处理音视频数据需求的场景,Agora 提供原始数据功能,你可以在将数据发送给编码器前进行前处理,对捕捉到的语音信号或视频帧进行修改;也可以在将数据发送给解码器后进行后处理,对接收到的语音信号或视频帧进行修改。

Native SDK 通过提供 IAudioFrameObserver 类,实现采集、修改原始音频数据功能。

实现方法

在使用原始数据功能前,请确保你已在项目中完成基本的实时音视频功能,详见如下文档:

参考如下步骤,在你的项目中实现原始音频数据功能:

  1. 加入频道前调用 registerAudioFrameObserver 方法注册语音观测器,并在该方法中实现一个 IAudioFrameObserver 类。
  2. 成功注册后,SDK 通过 onRecordAudioFrameonPlaybackAudioFrameonPlaybackAudioFrameBeforeMixingonMixedAudioFrame 回调发送采集到的原始音频数据。
  3. 用户拿到音频数据后,根据场景需要自行进行处理。完成音频数据处理后,你可以直接进行自播放,或根据场景需求再通过 onRecordAudioFrameonPlaybackAudioFrameonPlaybackAudioFrameBeforeMixingonMixedAudioFrame 回调发送给 SDK。

API 时序图

下图展示使用原始音频数据的 API 调用时序:

示例代码

你可以对照 API 时序图,参考下面的示例代码片段,在项目中实现音频原始数据功能:

class AgoraAudioFrameObserver : public agora::media::IAudioFrameObserver
{
    public:
        // 获取录制的音频帧
        virtual bool onRecordAudioFrame(AudioFrame& audioFrame) override
        {
            return true;
        }
        // 获取播放的音频帧
        virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame) override
        {
            return true;
         }
        // 获取远端某个用户发送的音频帧
        virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame) override
         {
            return true;
         }
        // 获取本地录制和播放混音后的音频帧
        virtual bool onMixedAudioFrame(AudioFrame& audioFrame) override
         {
         return true;
         }

};

class IAudioFrameObserver
{
    public:
            enum AUDIO_FRAME_TYPE {
            FRAME_TYPE_PCM16 = 0, // 音频数据格式为 PCM 16
            };
    struct AudioFrame {
            AUDIO_FRAME_TYPE type;
            int samples;  // 该音频帧的帧数
            int bytesPerSample; // 每帧的字节数:2
            int channels; // 声道数;双声道则音频数据重叠
            int samplesPerSec; // 采样率
            void* buffer; // 音频数据 Buffer
            int64_t renderTimeMs; // 当前音频帧的时间戳
         };
    public:
            virtual bool onRecordAudioFrame(AudioFrame& audioFrame) = 0;
            virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame) = 0;
            virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame) = 0;
            virtual bool onMixedAudioFrame(AudioFrame& audioFrame) = 0;
};

同时,我们在 GitHub 提供一个开源的 AgoraAudioIO-Objective-C 示例项目。你可以前往下载,或参考该项目的源代码。

API 参考

如果想要修改上述回调中的音频采样率,可以根据场景需求,调用如下方法进行设置:

开发注意事项

本文中使用的原始数据接口为 C++ 接口。如果你在 iOS 或 macOS 平台开发,请参考如下步骤注册音频数据观测器。

static AgoraAudioFrameObserver* s_audioFrameObserver;
- (void)addRegiset:(AgoraRtcEngineKit *)agoraKit {

    // Agora Engine of C++
    agora::rtc::IRtcEngine* rtc_engine = (agora::rtc::IRtcEngine*)agoraKit.getNativeHandle;
    agora::util::AutoPtr<agora::media::IMediaEngine> mediaEngine;
    mediaEngine.queryInterface(rtc_engine, agora::AGORA_IID_MEDIA_ENGINE);

    if (mediaEngine) {
        s_audioFrameObserver = new AgoraAudioFrameObserver();
        mediaEngine->registerAudioFrameObserver(s_audioFrameObserver);
    }
}

- (void)cancelRegiset {
    agora::rtc::IRtcEngine* rtc_engine = (agora::rtc::IRtcEngine*)self.agoraKit.getNativeHandle;
    agora::util::AutoPtr<agora::media::IMediaEngine> mediaEngine;
    mediaEngine.queryInterface(rtc_engine, agora::AGORA_IID_MEDIA_ENGINE);
    mediaEngine->registerAudioFrameObserver(NULL);
}