你可以获取格式为 PCM 的原始音频数据,对这些数据进行处理。例如,将数据存储到本地,实现客户端录制音频。
适用场景
前提条件
你已经集成 RTC SDK,实现了基本的音视频通话。
支持获取原始音频数据的 SDK 详见API 及回调。
功能实现
以下时序图以 Android SDK 中的 API 名称为例。不同端的 SDK 中 API 或回调名称可能略有不同,以 API 及回调为准。
1. 创建引擎
创建和初始化一个音视频引擎类。
如果你需要获取远端的音频数据,还需要加入房间并发布音频流,参考 构建 RTC 应用 获取详细步骤。
rtcVideo = RTCVideo.createRTCVideo(this, Constants.APP_ID, videoEventHandler, null, null);
self?.rtcVideo = ByteRTCVideo.createRTCVideo(kAppID, delegate: self, parameters: [:])
self?.rtcVideo?.startAudioCapture()
bytertc::IRTCVideo *video = bytertc::createRTCVideo(app_id, handler, nullptr);
video->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(RemoteStreamKey streamKey, IAudioFrame audioFrame) {
Log.i(TAG, "onRemoteUserAudioFrame:");
}
@Override
public void onMixedAudioFrame(IAudioFrame audioFrame) {
Log.i(TAG, "onMixedAudioFrame:");
}
};
// ByteRTCAudioFrameObserver
func onRecord(_ audioFrame: ByteRTCAudioFrame) {
//返回麦克风录制的音频数据,本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRecord 类型后即可收到该回调
// 你可以使用采集的麦克风数据进行音频录制,由于该数据是只读数据,因此无法修改,如果需要对音频数据进行自定义处理,请使用 registerAudioProcessor 接口
}
func onPlaybackAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
// 返回订阅的所有远端用户混音后的音频数据。
// 本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackPlayback 类型后即可收到该回调
}
func onMixedAudioFrame(_ audioFrame: ByteRTCAudioFrame) {
//返回远端单个用户的音频数据.
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackMixed 类型后即可收到该回调
}
func onRemoteUserAudioFrame(_ streamKey: ByteRTCRemoteStreamKey, audioFrame: ByteRTCAudioFrame) {
//返回本地屏幕录制的音频数据
//本端开启音频采集且注册音频回调 ByteRTCAudioFrameCallbackRemoteUser 类型后即可收到该回调
}
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:
};
3. 开启回调
通过 registerAudioFrameObserver
注册音频数据回调。
调用 enableAudioFrameCallback
,为需要收到的音频数据设置回调格式。每次调用只能设置其中一种音频数据的格式。
目标音频数据为录制、回放和混音时,需要在音频参数格式 format
中指定具体的采样率和声道数。
目标音频数据为远端音频流时,音频参数格式 format
需要设置为自动。
- 在
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);
// 注册音频数据回调
self.rtcVideo!.registerAudioFrameObserver(self)
//设置回调音频格式,以麦克风录制的音频数据回调为例
let audioFormat = ByteRTCAudioFormat.init()
audioFormat.sampleRate = .rate44100 //采样率
audioFormat.channel = .stereo //声道数
audioFormat.samplesPerCall = 0 //单次回调的音频帧中包含的采样点数
//开启指定格式的回调,以麦克风录制的音频数据回调为例
self.rtcVideo?.enableAudioFrameCallback(.record, format: audioFormat)
// 注册音频数据回调
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);
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);
//以关闭麦克风录制的音频数据回调为例
self.rtcVideo?.disableAudioFrameCallback(.record)
self.rtcVideo?.registerAudioFrameObserver(nil)
video->disableAudioFrameCallback(type);
video->registerAudioFrameObserver(nullptr);
5. 销毁引擎
通话结束后,销毁音视频引擎。
如果用户已经进入房间,则需要在销毁所有房间实例后再销毁音视频引擎。
RTCVideo.destroyRTCVideo();
ByteRTCVideo.destroyRTCVideo()
self.rtcVideo = nil
bytertc::destroyRTCVideo();
video = 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
方法,参见 自定义音频处理。