音视频外部采集
简介
Pano SDK 支持由开发者进行音视频外部采集(也称自定义采集),支持自行处理音频播放和视频数据渲染。
对于音频,一个简化的音频处理流程如下:
采集* --> 3A前处理* --> 编码 --> 发送 --> 接收 --> Jitter Buffer --> 解码 --> 播放*
* 3A前处理是指:AEC (Acoustic Echo Cancellation 回声消除)、AGC (Automatic Gain Control 自动增益控制)、ANS (Automatic Noise Suppression 自动降噪)
Pano SDK 支持由开发者自行处理采集和播放环节。
各端 SDK 相关接口,请查看下列介绍:
Windows (C++)
音频外部采集与外部播放
通过 RtcEngine
对象的 getAudioDeviceManager
方法获取音频设备管理器(AudioDeviceManager
)。
- 通过
AudioDeviceManager
对象的getExternalRecorder
方法获取外接音频录制设备(RtcExternalAudioRecorder
)。- 通过
RtcExternalAudioRecorder
对象的setEnableStatus
方法设置外接音频录制设备的启用状态 - 通过
RtcEngine
对象的startAudio
方法发送声音 - 通过
RtcExternalAudioRecorder
对象的pushData
方法推送外部采集的音频数据给 Pano SDK
- 通过
- 通过
AudioDeviceManager
对象的getExternalPlayer
方法获取外接音频播放设备(RtcExternalAudioPlayer
)。- 通过
RtcExternalAudioPlayer
对象的setEnableStatus
方法设置外接音频播放设备的启用状态 - 通过
RtcEngine
对象的subscribeAudio
方法订阅其他用户的声音(如果加入频道时配置了自动订阅音频,则无需此步骤) - 通过
RtcExternalAudioPlayer
对象的pullData
方法从 Pano SDK 拉取音频数据如果没有收到任何音频数据包,
pullData
会返回失败,此时开发者往声卡数据填 0 即可
- 通过
- 从 1.6.3 版本开始,
AudioDeviceManager
新增控制接口可以用于外部采集播放场景:startAudioRecording
/stopAudioRecording
开启/关闭音频设备录音startAudioPlayback
/stopAudioPlayback
开启/关闭音频设备播放
- 启用外接音频录制设备后,SDK 将不再采集音频,而使用外部采集的音频数据;
- 启用外接音频播放设备后,SDK 将不再播放音频,而交由外部处理播放音频数据;
- 可以同时启用外接音频录制设备和外接音频播放设备;
- 还可以同时结合 音视频数据回调 功能实现更灵活的高级处理。
视频外部采集
通过 RtcEngine
对象的 getVideoDeviceManager
方法获取视频设备管理器(VideoDeviceManager
)。
- 通过
VideoDeviceManager
对象的createExternalCapturer
方法创建外接视频采集设备(RtcExternalVideoCapturer
) - 通过
RtcExternalVideoCapturer
对象的getDeviceID
方法获取外接视频采集设备ID - 通过
VideoDeviceManager
对象的setDevice
方法设置使用视频采集设备 - 通过
RtcEngine
对象的startVideo
方法发送视频 - 通过
RtcExternalVideoCapturer
对象的putData
方法输入外部采集的视频数据给 Pano SDK
部分示例代码如下。
// 步骤一:设置虚拟的视频采集设备
VideoDeviceManager * videoDeviceManager = rtcEngine->getVideoDeviceManager();
RtcExternalVideoCapturer * externalCapturer = videoDeviceManager->createExternalCapturer();
char deviceId[kMaxDeviceIDLength];
externalCapturer->getDeviceID(deviceId);
videoDeviceManager->setDevice(deviceId);
// 步骤二:加入频道并开启视频
// 收到自己加入频道成功的通知后,调用 startVideo 方法开启视频,此处省略
// 步骤三:输入视频数据
/* 通过 externalCapturer 的 putData(void *buffer, int length, const MediaFormat &format) 方法
输入外部采集的视频数据(YUV I420格式)给 Pano SDK,其中传入视频帧数据地址、字节数和数据格式
下面代码仅示意如何配置 MediaFormat,请注意按实际情况处理
*/
MediaFormat format;
format.mediaType = MediaType::Video;
format.videoFmt.type = VideoType::I420;
format.videoFmt.width = width; // 视频帧的宽度
format.videoFmt.height = height; // 视频帧的高度
format.videoFmt.count = 3; // 固定为 3 个像素平面
format.videoFmt.offset[0] = 0; // Y 的偏移
format.videoFmt.offset[1] = width * height; // U 的偏移
format.videoFmt.offset[2] = format.videoFmt.offset[1] + width * height / 4; // V 的偏移
format.videoFmt.stride[0] = width; // Y 的跨度
format.videoFmt.stride[1] = width / 2; // U 的跨度
format.videoFmt.stride[2] = width / 2; // V 的跨度
format.videoFmt.rotation = VideoRotation::Rotation_0; // 视频帧的旋转角度
format.videoFmt.mirror = false; // 视频帧是否已镜像
视频外部渲染
以下接口均支持设置外部数据接收槽(RtcRenderSink
),来接收渲染数据地址(buffer
),以便开发者自行渲染:
VideoDeviceManager::startPreview
开启本地预览RtcEngine::startVideo
发送本地视频RtcEngine::subscribeVideo
订阅其他用户的视频
macOS/iOS (Objective-C)
音频外部采集与外部播放
- 通过
PanoRtcEngineKit
对象的- externalAudioRecorder
方法获取外接音频录制设备(PanoRtcExternalAudioRecorder
)。- 通过
PanoRtcExternalAudioRecorder
对象的- setEnableStatus:withSampleRate:channels:
方法设置外接音频录制设备的启用状态 - 通过
PanoRtcEngineKit
对象的- startAudio
方法发送声音 - 通过
PanoRtcExternalAudioRecorder
对象的- pushData:withLength:format:timestamp:
方法推送外部采集的音频数据给 Pano SDK
- 通过
- 通过
PanoRtcEngineKit
对象的- externalAudioPlayer
方法获取外接音频播放设备接口(PanoRtcExternalAudioPlayer
)。- 通过
PanoRtcExternalAudioPlayer
对象的- setEnableStatus:withSampleRate:channels:
方法设置外接音频播放设备的启用状态 - 通过
PanoRtcEngineKit
对象的- subscribeAudio:
方法订阅其他用户的声音(如果加入频道时配置了自动订阅音频,则无需此步骤) - 通过
PanoRtcExternalAudioPlayer
对象的- pullData:withLength:format:timestamp:
方法从 Pano SDK 拉取音频数据如果没有收到任何音频数据包,
- pullData:withLength:format:timestamp:
会返回失败,此时开发者往声卡数据填 0 即可
- 通过
- 从 1.6.3 版本开始,
PanoRtcEngineKit
新增控制接口可以用于外部采集播放场景:- startAudioRecording
/- stopAudioRecording
开启/关闭音频设备录音- startAudioPlayback
/- stopAudioPlayback
开启/关闭音频设备播放
- 启用外接音频录制设备后,SDK 将不再采集音频,而使用外部采集的音频数据;
- 启用外接音频播放设备后,SDK 将不再播放音频,而交由外部处理播放音频数据;
- 可以同时启用外接音频录制设备和外接音频播放设备;
- 还可以同时结合 音视频数据回调 功能实现更灵活的高级处理。
视频外部采集
通过 PanoRtcEngineKit
对象的 - getNativeHandle
方法来获取 C++ 的 RtcEngine
句柄,随后按照 C++ 的方式来处理视频外部采集,具体步骤如下。
- 前往 下载中心 下载 Windows SDK (其中包含 C++ 跨平台代码),解压其中的 api 目录,将 .h 文件导入 Xcode 工程。
Windows SDK 版本需要和 macOS/iOS SDK 版本保持一致,否则可能无法正常工作。
- 在 Xcode 中将需要处理视频外部采集的 .m 文件重命名为 .mm 文件。
- 在 .mm 文件中导入 C++ 头文件,例如:
#import "PanoRtcEngine.h"
- 参考 C++ 视频外部采集 的介绍进行处理,部分示例代码如下。
// 步骤一:设置虚拟的视频采集设备(此步骤代码写在 .mm 文件中)
// 需要把 OC 中初始化的用于视频外部采集的 PanoRtcEngineKit 对象传递过来,此处假设为 engineKit
RtcEngine * nativeRtcEngine = (RtcEngine *)[engineKit getNativeHandle];
VideoDeviceManager * videoDeviceManager = nativeRtcEngine->getVideoDeviceManager();
RtcExternalVideoCapturer * externalCapturer = videoDeviceManager->createExternalCapturer();
char deviceId[kMaxDeviceIDLength];
externalCapturer->getDeviceID(deviceId);
videoDeviceManager->setDevice(deviceId);
// 步骤二:开启视频(此步骤代码不必写在 .mm 文件中)
/* onChannelJoinConfirm 返回 kPanoResultOK 表示自己加入频道成功
在收到自己加入频道成功的通知后才能开启视频
此处假设由开发者自行处理本地预览,不需要 SDK 渲染,所以两个参数都传空
如需 SDK 渲染,请传入 View 和 Config
*/
[engineKit startVideoWithView:nil config:nil];
// 步骤三:输入视频数据(此步骤代码写在 .mm 文件中)
// 调用 nativeRtcEngine 的 putData 方法输入外部采集的视频数据
// 部分代码片段请参考 C++ 部分"视频外部采集"章节的"步骤三"
视频外部渲染
PanoRtcEngineKit
类以下接口的 delegate
参数支持由开发者自行实现 PanoRtcRenderDelegate
的 - onRenderVideoData:withLength:format:timestamp:
方法来处理数据。
- startPreviewWithDelegate:profile:
开启本地预览- startVideoWithDelegate:profile:
发送本地视频- subscribeVideo:withDelegate:profile:
订阅其他用户的视频
Android (Java)
音频外部采集与外部播放
- 通过
RtcEngine
对象的getExternalAudioRecorder
方法获取外接音频录制设备接口(RtcExternalAudioRecorder
)。- 通过
RtcExternalAudioRecorder
对象的setEnableStatus
方法设置外接音频录制设备的启用状态 - 通过
RtcEngine
对象的startAudio
方法发送声音 - 通过
RtcExternalAudioRecorder
对象的pushData
方法推送外部采集的音频数据给 Pano SDK
pushData
方法的参数RtcAudioDataFormat format
中,type
设置为0
表示数据类型为 PCM。 - 通过
- 通过
RtcEngine
对象的getExternalAudioPlayer
方法获取外接音频播放设备接口(RtcExternalAudioPlayer
)。- 通过
RtcExternalAudioPlayer
对象的setEnableStatus
方法设置外接音频播放设备的启用状态 - 通过
RtcEngine
对象的subscribeAudio
方法订阅其他用户的声音(如果加入频道时配置了自动订阅音频,则无需此步骤) - 通过
RtcExternalAudioPlayer
对象的pullData
方法从 Pano SDK 拉取音频数据如果没有收到任何音频数据包,
pullData
会返回失败,此时开发者往声卡数据填 0 即可
- 通过
- 从 1.6.3 版本开始,
RtcAudioDeviceManager
(RtcEngine.getAudioMixingMgr
)新增控制接口可以用于外部采集播放场景:startAudioRecording
/stopAudioRecording
开启/关闭音频设备录音startAudioPlayback
/stopAudioPlayback
开启/关闭音频设备播放
- 启用外接音频录制设备后,SDK 将不再采集音频,而使用外部采集的音频数据;
- 启用外接音频播放设备后,SDK 将不再播放音频,而交由外部处理播放音频数据;
- 可以同时启用外接音频录制设备和外接音频播放设备;
- 还可以同时结合 音视频数据回调 功能实现更灵活的高级处理。
视频外部采集
前往 下载中心 下载 Windows SDK (其中包含 C++ 跨平台代码),解压其中的 api 目录,将 .h 文件导入 Android 工程。
Windows SDK 版本需要和 Android SDK 版本保持一致,否则可能无法正常工作。
通过 RtcEngine
对象的 getNativeHandle
方法来获取 C++ 的 RtcEngine
句柄,随后按照 C++ 的方式来处理视频外部采集,部分示例代码如下。
// Java 部分:
// 请先加入频道,收到自己加入频道成功的通知后,再执行下列代码
private long nativeHandle = rtcEngine.getNativeHandle();
// 1. 必须将 nativeHandle 传递到 JNI 中
// 2. 如果开发者需要 Pano SDK 处理本地预览
// 必须将 Android 的视图(IVideoRender)传递到 JNI 中交由 Native 进行渲染
// 如果开发者自行处理本地预览,则无需传递
callNative(long nativeHandle); // 开发者自行处理本地预览,仅传递 nativeHandle
// callNative(long nativeHandle, IVideoRender render); // 需要 SDK 处理渲染
// callNative(long nativeHandle, IVideoRender render, RtcVideoConfig config); // 同时携带视频配置
// JNI 部分:
// callNative 方法中:
RtcEngine * nativeRtcEngine = reinterpret_cast<RtcEngine*>(nativeHandle);
// 步骤一:设置虚拟的视频采集设备
VideoDeviceManager * videoDeviceManager = nativeRtcEngine->getVideoDeviceManager();
RtcExternalVideoCapturer * externalCapturer = videoDeviceManager->createExternalCapturer();
char deviceId[kMaxDeviceIDLength];
externalCapturer->getDeviceID(deviceId);
videoDeviceManager->setDevice(deviceId);
// 步骤二:开启视频
// 如果传递了 RtcVideoConfig 到 JNI 中,请将参数取出后转换为 config 的对应参数
panortc::VideoConfig config;
rtcEngine->startVideo(nullptr, config); // SDK 不处理渲染,渲染窗口传空
// rtcEngine->startVideo(render, config); // SDK 处理渲染
// 步骤三:输入视频数据
// 调用 nativeRtcEngine 的 putData 方法输入外部采集的视频数据
// 部分代码片段请参考 C++ 部分"视频外部采集"章节的"步骤三"
视频外部渲染
以下接口的 IVideoRender render
参数支持由开发者自行实现其 onFrame(VideoFrame videoFrame)
方法来处理数据。
RtcEngine.setLocalVideoRender(IVideoRender render)
设置本地用户的视频画布RtcEngine.setRemoteVideoRender(long userId, IVideoRender render)
设置远端用户的视频画布
示例代码:
public class MyRtcView implements IVideoRender {
...
@Override
public void onFrame(VideoFrame videoFrame) {
// 由开发者自行处理 VideoFrame
}
}