你可以获取格式为 PCM 的原始音频数据,对这些数据进行处理。例如,将数据存储到本地,实现客户端录制音频。

适用场景
前提条件

你已经集成 RTC SDK,实现了基本的音视频通话。
支持获取原始音频数据的 SDK 详见API 及回调。

功能实现

以下时序图以 Android SDK 中的 API 名称为例。不同端的 SDK 中 API 或回调名称可能略有不同,以 API 及回调为准。

alt

1. 创建引擎

创建和初始化一个音视频引擎类。

如果你需要获取远端的音频数据,还需要加入房间并发布音频流,参考 构建 RTC 应用 获取详细步骤。

rtcVideo = RTCVideo.createRTCVideo(this, Constants.APP_ID, videoEventHandler, null, null);
java
self?.rtcVideo = ByteRTCVideo.createRTCVideo(kAppID, delegate: self, parameters: [:])
self?.rtcVideo?.startAudioCapture()
swift
bytertc::IRTCVideo *video = bytertc::createRTCVideo(app_id, handler, nullptr);
video->startAudioCapture();
cpp
2. 继承 AudioFrameObserver

继承回调类,并实现里面的回调方法。

private IAudioFrameObserver audioFrameObserver = new IAudioFrameObserver() {
    @Override
    public void onRecordAudioFrame(IAudioFrame audioFrame) {
        Log.i(TAG, "onRecordAudioFrame:");
    }

    @Override
    public void onPlaybackAudioFrame(IAudioFrame audioFrame) {
        Log.i(TAG, "onPlaybackAudioFrame:");
    }

    @Override
    public void onRemoteUserAudioFrame(RemoteStreamKey streamKey, IAudioFrame audioFrame) {
        Log.i(TAG, "onRemoteUserAudioFrame:");
    }

    @Override
    public void onMixedAudioFrame(IAudioFrame audioFrame) {
        Log.i(TAG, "onMixedAudioFrame:");
    }
};
java
// ByteRTCAudioFrameObserver
func onRecord(_ audioFrame: ByteRTCAudioFrame) {
//返回麦克风录制的音频数据,本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRecord 类型后即可收到该回调
// 你可以使用采集的麦克风数据进行音频录制,由于该数据是只读数据,因此无法修改,如果需要对音频数据进行自定义处理,请使用 registerAudioProcessor 接口
}

func onPlaybackAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
// 返回订阅的所有远端用户混音后的音频数据。
// 本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackPlayback 类型后即可收到该回调   
}

func onMixedAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
//返回远端单个用户的音频数据.
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackMixed 类型后即可收到该回调    
}

func onRemoteUserAudioFrame(_ streamKey: ByteRTCRemoteStreamKey, audioFrame: ByteRTCAudioFrame) {
//返回本地屏幕录制的音频数据
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRemoteUser 类型后即可收到该回调    
}
swift
class RawAudioDataObserver : public bytertc::IAudioFrameObserver
{
public:
    RawAudioDataObserver();
    ~RawAudioDataObserver();

    virtual void onRecordAudioFrameOriginal(const bytertc::IAudioFrame& audio_frame){
    //内部使用
    }
    virtual void onRecordAudioFrame(const bytertc::IAudioFrame& audio_frame) {
    //返回麦克风录制的音频数据,本端开启音频采集且注册音频回调 kAudioFrameCallbackRecord 类型后即可收到该回调
    // 回调函数是在 SDK 内部线程(非 UI 线程)同步抛出来的,请不要做耗时操作或直接操作 UI,否则可能导致 app 崩溃
    // 你可以使用采集的麦克风数据进行音频录制,由于该数据是只读数据,因此无法修改,如果需要对音频数据进行自定义处理,请使用 registerAudioProcessor 接口
    }
    virtual void onPlaybackAudioFrame(const bytertc::IAudioFrame& audio_frame) {
    // 返回订阅的所有远端用户混音后的音频数据。
    // 本端开启音频采集且注册音频回调 kAudioFrameCallbackPlayback 类型后即可收到该回调
    }
    virtual void onRemoteUserAudioFrame(const bytertc::RemoteStreamKey& stream_info, const bytertc::IAudioFrame& audio_frame) {
    //返回远端单个用户的音频数据.
    //本端开启音频采集且注册音频回调 kAudioFrameCallbackRemoteUser 类型后即可收到该回调
    }
    virtual void onMixedAudioFrame(const bytertc::IAudioFrame& audio_frame) {
    //返回本地麦克风录制和订阅的所有远端用户混音后的音频数据
    //本端开启音频采集且注册音频回调 kAudioFrameCallbackMixed 类型后即可收到该回调
    }

    virtual void onRecordScreenAudioFrame(const bytertc::IAudioFrame& audio_frame){
    //返回本地屏幕录制的音频数据
    //本端开启音频采集且注册音频回调 kAudioFrameCallbackRecordScreen 类型后即可收到该回调
    }

private:
};
cpp
3. 开启回调
  1. 通过 registerAudioFrameObserver 注册音频数据回调。

  2. 调用 enableAudioFrameCallback,为需要收到的音频数据设置回调格式。每次调用只能设置其中一种音频数据的格式。

目标音频数据为录制、回放和混音时,需要在音频参数格式 format 中指定具体的采样率和声道数。
目标音频数据为远端音频流时,音频参数格式 format 需要设置为自动。

  1. 在 RawAudioDataObserver 中接收对应类型的音频回调数据,你可以在回调数据中实现音频录制等操作。
