Pano开发者中心
  • 开发者中心
  • 下载中心

›高级功能(RTC)

新手入门

  • 简介
  • 名词解释
  • 创建第一个应用

规则说明

  • Channel ID命名规则
  • 权限控制
  • 计费说明
  • 频道最大时长说明
  • 每月一万分钟免费说明
  • 布局参数说明
  • 水印

场景方案

    教育行业

    • 1vN互动小班课
    • 互动直播大班课

快速接入

  • 简介
  • 音视频

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Electron
    • Flutter
    • React Native
    • Unity

    白板

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Electron
    • Flutter
    • React Native

高级功能(RTC)

  • 简介
  • 屏幕共享
  • 分组讨论
  • 状态回调
  • 设备诊断
  • 音量指示
  • 控制声音
  • 声卡操作
  • 混音/伴音
  • 混响
  • 耳返
  • 变声
  • 美颜
  • 音视频数据回调
  • 音视频外部采集
  • 收发多路视频
  • 多窗口渲染
  • 性能检测
  • 截图
  • 反馈

高级功能(RTS)

  • 简介
  • 白板

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Flutter

    标注

    • 视频标注
    • 共享标注
    • 外部标注

    消息

    • 消息服务

    远程控制

    • 远程控制

操作实践

  • 切换大小屏

RESTful API

  • 基本格式
  • 生成Token
  • 频道管理
  • 云端录制
  • CDN推流
  • 文档转码
  • 消息服务
  • 服务端消息通知

SDK API

  • SDK接口说明
  • Windows (C++)
  • macOS/iOS (Objective-C)
  • Android (Java)
  • Web SDK (IE专用版)
  • Web SDK

    • 浏览器兼容性
    • RtcEngine
    • GroupManager
    • RtcWhiteboard
    • RtsService
    • RtcMessage
    • Annotation
    • Constants

更新记录

  • 简介
  • Windows
  • macOS
  • iOS
  • Android
  • Electron
  • Flutter
  • React Native
  • Unity
  • Web(全功能SDK)
  • Web(RTS SDK)
  • Web(IE专用音视频SDK)

帮助

  • FAQ
  • 更多帮助

音视频数据回调

简介

Pano SDK 支持将音视频数据回调给开发者进行处理,例如视频美颜、音频变声、语音识别等。

  • 对于音频,一个简化的音频处理流程如下:

    采集 --(1)--> 3A前处理* --(2)--> 编码 --> 发送 --> 接收 --> Jitter Buffer --> 解码 --(3)--> 播放

    * 3A前处理是指:AEC (Acoustic Echo Cancellation 回声消除)、AGC (Automatic Gain Control 自动增益控制)、ANS (Automatic Noise Suppression 自动降噪)

    Pano SDK 支持在 3 个时机回调数据:

    • 本地采集后,前处理之前
    • 本地采集后,编码之前
    • 播放之前
  • 对于视频,Pano SDK 在本地采集后,编码之前回调数据。

对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程。

各端 SDK 相关接口,请查看下列介绍:

  • Windows (C++)
  • macOS/iOS (Objective-C)
  • Android (Java)
  • Web

Windows (C++)

通过 RtcEngine 实例的 setMediaProcessor 方法设置媒体处理模块。

[注意] 上述接口只对当前选中的一个摄像头生效。如果有多个摄像头同时发送视频,或者同时预览和发送不同摄像头的视频等复杂场景,请更换为指定目标设备的方式:

  • 先调用 RtcEngine 实例的 getVideoDeviceManager 方法获取视频设备管理器(VideoDeviceManager)
  • 通过其 enumerateCaptureDevices 方法枚举视频采集设备,通过回调函数获取 deviceId
  • 再通过其 setDeviceBoundMediaProcessor 方法进行设置
  • 对于音频,如需在本地采集后,前处理之前,对数据进行处理:
    • MediaProcessorType 媒体处理类型需要设置为 AudioCaptureExProcessor ,同时 processor 处理模块必须为 RtcExternalAudioProcess 类型,param 设置为空。
    • 开发者需要实现 RtcExternalAudioProcess 类,并实现 onAudioFrame 回调方法,在其中对 SDK 提供的音频数据进行处理。
  • 对于音频,如需在本地采集后,编码之前,对数据进行处理:
    • MediaProcessorType 媒体处理类型需要设置为 AudioCaptureExEffectProcessor ,同时 processor 处理模块必须为 RtcExternalAudioProcess 类型,param 设置为空。
    • 开发者需要实现 RtcExternalAudioProcess 类,并实现 onAudioFrame 回调方法,在其中对 SDK 提供的音频数据进行处理。
  • 对于音频,如需在播放之前,对数据进行处理:
    • MediaProcessorType 媒体处理类型需要设置为 AudioRenderExProcessor ,同时 processor 处理模块必须为 RtcExternalAudioProcess 类型,param 设置为空。
    • 开发者需要实现 RtcExternalAudioProcess 类,并实现 onAudioFrame 回调方法,在其中对 SDK 提供的音频数据进行处理。
  • 对于视频,如需对数据进行处理:
    • MediaProcessorType 媒体处理类型需要设置为 VideoPreprocessor ,同时 processor 处理模块必须为 RtcExternalVideoProcessor 类型,param 设置为空。
    • 开发者需要实现 RtcExternalVideoProcessor 类,并实现 onVideoFrame 回调方法,在其中对 SDK 提供的视频数据进行处理。
    • 需要先设置媒体处理模块,再 开启本地预览 或者 发送本地视频,之后才会回调视频数据。

