音视频采集
音视频 Track 为音视频交互的基本单位,本文主要介绍音视频 Track 的创建及采集等功能的使用。
- 一路 Track 代表一路音频或者视频的数据
- SDK 支持创建并发布多路音视频 Track。(v5.2.3 之前不支持多音频 Track,重复创建将会失败)
摄像头视频 Track
QNCameraVideoTrack 为摄像头采集的本地 track,其创建方式如下:
QNCameraVideoTrackConfig cameraVideoTrackConfig = new QNCameraVideoTrackConfig(TAG_CAMERA)
.setCameraFacing(QNCameraFacing.FRONT)
.setVideoCaptureConfig(QNVideoCaptureConfigPreset.CAPTURE_640x480) // 配置预览格式
.setVideoEncoderConfig(new QNVideoEncoderConfig(640, 480, 30, 800)); // 配置编码参数
mCameraVideoTrack = QNRTC.createCameraVideoTrack(cameraVideoTrackConfig);
其中:
- QNVideoCaptureConfig 用来配置摄像头采集参数,包括分辨率和帧率等;设置时可以使用 SDK 提供的预设值,详情可参考 QNVideoCaptureConfigPreset。
- QNVideoEncoderConfig 用来配置视频的编码参数,包括分辨率、帧率和码率(kbps)等。
- QNVideoCaptureConfig 和 QNVideoEncoderConfig 的配置可以缺省,SDK 内部默认提供的采集编码参数为 640x480、20fps、800kbps
在创建好 QNCameraVideoTrack 之后,就可以通过调用 SDK 提供的相关方法进行摄像头的相关操作:
设置事件监听
通过调用 QNCameraVideoTrack.setCameraEventListener
接口进行摄像头事件的回调监听。
public void setCameraEventListener(QNCameraEventListener listener);
QNCameraEventListener
回调定义如下:
interface QNCameraEventListener {
int[] onCameraOpened(List<Size> sizes, List<Integer> fpsAscending); // 根据返回的设备能力选择采集参数
void onCaptureStarted(); // 开始采集时触发
void onCaptureStopped(); // 停止采集时触发
void onError(int errorCode, String description); // 摄像头发生错误时触发
}
该回调监听可用来选择期望的采集能力、监听摄像头的相关异常等,详情可参考 QNCameraEventListener 接口文档
开始/停止摄像头采集
通过调用 QNCameraVideoTrack.startCapture
接口进行摄像头采集,通过调用 QNCameraVideoTrack.stopCapture
接口停止摄像头采集,通过调用 QNCameraVideoTrack.play
设置摄像头采集的预览窗口。
public void startCapture();
public void stopCapture();
public void play(QNRenderView view);
- 由于 Android 中的相机资源是单例的,若应用占用了相机资源则会导致其他应用无法获取到相机资源。SDK 支持在通话过程中可以通过
QNCameraVideoTrack.startCapture
获取相机资源,通过QNCameraVideoTrack.stopCapture
释放相机资源。- 若摄像头采集开启失败,会通过 QNCameraEventListener.onError 监听回调错误信息,错误码请参考设备采集相关错误码。
基于 Android 行为变更的声明,Android 9 之后的设备将无法后台进行音视频的采集。
- 若您有后台连麦的需求,可参考 Android 官网相关说明在退后台后使用前台服务让应用正常工作。
- 若您不需要后台连麦,可以在 Activity
onResume
、onPause
等生命周期函数中分别调用 QNCameraVideoTrack.startCapture 和 QNCameraVideoTrack.stopCapture 方法进行 Camera 采集的开启和关闭操作。
开启/关闭预览
通过调用 QNCameraVideoTrack.setPreviewEnabled
接口进行预览画面的开关控制:
public void setPreviewEnabled(boolean isEnabled)
开启/关闭闪光灯
通过调用 QNCameraVideoTrack.turnLightOn
接口开启闪光灯,通过调用 QNCameraVideoTrack.turnLightOff
接口关闭闪光灯:
public boolean turnLightOn()
public boolean turnLightOff()
切换摄像头
通过调用 QNCameraVideoTrack.switchCamera
接口进行摄像头的切换。
public void switchCamera(QNCameraSwitchResultCallback callback)
其中,切换成功与否会通过 QNCameraSwitchResultCallback 回调出来,若不需要结果回调,可以传入 null。
相机在启动或使用过程中可能会遇到一些问题,在此情况下 SDK 会在
QNCameraEventListener.onError
中回调到上层,详情可参考 QNCameraEventListener。
设置缩放
通过调用 QNCameraVideoTrack.setZoom(float zoom)
接口对相机采集的画面进行缩放。需要注意的是 setZoom 里的参数必须是通过调用 QNCameraVideoTrack.getZooms()
接口获取到的列表里的数值,如果 QNCameraVideoTrack.getZooms()
接口获取到的列表为空,即代表不支持缩放设置:
public void setZoom(float zoom);
public List<Float> getZooms();
开启/关闭镜像
SDK 内提供了预览镜像和采集镜像两种镜像接口。通过调用 QNCameraVideoTrack.setPreviewMirror(boolean mirror)
接口即可开启或关闭预览镜像,开启了预览镜像仅仅在本地预览才会镜像,远端看还是正常的画面;通过调用 QNCameraVideoTrack.setMirror(boolean mirror)
接口即可开启或关闭采集镜像,若开启了采集镜像本地预览和远端都将会显示镜像画面:
public void setMirror(boolean mirror);
public void setPreviewMirror(boolean mirror);
美颜
通过调用 QNCameraVideoTrack.setBeauty
接口进行内置美颜的参数配置。其中,美颜的开关可以通过 QNBeautySetting 来设置,具体的美颜配置可以参考 QNBeautySetting。
public void setBeauty(QNBeautySetting beautySetting)
如需接入外部美颜或滤镜,可以通过 QNCameraVideoTrack.setVideoFrameListener
接口设置 QNVideoFrameListener 回调来对接外部第三方美颜或者滤镜。
需要注意的是,由于 Android 摄像头设备角度的原因,在竖屏情况下 SDK 内部会对图像进行旋转,在竖屏情况的宽高设置跟实际图像会有所差别。比如:在横屏情况下发布
1280 * 720
的视频图像,那么设置为new QNVideoEncoderConfig(1280, 720, DEFAULT_FPS, DEFAULT_BITRATE)
即可;但如果想要在竖屏情况下发布720 * 1280
的视频图像,那么由于上述原因应设置为new QNVideoEncoderConfig(1280, 720, DEFAULT_FPS, DEFAULT_BITRATE)
。另外,在 CDN 转推合流配置中的宽高与此处的配置不同,合流配置的宽高需要以实际宽高为准。
屏幕录制视频 Track
QNScreenVideoTrack 为屏幕录制的本地 Track,录屏连麦的主要步骤如下:
判断设备是否支持屏幕录制
屏幕录制依赖 Android 系统版本,可通过 SDK 提供的如下接口判断是否支持:
static boolean isScreenCaptureSupported();
示例代码如下:
boolean isSupported = QNScreenVideoTrack.isScreenCaptureSupported();
发起屏幕录制请求
SDK 提供如下方法进行屏幕请求的发起:
static boolean requestPermission(Activity activity);
示例代码如下:
QNScreenVideoTrack.requestPermission(activity);
当用户同意录屏请求后,会通过系统的 onActivityResult
进行通知,在收到录屏请求的返回后,可通过 SDK 提供的 checkActivityResult
方法进行处理,如果接口返回 true,便可以创建 Screen Track 进行屏幕录制了。
示例代码如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == QNScreenVideoTrack.SCREEN_CAPTURE_PERMISSION_REQUEST_CODE &&
QNScreenVideoTrack.checkActivityResult(requestCode, resultCode, data)) {
// 创建 Screen Track
createScreenTrack();
}
}
创建 Screen Track
在通过了屏幕录制申请后,可以通过如下方式进行 Screen Track 的创建:
QNScreenVideoTrackConfig screenVideoTrackConfig = new QNScreenVideoTrackConfig(Config.TAG_SCREEN_TRACK)
.setVideoEncoderConfig(createEncoderConfig());
mScreenVideoTrack = QNRTC.createScreenVideoTrack(screenVideoTrackConfig);
其中,QNVideoEncoderConfig 用来配置视频的编码参数,包括分辨率、帧率和码率(kbps)等; 录屏时建议分辨率和屏幕分辨率比例保存一致,避免录屏画面有黑边或者不清晰,具体可参考。
外部导入视频 Track
SDK 外部导入视频连麦支持导入 NV21 数据 和 纹理数据 两种格式的数据,使用方式如下:
创建外部导入视频 Track
QNCustomVideoTrack 为外部数据导入视频 track,创建方式如下:
QNCustomVideoTrackConfig customVideoTrackConfig = new QNCustomVideoTrackConfig(TAG_FOR_EXTERNAL_IMPORT_VIDEO)
.setVideoEncoderConfig(new QNVideoEncoderConfig(640, 480, 30, 800));
mCustomVideoTrack = QNRTC.createCustomVideoTrack(customVideoTrackConfig);
数据导入
导入 NV21 数据
SDK 支持导入 NV21 的数据,在创建好 QNCustomVideoTrack 之后,可通过如下方式推送数据:
QNVideoFrame videoFrame = new QNVideoFrame();
videoFrame.buffer = data; // NV21 数据
videoFrame.width = width; // 视频帧的宽度
videoFrame.height = height; // 视频帧的高度
videoFrame.rotation = 0; // 视频帧的角度
videoFrame.timestampNs = ts; // 视频帧的时间戳,以 ns 为单位
mCustomVideoTrack.pushVideoFrame(videoFrame);
为兼容所有机型,导入 NV21 数据时,建议选择软编码的方式进行导入。
导入纹理数据
SDK 支持导入纹理数据,在创建好 QNCustomVideoTrack 之后,可通过如下方式推送数据:
QNVideoFrame videoFrame = new QNVideoFrame();
videoFrame.texture = QNTexture.create(
mTextureType == QNTexture.TextureType.OES ? mOESTexID : mCanvas.getCanvasTexID(),
mTextureType,
mMatrix,
mCanvasThread.getHandler());
videoFrame.width = mWidth;
videoFrame.height = mHeight;
videoFrame.rotation = 0;
videoFrame.timestampNs = ts;
mCustomVideoTrack.pushVideoFrame(videoFrame);
其中:
- TextureType 为纹理类型,需要根据实际类型指定为
OES
或者RGB
。 - Matrix 为 4x4 的纹理变换矩阵。根据纹理类型的不同,处理方式也有所区别:
- 如果推送的纹理为 OES 纹理,则需要传入对应的纹理变换矩阵。
- 如果推送的纹理为 RGB 纹理,则通常只需传入单位矩阵即可。
- 纹理导入需要 OpenGL 上下文,因此,Handler 需要指定为纹理所在线程的 Handler。
麦克风音频 Track
QNMicrophoneAudioTrack 为麦克风采集的音频 Track,如需以麦克风采集数据作为音频源,仅需创建一个 QNMicrophoneAudioTrack 并发布即可,其创建方式如下:
QNMicrophoneAudioTrackConfig microphoneAudioTrackConfig = new QNMicrophoneAudioTrackConfig(TAG_AUDIO)
.setAudioQuality(QNAudioQualityPreset.STANDARD);
mMicrophoneAudioTrack = QNRTC.createMicrophoneAudioTrack(microphoneAudioTrackConfig);
其中,QNAudioQuality 代表音频的质量参数,包括采样率、声道数、位宽以及编码码率,SDK 有提供对应的预设以方便选择,可参考 QNAudioQualityPreset。
注意:
- 从 v5.2.3 开始,SDK 支持同时创建并发布多路音频 Track;v5.2.3 之前仅支持一路音频 Track,QNMicrophoneAudioTrack 和 QNCustomAudioTrack 实例不能同时创建。
- 在音视频通话的场景下,为了获得更好的通话体验,建议使用单声道的音频配置。
外部导入音频 Track
QNCustomAudioTrack 为外部导入音频 track,如需导入音频数据作为音频源,仅需创建一个 QNCustomAudioTrack 即可,然后通过调用 QNCustomAudioTrack.pushAudioFrame(QNAudioFrame frame)
进行外部音频数据的导入。
支持的音频数据格式为:PCM 格式,16 bit 位宽。
使用方式可参考如下示例:
QNAudioFrame audioFrame = new QNAudioFrame(buffer, size, dataWidth, sampleRate, channels);
mCustomAudioTrack.pushAudioFrame(audioFrame);
从 v5.2.3 开始,SDK 支持同时创建并发布多路音频 Track;v5.2.3 之前仅支持一路音频 Track,QNMicrophoneAudioTrack 和 QNCustomAudioTrack 实例不能同时创建。
示例代码
音视频采集场景的示例代码可参考 QNRTC-API-Examples。