你可以获取格式为 PCM 的原始音频数据,对这些数据进行处理。例如,将数据存储到本地,实现客户端录制音频。
适用场景
前提条件
你已经集成 RTC SDK,实现了基本的音视频通话。
支持获取原始音频数据的 SDK 详见API 及回调。
功能实现
以下时序图以 Android SDK 中的 API 名称为例。不同端的 SDK 中 API 或回调名称可能略有不同,以 API 及回调为准。

1. 创建引擎
创建和初始化一个音视频引擎类。
如果你需要获取远端的音频数据,还需要加入房间并发布音频流,参考 构建 RTC 应用 获取详细步骤。
EngineConfig config = new EngineConfig();
config.appID = appId;
config.context = applicationContext;
rtcEngine = RTCEngine.createRTCEngine(config, engineEventHandler);
let engineCfg = ByteRTCEngineConfig.init()
engineCfg.appID = appId
engineCfg.parameters = [:]
self.rtcEngine = ByteRTCEngine.createRTCEngine(engineCfg, delegate: self)
bytertc::EngineConfig conf;
conf.app_id = g_appid.c_str();
engine = bytertc::IRTCEngine::createRTCEngine(conf, this);
engine->startAudioCapture();
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(String streamId, StreamInfo streamInfo, IAudioFrame audioFrame) {
Log.i(TAG, "onRemoteUserAudioFrame:");
}
@Override
public void onMixedAudioFrame(IAudioFrame audioFrame) {
Log.i(TAG, "onMixedAudioFrame:");
}
@Override
public void onCaptureMixedAudioFrame(IAudioFrame audioFrame) {
Log.i(TAG, "onCaptureMixedAudioFrame:");
}
};
// ByteRTCAudioFrameObserver
func onRecordAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
//返回麦克风录制的音频数据,本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRecord 类型后即可收到该回调
// 你可以使用采集的麦克风数据进行音频录制,由于该数据是只读数据,因此无法修改,如果需要对音频数据进行自定义处理,请使用 registerAudioProcessor 接口
}
func onPlaybackAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
// 返回订阅的所有远端用户混音后的音频数据。
// 本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackPlayback 类型后即可收到该回调
}
func onMixedAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
//返回远端单个用户的音频数据.
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackMixed 类型后即可收到该回调
}
func onCaptureMixedAudioFrame(_ audioFrame: ByteRTCAudioFrame) {//返回本地麦克风录制的音频数据,本地 MediaPlayer / EffectPlayer 播放音频文件混音后的音频数据
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackCaptureMixed 类型后即可收到该回调
}
func onRemoteUserAudioFrame(_ streamId: String, info: ByteRTCStreamInfo, audioFrame: ByteRTCAudioFrame) {
//返回本地屏幕录制的音频数据
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRemoteUser 类型后即可收到该回调
}
class RawAudioDataObserver : public bytertc::IAudioFrameObserver
{
public:
RawAudioDataObserver();
~RawAudioDataObserver();
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:
};
3. 开启回调
通过 registerAudioFrameObserver 注册音频数据回调。
调用 enableAudioFrameCallback,为需要收到的音频数据设置回调格式。每次调用只能设置其中一种音频数据的格式。
目标音频数据为录制、回放和混音时,需要在音频参数格式 format 中指定具体的采样率和声道数。
目标音频数据为远端音频流时,音频参数格式 format 需要设置为自动。
- 在
RawAudioDataObserver 中接收对应类型的音频回调数据,你可以在回调数据中实现音频录制等操作。
// 注册音频数据回调
rtcEngine.registerAudioFrameObserver(audioFrameObserver);
//设置回调音频格式
AudioFormat format = new AudioFormat(AudioSampleRate.AUDIO_SAMPLE_RATE_48000, AudioChannel.AUDIO_CHANNEL_MONO);
// 开启本地麦克风录制的音频数据回调
rtcEngine.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_RECORD, format);
// 开启本地麦克风录制和订阅的远端所有用户混音后的音频数据回调
rtcEngine.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_MIXED, format);
// 开启订阅的远端所有用户混音后的音频数据回调
rtcEngine.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_PLAYBACK, format);
//设置回调音频格式
AudioFormat audioFormat = new AudioFormat(AudioSampleRate.AUDIO_SAMPLE_RATE_AUTO, AudioChannel.AUDIO_CHANNEL_AUTO);
// 开启订阅的远端每个用户混音前的音频数据回调
rtcEngine.enableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_REMOTE_USER, audioFormat);
// 注册音频数据回调
self.rtcEngine!.registerAudioFrameObserver(self)
//设置回调音频格式,以麦克风录制的音频数据回调为例
let audioFormat = ByteRTCAudioFormat.init()
audioFormat.sampleRate = .rate44100 //采样率
audioFormat.channel = .stereo //声道数
audioFormat.samplesPerCall = 0 //单次回调的音频帧中包含的采样点数
//开启指定格式的回调,以麦克风录制的音频数据回调为例
self.rtcEngine?.enableAudioFrameCallback(.record, format: audioFormat)
// 注册音频数据回调
observer = new RawAudioDataObserver();
engine->registerAudioFrameObserver(observer);
//设置回调音频格式,以麦克风录制的音频数据回调为例
bytertc::AudioFormat format;
format.channel = bytertc::kAudioChannelStereo; //声道数
format.sample_rate = bytertc::kAudioSampleRate48000; //采样率
format.samples_per_call = 480; //单次回调的音频帧中包含的采样点数
//开启指定格式的回调,以麦克风录制的音频数据回调为例
ret = engine->enableAudioFrameCallback(bytertc::AudioFrameCallbackMethod::kAudioFrameCallbackRecord, format);
4. 关闭回调
不再需要音频数据时,给 registerAudioFrameObserver 传空可关闭回调。
rtcEngine.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_RECORD);
rtcEngine.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_MIXED);
rtcEngine.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_PLAYBACK);
rtcEngine.disableAudioFrameCallback(AudioFrameCallbackMethod.AUDIO_FRAME_CALLBACK_REMOTE_USER);
//以关闭麦克风录制的音频数据回调为例
self.rtcEngine?.disableAudioFrameCallback(.record)
self.rtcEngine?.registerAudioFrameObserver(nil)
engine->disableAudioFrameCallback(type);
engine->registerAudioFrameObserver(nullptr);
5. 销毁引擎
通话结束后,销毁音视频引擎。
如果用户已经进入房间,则需要在销毁所有房间实例后再销毁音视频引擎。
RTCEngine.destroyRTCEngine();
ByteRTCEngine.destroyRTCEngine()
self.rtcEngine = nil
bytertc::IRTCEngine::destroyRTCEngine();
engine = nullptr;
示例项目
参考以下项目获取完整代码。
API 及回调
以下客户端 SDK 均支持获取原始音频数据。你可以根据上文中的描述和实例,使用不同的 SDK,在不同的端上实现这个功能。
说明:表格中的 macOS API 接口为 Objective-C,而示例项目中的 macOS 项目使用的是 Windows SDK 中的 API 接口。
常见问题
Q1:调用开启接口成功,但收不到回调
A:确认调用 enableAudioFrameCallback 时传入的参数 method 和 format 是否匹配,参考以下表格。
| 参数含义 | 参数名称 | 参数取值组合 1 | 参数取值组合 2 |
|---|
音频回调方法 | method
| 0: 本地麦克风1: 所有远端混音2: 本地与远端混音
| 3: 单个远端用户音频流
|
| 音频格式 | format | 指定采样率和声道 | -1: 自动 |
Q2:如何将音频数据处理后发送到远端
A:通过本文提到的回调获取数据,进行处理后,不会影响发送到远端的数据。如果你希望处理音频数据后,送回 RTC 进行编码和发送,应使用 registerAudioProcessor 方法,参见 自定义音频处理。