示例代码:

// .h 文件中:
// 以处理视频数据回到为例,继承 RtcExternalVideoProcessor
class RtcTester : public panortc::RtcExternalVideoProcessor
...
// 声明回调方法
panortc::QResult onVideoFrame(void* buffer, int length, panortc::VideoFormat& fmt);
panortc::QResult onVideoFrame(void* native, panortc::VideoFormat& fmt);

// .cpp 文件中:
// 设置视频处理模块
rtcEngine_->setMediaProcessor(MediaProcessorType::VideoPreprocessor, (RtcExternalVideoProcessor*)this, nullptr);
// 实现回调方法
panortc::QResult RtcTester::onVideoFrame(void* buffer, int length, panortc::VideoFormat& fmt) {
    // 此处展示查看视频信息
    printf("--> onVideoFrame: buffer = %p \n", buffer);
    printf("--> onVideoFrame: length = %d \n", length);
    printf("--> onVideoFrame: fmt.type = %d \n", (int)fmt.type);
    printf("--> onVideoFrame: fmt.width = %u \n", fmt.width);
    printf("--> onVideoFrame: fmt.height = %u \n", fmt.height);
    printf("--> onVideoFrame: fmt.count = %u \n", fmt.count);
    for (int i = 0; i < fmt.count; i++)
    {
        printf("--> onVideoFrame: fmt.offset[%d] = %u \n", i, fmt.offset[i]);
        printf("--> onVideoFrame: fmt.stride[%d] = %u \n", i, fmt.stride[i]);
    }
    printf("--> onVideoFrame: fmt.rotation = %u \n", (int)fmt.rotation);
    printf("--> onVideoFrame: fmt.mirror = %d \n", fmt.mirror);
    printf("--> onVideoFrame: ---------- \n");
    return panortc::QResult::OK;

}
panortc::QResult RtcTester::onVideoFrame(void* native, panortc::VideoFormat& fmt) {
    // 不需要处理此回调,直接返回 QResult::OK
    return panortc::QResult::OK;
}

macOS/iOS (Objective-C)

通过 PanoRtcEngineKit 实例的 - setMediaProcessor:processor:param: 方法设置媒体处理模块。

[注意] 上述接口只对当前选中的一个摄像头生效。如果有多个摄像头同时发送视频,或者同时预览和发送不同摄像头的视频等复杂场景,请更换为指定目标设备的方式:

  • 先通过 PanoRtcEngineKit 实例的 - enumerateDevices: 方法(macOS) 或 - getCameraDeviceId: 方法(iOS) 获取摄像头的 deviceId
  • 再通过 - setDeviceBoundMediaProcessor:processor:param:forDevice: 方法进行设置
  • 对于音频,如需在本地采集后,前处理之前,对数据进行处理:
    • 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 类,并实现 - onNativeVideoFrame:withRotation: 回调方法,在其中对 SDK 提供的视频数据进行处理。
    • 需要先设置媒体处理模块,再 开启本地预览 或者 发送本地视频,之后才会回调视频数据。

示例代码:

#import "PanoRtc/PanoRtcEngineKit.h"

// 实现 PanoRtcAudioDataExProcessorDelegate / PanoRtcVideoFilterDelegate 委托协议
@interface ChannelViewController () <PanoRtcEngineDelegate, PanoRtcAudioDataExProcessorDelegate, PanoRtcVideoFilterDelegate>
...
@end

