human: 如何处理七牛云的实时音视频音视频采集

gpt: [实时音视频](https://developer.qiniu.com/rtc) > 使用指南 > Android >音视频采集

#  音视频采集

最近更新时间: 2023-04-25 10:33:44

音视频 [Track](https://developer.qiniu.com/rtc/quick_start/9909/the-rtc-basic-
concept#track) 为音视频交互的基本单位，本文主要介绍音视频 Track 的创建及采集等功能的使用。

>   * 一路 Track 代表一路音频或者视频的数据
>   * SDK 支持创建并发布多路音视频 Track。（v5.2.3 之前不支持多音频 Track，重复创建将会失败）
>

# 摄像头视频 Track

[QNCameraVideoTrack](https://developer.qiniu.com/rtc/api/8640/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);
    

其中：

  1. [QNVideoCaptureConfig](https://developer.qiniu.com/rtc/api/8700/QNVideoCaptureConfig) 用来配置摄像头采集参数，包括分辨率和帧率等；设置时可以使用 SDK 提供的预设值，详情可参考 [QNVideoCaptureConfigPreset](https://developer.qiniu.com/rtc/api/8731/video-capture-config-preset-android)。
  2. [QNVideoEncoderConfig](https://developer.qiniu.com/rtc/api/8701/QNVideoEncoderConfig) 用来配置视频的编码参数，包括分辨率、帧率和码率（kbps）等。
  3. [QNVideoCaptureConfig](https://developer.qiniu.com/rtc/api/8700/QNVideoCaptureConfig) 和 [QNVideoEncoderConfig](https://developer.qiniu.com/rtc/api/8701/QNVideoEncoderConfig) 的配置可以缺省，SDK 内部默认提供的采集编码参数为 640x480、20fps、800kbps

在创建好
[QNCameraVideoTrack](https://developer.qiniu.com/rtc/api/8640/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](https://developer.qiniu.com/rtc/api/8637/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](https://developer.qiniu.com/rtc/api/8637/QNCameraEventListener#onError)
> 监听回调错误信息，错误码请参考[设备采集相关错误码](https://developer.qiniu.com/rtc/development_guidelines/9904/rtc-
> error-code-android#2)。
>

基于 [Android
行为变更](https://developer.android.com/about/versions/pie/android-9.0-changes-
all#bg-sensor-access)的声明，Android 9 之后的设备将无法后台进行音视频的采集。

  * 若您有后台连麦的需求，可参考 [Android 官网相关说明](https://developer.android.com/guide/topics/media/camera)在退后台后使用[前台服务](https://developer.android.com/guide/components/services?hl=zh-cn#Foreground)让应用正常工作。
  * 若您不需要后台连麦，可以在 Activity `onResume`、`onPause` 等生命周期函数中分别调用 [QNCameraVideoTrack.startCapture](https://developer.qiniu.com/rtc/api/8640/QNCameraVideoTrack#startCapture) 和 [QNCameraVideoTrack.stopCapture](https://developer.qiniu.com/rtc/api/8640/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](https://developer.qiniu.com/rtc/api/8639/QNCameraSwitchResultCallback)
回调出来，若不需要结果回调，可以传入 null。

> 相机在启动或使用过程中可能会遇到一些问题，在此情况下 SDK 会在 `QNCameraEventListener.onError`
> 中回调到上层，详情可参考
> [QNCameraEventListener](https://developer.qiniu.com/rtc/api/8637/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](https://developer.qiniu.com/rtc/api/8636/QNBeautySetting)。

    
    
    public void setBeauty(QNBeautySetting beautySetting)
    

如需接入外部美颜或滤镜，可以通过 `QNCameraVideoTrack.setVideoFrameListener` 接口设置
[QNVideoFrameListener](https://developer.qiniu.com/rtc/api/8704/QNVideoFrameListener)
回调来对接外部第三方美颜或者滤镜。

> 需要注意的是，由于 Android 摄像头设备角度的原因，在竖屏情况下 SDK
> 内部会对图像进行旋转，在竖屏情况的宽高设置跟实际图像会有所差别。比如：在横屏情况下发布 `1280 * 720` 的视频图像，那么设置为 `new
> QNVideoEncoderConfig(1280, 720, DEFAULT_FPS,
> DEFAULT_BITRATE)`即可；但如果想要在竖屏情况下发布 `720 * 1280` 的视频图像，那么由于上述原因应设置为 `new
> QNVideoEncoderConfig(1280, 720, DEFAULT_FPS, DEFAULT_BITRATE)`。另外，在 [CDN
> 转推](https://developer.qiniu.com/rtc/development_guidelines/8770/turn-the-
> cdn-push-android)合流配置中的宽高与此处的配置不同，合流配置的宽高需要以实际宽高为准。

######

# 屏幕录制视频 Track

[QNScreenVideoTrack](https://developer.qiniu.com/rtc/api/8687/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](https://developer.qiniu.com/rtc/api/8701/QNVideoEncoderConfig)
用来配置视频的编码参数，包括分辨率、帧率和码率（kbps）等；
录屏时建议分辨率和屏幕分辨率比例保存一致，避免录屏画面有黑边或者不清晰，具体可[参考](https://github.com/pili-
engineering/QNRTC-Android/blob/master/QNRTC-API-
Examples/app/src/main/java/com/qiniu/droid/rtc/api/examples/activity/ScreenCaptureActivity.java)。

# 外部导入视频 Track

SDK 外部导入视频连麦支持导入 **NV21 数据** 和 **纹理数据** 两种格式的数据，使用方式如下：

## 创建外部导入视频 Track

[QNCustomVideoTrack](https://developer.qiniu.com/rtc/api/8649/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](https://developer.qiniu.com/rtc/api/8649/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](https://developer.qiniu.com/rtc/api/8649/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);
    

其中：

  1. [TextureType](https://developer.qiniu.com/rtc/api/8691/QNTexture#TextureType) 为纹理类型，需要根据实际类型指定为 `OES` 或者 `RGB`。
  2. Matrix 为 4x4 的纹理变换矩阵。根据纹理类型的不同，处理方式也有所区别： 
     * 如果推送的纹理为 OES 纹理，则需要传入对应的纹理变换矩阵。
     * 如果推送的纹理为 RGB 纹理，则通常只需传入单位矩阵即可。
  3. 纹理导入需要 OpenGL 上下文，因此，Handler 需要指定为纹理所在线程的 Handler。

# 麦克风音频 Track

[QNMicrophoneAudioTrack](https://developer.qiniu.com/rtc/api/8667/QNMicrophoneAudioTrack)
为麦克风采集的音频 Track，如需以麦克风采集数据作为音频源，仅需创建一个
[QNMicrophoneAudioTrack](https://developer.qiniu.com/rtc/api/8667/QNMicrophoneAudioTrack)
并发布即可，其创建方式如下：

    
    
    QNMicrophoneAudioTrackConfig microphoneAudioTrackConfig = new QNMicrophoneAudioTrackConfig(TAG_AUDIO)
            .setAudioQuality(QNAudioQualityPreset.STANDARD);
    mMicrophoneAudioTrack = QNRTC.createMicrophoneAudioTrack(microphoneAudioTrackConfig);
    

其中，[QNAudioQuality](https://developer.qiniu.com/rtc/api/8634/QNAudioQuality)
代表音频的质量参数，包括采样率、声道数、位宽以及编码码率，SDK 有提供对应的预设以方便选择，可参考
[QNAudioQualityPreset](https://developer.qiniu.com/rtc/api/8635/QNAudioQualityPreset)。

> **注意：**
>
>   1. 从 v5.2.3 开始，SDK 支持同时创建并发布多路音频 Track；v5.2.3 之前仅支持一路音频
> Track，[QNMicrophoneAudioTrack](https://developer.qiniu.com/rtc/api/8667/QNMicrophoneAudioTrack)
> 和
> [QNCustomAudioTrack](https://developer.qiniu.com/rtc/api/8646/QNCustomAudioTrack)
> 实例不能同时创建。
>   2. 在音视频通话的场景下，为了获得更好的通话体验，建议使用单声道的音频配置。
>

# 外部导入音频 Track

[QNCustomAudioTrack](https://developer.qiniu.com/rtc/api/8646/QNCustomAudioTrack)
为外部导入音频 track，如需导入音频数据作为音频源，仅需创建一个
[QNCustomAudioTrack](https://developer.qiniu.com/rtc/api/8646/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](https://developer.qiniu.com/rtc/api/8667/QNMicrophoneAudioTrack)
> 和
> [QNCustomAudioTrack](https://developer.qiniu.com/rtc/api/8646/QNCustomAudioTrack)
> 实例不能同时创建。

# 示例代码

音视频采集场景的示例代码可参考 [QNRTC-API-Examples](https://github.com/pili-
engineering/QNRTC-Android/tree/master/QNRTC-API-Examples)。

以上内容是否对您有帮助？