音视频数据回调
简介
Pano SDK 支持将音视频数据回调给开发者进行处理,例如视频美颜、音频变声、语音识别等。
对于音频,一个简化的音频处理流程如下:
采集 --(1)--> 3A前处理* --(2)--> 编码 --> 发送 --> 接收 --> Jitter Buffer --> 解码 --(3)--> 播放
* 3A前处理是指:AEC (Acoustic Echo Cancellation 回声消除)、AGC (Automatic Gain Control 自动增益控制)、ANS (Automatic Noise Suppression 自动降噪)
Pano SDK 支持在 3 个时机回调数据:
- (1) 本地采集后,前处理之前
- (2) 本地采集后,编码之前
- (3) 播放之前
对于视频,Pano SDK 在本地采集后,编码之前回调数据。
对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程。
各端 SDK 相关接口,请查看下列介绍:
Windows (C++)
通过 RtcEngine
对象的 setMediaProcessor (MediaProcessorType type, void *processor, void *param=nullptr)
方法设置媒体处理模块。
- 对于音频,如需在本地采集后,前处理之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioCaptureExProcessor
,同时processor
处理模块必须为RtcExternalAudioProcess
类型,param
设置为空。- 开发者需要实现
RtcExternalAudioProcess
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在本地采集后,编码之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioCaptureExEffectProcessor
,同时processor
处理模块必须为RtcExternalAudioProcess
类型,param
设置为空。- 开发者需要实现
RtcExternalAudioProcess
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在播放之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioRenderExProcessor
,同时processor
处理模块必须为RtcExternalAudioProcess
类型,param
设置为空。- 开发者需要实现
RtcExternalAudioProcess
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于视频,如需对数据进行处理:
Android (Java)
通过 RtcEngine
对象的 setMediaProcessor (MediaProcessorType type, Object processor, Object param)
方法设置媒体处理模块。
- 对于音频,如需在本地采集后,前处理之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioCaptureExProcessor
,同时processor
处理模块必须为RtcAudioExProcessor
类型,param
设置为空。- 开发者需要实现
RtcAudioExProcessor
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在本地采集后,编码之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioCaptureExEffectProcessor
,同时processor
处理模块必须为RtcAudioExProcessor
类型,param
设置为空。- 开发者需要实现
RtcAudioExProcessor
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在播放之前,对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为AudioRenderExProcessor
,同时processor
处理模块必须为RtcAudioExProcessor
类型,param
设置为空。- 开发者需要实现
RtcAudioExProcessor
类,并实现onAudioFrame
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于视频,如需对数据进行处理:
MediaProcessorType
媒体处理类型需要设置为VideoTexturePreprocessor
,同时processor
处理模块必须为RtcVideoTextureFilter
类型,param
设置为RtcVideoTextureFilterConfig
对象。- 开发者需要创建一个
RtcVideoTextureFilterConfig
对象,可以指定以下属性:textureType
(TextureOES
或Texture2D
)和withYuv
(是否同时返回 YUV 数据),不指定的话将使用默认值,具体请参考 SDK API文档。 - 开发者需要实现
RtcVideoTextureFilter
类,并实现onVideoFrame (int textureId, int width, int height, int rotation, byte[] yuvData)
回调方法,在其中对 SDK 提供的视频数据进行处理。
示例代码:
mRtcEngine = RtcEngine.create(engineConfig); // 初始化
// 设置音频处理模块(本地采集后,前处理之前)
mRtcEngine.setMediaProcessor(AudioCaptureExProcessor, new MyRtcAudioExProcessor(), null);
// 设置视频处理模块
mRtcEngine.setMediaProcessor(VideoTexturePreprocessor, new MyRtcVideoTextureFilter(), new RtcVideoTextureFilterConfig());
MyRtcAudioExProcessor中:
public class MyRtcAudioExProcessor implements RtcAudioExProcessor {
private File file = new File(Environment.getExternalStorageDirectory() + File.separator + "test.pcm"); // 配合下文演示将音频数据写入文件保存到存储卡根目录
private FileOutputStream out = null; // 同上
@Override
public int onAudioFrame(ByteBuffer byteBuffer, int length, int maxBufferByteLens, RtcAudioDataFormat rtcAudioDataFormat) {
// 在这里处理 Pano SDK 回调的数据
// 需要调用 startAudio 采集音频数据之后,才会进入此回调
// SDK 回调的数据是 16 bit、LITTLE_ENDIAN
// 如果用于实时处理,请注意数据长度不要超过 byteBuffer 的 limit
// 对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程
// Log.i(TAG, "onAudioFrame, byteBuffer: " + byteBuffer + ", length: " + length + ", rtcAudioDataFormat-type: " + rtcAudioDataFormat.type + ", channels: " + rtcAudioDataFormat.channels + ", sampleRate: " + rtcAudioDataFormat.sampleRate + ", bytesPerSample: " + rtcAudioDataFormat.bytesPerSample);
// RtcAudioDataFormat 中,type: 数据类型(0: PCM),channels: 声道数,sampleRate: 采样率,bytesPerSample: 采样位宽(2 bytes = 16 bit)
// 可以通过 `RtcEngine.setOption` 配置 `EnablePanoAudioProfile` 和 `RtcAudioProfile` 来调整 `sampleRate` 和 `channel` 参数值
// 下面演示将音频数据写入文件,以下为简化示例,请自行处理权限申请、逻辑判断等
byte[] byte_array = new byte[length];
byteBuffer.get(byte_array);
try {
out = new FileOutputStream(file, true); // 以追加方式写入
out.write(byte_array);
} catch (IOException e) {
e.printStackTrace();
}
// 以采样率48000、单声道的数据为例,可以使用 ffplay 通过以下命令进行播放:
// ffplay -ar 48000 -ac 1 -f s16le -i YourFilePath
// -ar: 音频采样率,-ac: 声道数,-f: 格式(s16le: signed 16 bits little endian, 有符号 16 位小端)
return 0; // SDK 不关心此处返回值
}
}
MyRtcVideoTextureFilter中:
public class MyRtcVideoTextureFilter implements RtcVideoTextureFilter {
private boolean isFirst = true; // 配合下文演示对接第三方美颜功能
@Override
public int onVideoFrame(int textureId, int width, int height, int rotation, byte[] yuvData) {
// 在这里处理 SDK 回调的数据,默认情况下 yuvData 为空
// 需要调用 startPreview 或 startVideo 采集视频数据之后,才会进入此回调
// 对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程
// 下面演示对接 FaceUnity 的美颜功能(请先自行处理美颜 SDK 初始化工作)
if (isFirst) {
mFuRenderer.onSurfaceCreated();
isFirst = false;
}
return mFuRenderer.onDrawFrameSingleInput(textureId, width, height);
// return newTextureId; // 返回处理后输出的 textureId
}
@Override
public void releaseOnGlThread() {
// 若使用 OpenGL 处理纹理,则需要在此进行 OpenGL 资源的释放;如无需要,可以不处理此回调
mFuRenderer.onSurfaceDestroyed(); // 此行演示对接 FaceUnity 美颜的处理
}
}
iOS/macOS (Objective-C)
通过 PanoRtcEngineKit
对象的 - setMediaProcessor:processor:param:
方法设置媒体处理模块。
- 对于音频,如需在本地采集后,前处理之前,对数据进行处理:
PanoMediaProcessorType
媒体处理类型需要设置为kAudioCaptureExProcessor
,同时processor
处理模块必须为PanoRtcAudioDataExProcessorDelegate
类型,param
设置为空。- 开发者需要实现
PanoRtcAudioDataExProcessorDelegate
协议,并实现- onAudioFrame:withLength:withMaxLength:withFormat:
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在本地采集后,编码之前,对数据进行处理:
PanoMediaProcessorType
媒体处理类型需要设置为kAudioCaptureExEffectProcessor
,同时processor
处理模块必须为PanoRtcAudioDataExProcessorDelegate
类型,param
设置为空。- 开发者需要实现
PanoRtcAudioDataExProcessorDelegate
协议,并实现- onAudioFrame:withLength:withMaxLength:withFormat:
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于音频,如需在播放之前,对数据进行处理:
PanoMediaProcessorType
媒体处理类型需要设置为kAudioRenderExProcessor
,同时processor
处理模块必须为PanoRtcAudioDataExProcessorDelegate
类型,param
设置为空。- 开发者需要实现
PanoRtcAudioDataExProcessorDelegate
协议,并实现- onAudioFrame:withLength:withMaxLength:withFormat:
回调方法,在其中对 SDK 提供的音频数据进行处理。
- 对于视频,如需对数据进行处理:
PanoMediaProcessorType
媒体处理类型需要设置为kVideoPreprocessor
,同时processor
处理模块必须为PanoRtcVideoFilterDelegate
类型,param
设置为空。- 开发者需要实现
PanoRtcVideoFilterDelegate
类,并在 iOS 上实现- onNativeVideoFrame:withRotation:
回调方法,在 macOS 上 实现- onVideoFrame:withLength:withFormat:
方法,在其中对 SDK 提供的视频数据进行处理。 - 需要 开启本地预览 或者 发送本地视频 之后,才会回调视频数据。
示例代码:
#import "PanoRtc/PanoRtcEngineKit.h"
@interface ChannelViewController () <PanoRtcEngineDelegate, PanoRtcAudioDataExProcessorDelegate>
...
@end
@implementation ChannelViewController
...
self.engineKit = [PanoRtcEngineKit engineWithConfig:engineConfig delegate:self]; // 初始化
// 设置处理模块,以音频采集外部处理(本地采集后,前处理之前)为例
[self.engineKit setMediaProcessor:kAudioCaptureExProcessor processor:self param:nil];
...
- (void)onAudioFrame:(void *)buffer withLength:(SInt32)length withMaxLength:(SInt32)maxBufferByteLens withFormat:(PanoRtcAudioFormat *)format{
// 在这里处理 SDK 回调的数据
// 对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程
}
@end