@implementation ChannelViewController
...
self.engineKit = [PanoRtcEngineKit engineWithConfig:engineConfig delegate:self]; // 初始化
// 设置音频处理模块,以音频采集外部处理(本地采集后,前处理之前)为例
[self.engineKit setMediaProcessor:kAudioCaptureExProcessor processor:self param:nil];
// 设置视频处理模块
[self.engineKit setMediaProcessor:kVideoPreprocessor processor:self param:nil];
...
- (void)onAudioFrame:(void *)buffer withLength:(SInt32)length withMaxLength:(SInt32)maxBufferByteLens withFormat:(PanoRtcAudioFormat *)format{
    // 在这里处理 SDK 回调的音频数据
    // 对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程
}

- (void)onNativeVideoFrame:(CVPixelBufferRef)frame withRotation:(PanoVideoRotation)rotation{
    // 在这里处理 SDK 回调的视频数据
    // 对 frame 同步处理完成后,SDK 会自动发送处理后的视频数据
    // 对于不需要回传数据给 SDK 的情况,如果计算量较大,建议拷贝数据到其他线程单独处理,以免阻塞 SDK 的回调线程
}

@end

Android (Java)

通过 RtcEngine 实例的 setMediaProcessor(MediaProcessorType type, Object processor, Object param) 方法设置媒体处理模块。

[注意] 上述接口只对当前选中的一个摄像头生效。如果有多个摄像头同时发送视频,或者同时预览和发送不同摄像头的视频等复杂场景,请更换为指定目标设备的方式:

  • 先调用 RtcEngine 实例的 getVideoDeviceManager 方法获取视频设备管理器(RtcVideoDeviceManager),通过其 getCaptureDeviceList 方法获取视频采集设备列表(RtcDeviceInfo),其中包含 deviceId
  • 再通过 RtcEngine 实例的 setDeviceBoundMediaProcessor (String deviceId, 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 文档。

      注意:当 textureType 属性值为 TextureOES 时,"音视频数据回调"和 SDK 自带的 美颜 功能无法同时使用。

    • 开发者需要实现 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) {
        /* # 需要调用 startAudio 采集音频数据之后,才会进入此回调
           # 在这里处理 Pano 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) {
        /* # 在这里处理 Pano SDK 回调的数据,默认情况下 yuvData 为空
             可以配置 RtcVideoTextureFilterConfig 的 withYuv 属性为 true 开启拷贝 yuvData
           # 后续编码传输使用纹理数据,yuvData 仅为拷贝(不会回传给 SDK)
             所以修改 yuvData 不会影响编码和传输的数据(不会有任何效果)
           # 对于不需要回传数据给 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 资源的释放;如无需要,可以不处理此回调
           # 注意:当使用第三方美颜时,由于释放操作有线程要求,必须在此处调用第三方美颜的释放接口
             否则可能导致释放失败,产生内存泄漏
           # 通过调用 RtcEngine 对象的 setMediaProcessor 方法将 processor 设置为 null 来触发此回调
             例如:mRtcEngine.setMediaProcessor(VideoTexturePreprocessor, null, null);
         */
        mFuRenderer.onSurfaceDestroyed(); // 此行演示对接 FaceUnity 美颜的处理
    }
}

Web

  • Web SDK 目前仅支持在抓取麦克风音频之后发送之前进行数据回调。
  • 调用 stopAudio 后,此回调会自动停止;再次 startAudio 后,此回调会自动继续。
  • 调用 leaveChannel 后,此回调会被销毁;再次 joinChannel 后,需要重新设置。

通过 RtcEngine 的 setMediaProcessor 方法设置媒体处理函数。

示例代码:

rtcEngine.setMediaProcessor('AudioCaptureExProcessor', (dataView, rtcAudioDataFormat) => {
    console.log('AudioCaptureExProcessor: ', dataView, rtcAudioDataFormat);
    // dataView: Int16Array(2048) [ ... ]
    // rtcAudioDataFormat: {type: 0, sampleRate: 48000, channels: 1, bytesPerSample: 16} 
});
Last updated on 2/18/2022
← 美颜音视频外部采集 →
  • 简介
  • Windows (C++)
  • macOS/iOS (Objective-C)
  • Android (Java)
  • Web
浙ICP备20002645号 ©2019-2022 Pano拍乐云