// 注册音频数据回调
rtcVideo.registerAudioFrameObserver(audioFrameObserver);
//设置回调音频格式
AudioFormat format = new AudioFormat(AudioSampleRate.AUDIO_SAMPLE_RATE_48000, AudioChannel.AUDIO_CHANNEL_MONO);
// 开启本地麦克风录制的音频数据回调
rtcVideo.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_RECORD, format);
// 开启本地麦克风录制和订阅的远端所有用户混音后的音频数据回调
rtcVideo.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_MIXED, format);
// 开启订阅的远端所有用户混音后的音频数据回调
rtcVideo.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_PLAYBACK, format);

//设置回调音频格式
AudioFormat audioFormat = new AudioFormat(AudioSampleRate.AUDIO_SAMPLE_RATE_AUTO, AudioChannel.AUDIO_CHANNEL_AUTO);
// 开启订阅的远端每个用户混音前的音频数据回调
rtcVideo.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_REMOTE_USER, audioFormat);
java
// 注册音频数据回调
self.rtcVideo!.registerAudioFrameObserver(self)

//设置回调音频格式,以麦克风录制的音频数据回调为例
let audioFormat = ByteRTCAudioFormat.init()
audioFormat.sampleRate = .rate44100 //采样率
audioFormat.channel = .stereo //声道数
audioFormat.samplesPerCall = 0 //单次回调的音频帧中包含的采样点数
//开启指定格式的回调,以麦克风录制的音频数据回调为例
self.rtcVideo?.enableAudioFrameCallback(.record, format: audioFormat)
swift
// 注册音频数据回调
observer = new RawAudioDataObserver();
video->registerAudioFrameObserver(observer);
//设置回调音频格式,以麦克风录制的音频数据回调为例
bytertc::AudioFormat format;
format.channel = bytertc::kAudioChannelStereo; //声道数
format.sample_rate = bytertc::kAudioSampleRate48000; //采样率
format.samples_per_call = 480; //单次回调的音频帧中包含的采样点数
//开启指定格式的回调,以麦克风录制的音频数据回调为例
ret = m_video->enableAudioFrameCallback(bytertc::AudioFrameCallbackMethod::kAudioFrameCallbackRecord, format);
cpp
4. 关闭回调

不再需要音频数据时,给 registerAudioFrameObserver 传空可关闭回调。

rtcVideo.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_RECORD);
rtcVideo.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_MIXED);
rtcVideo.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_PLAYBACK);
rtcVideo.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_REMOTE_USER);
java
//以关闭麦克风录制的音频数据回调为例
self.rtcVideo?.disableAudioFrameCallback(.record)
self.rtcVideo?.registerAudioFrameObserver(nil)
swift
video->disableAudioFrameCallback(type);
video->registerAudioFrameObserver(nullptr);
cpp
5. 销毁引擎

通话结束后,销毁音视频引擎。

如果用户已经进入房间,则需要在销毁所有房间实例后再销毁音视频引擎。

RTCVideo.destroyRTCVideo();
java
ByteRTCVideo.destroyRTCVideo()
self.rtcVideo = nil
swift
bytertc::destroyRTCVideo();
video = nullptr;
cpp
示例项目

参考以下项目获取完整代码。

API 及回调

以下客户端 SDK 均支持获取原始音频数据。你可以根据上文中的描述和实例,使用不同的 SDK,在不同的端上实现这个功能。

说明:表格中的 macOS API 接口为 Objective-C,而示例项目中的 macOS 项目使用的是 Windows SDK 中的 API 接口。

平台AndroidiOSmacOSWindowsLinuxElectronUnity
注册音频数据回调观察者registerAudioFrameObserverregisterAudioFrameObserver:registerAudioFrameObserver:registerAudioFrameObserverregisterAudioFrameObserver无无
设置并开启指定的音频数据帧回调enableAudioFrameCallbackenableAudioFrameCallback:format:enableAudioFrameCallback:format:enableAudioFrameCallbackenableAudioFrameCallbackenableAudioFrameCallbackEnableAudioFrameCallback
关闭音频数据帧回调disableAudioFrameCallbackdisableAudioFrameCallback:disableAudioFrameCallback:disableAudioFrameCallbackdisableAudioFrameCallbackdisableAudioFrameCallbackDisableAudioFrameCallback

音频数据回调回调

IAudioFrameObserver

ByteRTCAudioFrameObserver

ByteRTCAudioFrameObserver

IAudioFrameObserver

IAudioFrameObserver

onRecordAudioFrame
onPlaybackAudioFrame
onRemoteUserAudioFrame
onMixedAudioFrame
onRecordScreenAudioFrame

OnRecordAudioFrameEventHandler
OnPlaybackAudioFrameEventHandler
OnRemoteUserAudioFrameEventHandler
OnMixedAudioFrameEventHandler
OnRecordScreenAudioFrameEventHandler

常见问题
Q1:调用开启接口成功,但收不到回调

A:确认调用 enableAudioFrameCallback 时传入的参数 method 和 format 是否匹配,参考以下表格。

参数含义参数名称参数取值组合 1参数取值组合 2

音频回调方法

method

  • 0: 本地麦克风
  • 1: 所有远端混音
  • 2: 本地与远端混音

3: 单个远端用户音频流

音频格式format指定采样率和声道-1: 自动
Q2:如何将音频数据处理后发送到远端

A:通过本文提到的回调获取数据,进行处理后,不会影响发送到远端的数据。如果你希望处理音频数据后,送回 RTC 进行编码和发送,应使用 registerAudioProcessor 方法,参见 自定义音频处理。