自定义采集和渲染

最后更新时间:2021-10-18 10:21:53

    内容介绍

    • 自定义视频采集
      如果您自研(或者购买第三方)美颜和特效处理模块,则需要自己采集和处理摄像头拍摄画面,您可以通过 TRTCCloud 的 enableCustomVideoCapture 接口关闭 TRTC SDK 自己的摄像头采集和图像处理逻辑。然后您可以使用 sendCustomVideoData 接口向 TRTC SDK 填充您自己的视频数据。
    • 自定义视频渲染
      TRTC SDK 使用 OpenGL 进行视频画面的渲染,如果您是用在游戏开发中,或者需要在自己的界面引擎中嵌入 TRTC SDK,那么就要自己渲染视频画面。
    • 自定义音频采集
      如果您是在特殊硬件设备上使用 TRTC SDK,当需要外接声音采集设备并自己采集声音数据时,您可以通过 TRTCCloud 的 enableCustomAudioCapture 接口关闭 TRTC SDK 默认的声音采集流程。然后您可以使用 sendCustomAudioData 接口向 TRTC SDK 填充您自己的声音数据。
      注意:

      开启自定义音频采集后,有可能会导致回声抵消(AEC)的功能失效。

    • 获取音频原数据
      声音模块是一个高复杂度的模块,SDK 需要严格控制声音设备的采集和播放逻辑。在某些场景下,当您需要获取远程用户的音频数据或者需要获取本地麦克风采集到的音频数据时,可以通过 TRTC SDK 提供的相应的回调接口来实现。

    支持的平台

    iOS Android Mac OS Windows Web端 Flutter 端
    ✓(Web 端 ×

    自定义视频采集

    您可以通过 TRTCCloud 的 enableCustomVideoCapture 接口关闭 TRTC SDK 自己的摄像头采集和图像处理逻辑。然后您可以使用 sendCustomVideoData 接口向 TRTC SDK 填充您自己的视频数据。

    sendCustomVideoData 接口中有一个叫 TRTCVideoFrame 的参数,它表示一帧视频画面。为了避免不必要的性能损失,对于输入 TRTC SDK 的视频数据,在不同平台上有不同的格式要求,具体要求如下:

    TRTC SDK 支持 NV12 和 i420 两种 iOS 版本的 YUV 数据格式。在 iOS 平台上,比较高性能的图像传递方式是 CVPixelBufferRef,因此我们建议参数格式如下:

    参数名称参数类型推荐取值备注说明
    pixelFormatTRTCVideoPixelFormatTRTCVideoPixelFormat_NV12iOS 平台上摄像头原生采集出的视频格式即是 NV12。
    bufferTypeTRTCVideoBufferTypePixelBufferiOS 中原生支持的视频帧格式,性能最佳。
    pixelBufferCVPixelBufferRef如果 TRTCVideoBufferType 是 PixelBuffer,则需填写。iPhone 摄像头采集的数据是 NV12 格式的 PixelBuffer。
    dataNSData*如果 TRTCVideoBufferType 是 NSData,则需填写。性能不如 PixelBuffer。
    timestampuint64_t0可以填0,这样 SDK 会自定填充 timestamp 字段,但请均匀地控制 sendCustomVideoData 的调用间隔。
    widthuint64_t视频画面的宽度请严格填写传入画面的像素宽度。
    heightuint32_t视频画面的高度请严格填写传入画面的像素高度。
    rotationTRTCVideoRotation不填写
    • 默认不填写。
    • 如果需要对画面进行旋转,可以填写TRTCVideoRotation_0TRTCVideoRotation_90TRTCVideoRotation_180TRTCVideoRotation_270。SDK 会根据这个值将视频顺时针旋转对应角度。例如一个竖屏画面,传入TRTCVideoRotation_90后,SDK 会旋转成横屏显示。

    示例代码

    Demo 文件夹中有一个叫做 LocalVideoShareViewController.m 的文件,它展示了如何从一个本地视频文件中读取出 NV12 格式的 PixelBuffer,并通过 SDK 进行后续处理。

    //组装一个 TRTCVideoFrame 并将其送给 trtcCloud 对象
    TRTCVideoFrame* videoFrame = [TRTCVideoFrame new];
    videoFrame.bufferType = TRTCVideoBufferType_PixelBuffer;
    videoFrame.pixelFormat = TRTCVideoPixelFormat_NV12;
    videoFrame.pixelBuffer = imageBuffer;
    videoFrame.rotation = rotation;
    videoFrame.timestamp = timeStamp;
    
    

    [trtcCloud sendCustomVideoData:videoFrame];

    自定义视频渲染

    TRTC SDK 使用 OpenGL 进行视频画面的渲染,如果您是用在游戏开发中,或者需要在自己的界面引擎中嵌入 TRTC SDK,那么就要自己渲染视频画面。

    通过 TRTCCloud 的 setLocalVideoRenderDelegatesetRemoteVideoRenderDelegate 可以设置本地和远程画面的自定义渲染回调,相关参数如下:

    参数名称参数类型推荐取值备注说明
    pixelFormatTRTCVideoPixelFormatTRTCVideoPixelFormat_NV12-
    bufferTypeTRTCVideoBufferTypeTRTCVideoBufferType_PixelBufferiOS 中原生支持的视频帧格式,性能最佳。

    示例代码

    如果 pixelFormat 选择了 TRTCVideoPixelFormat_NV12,bufferType 选择了 TRTCVideoBufferType_PixelBuffer,那么整个您可以很方便地将一帧 NV12 格式的 PixelBuffer 转成一副视频画面。在 Demo 文件夹中有一个叫做 TestRenderVideoFrame.m 的文件,其中就用如下的示例代码展示了如何使用该方法。

    - (void)onRenderVideoFrame:(TRTCVideoFrame *)frame 
                                  userId:(NSString *)userId 
                            streamType:(TRTCVideoStreamType)streamType
    {
      //userId是nil时为本地画面,否则为远端画面
      CFRetain(frame.pixelBuffer);
      __weak __typeof(self) weakSelf = self;
      dispatch_async(dispatch_get_main_queue(), ^{
          TestRenderVideoFrame* strongSelf = weakSelf;
          UIImageView* videoView = nil;
          if (userId) {
              videoView = [strongSelf.userVideoViews objectForKey:userId];
          }
          else {
              videoView = strongSelf.localVideoView;
          }
          videoView.image = [UIImage imageWithCIImage:[CIImage imageWithCVImageBuffer:frame.pixelBuffer]];
          videoView.contentMode = UIViewContentModeScaleAspectFit;
          CFRelease(frame.pixelBuffer);
      });
    }
    

    自定义音频采集

    您可以通过 TRTCCloud 的 enableCustomAudioCapture 接口关闭 TRTC SDK 默认的声音采集流程。然后您可以使用 sendCustomAudioData 接口向 TRTC SDK 填充您自己的声音数据。

    sendCustomAudioData 接口中有一个叫 TRTCAudioFrame 的参数,它表示一帧 20ms 长度的音频数据:

    • 通过 sendCustomAudioData 向 SDK 投送的数据必须是 PCM 格式的未经压缩的音频裸数据,不可以是 AAC 或者其他的压缩格式。
    • sampleRate 和 channels 分别代表声音采样率和声道数,请保持跟传入的 PCM 数据严格一致。
    • 每帧音频数据的时长推荐是20ms,我们可以计算一下,如果 sampleRate 为48000,声道数是1(单声道),那么每次调用 sendCustomAudioData 时传入的 buffer 长度应该是:48000 * 0.02s * 1 * 16bit = 15360bit = 1920字节。
    • timestamp 可以为0,当 timestamp 为0时,SDK 会自动填充音频时间戳。因此,为了确保音频时间戳的稳定,请均匀地调用 sendCustomAudioData,保持20ms一次的频率,否则会导致声音出现断断续续的效果。
    注意:

    使用 sendCustomAudioData 有可能会导致回声抵消(AEC)的功能失效。

    获取音频原数据

    声音模块是一个高复杂度的模块,SDK 需要严格控制声音设备的采集和播放逻辑。在某些场景下,当您需要获取远程用户的音频数据或者需要获取本地麦克风采集到的音频数据时,可以通过 TRTCCloud 对应的不同平台的接口,来给 SDK 集成三个回调函数。

    TRTCCloud 对应的不同平台的接口分别为:
    • iOS:setAudioFrameDelegate。
    • Android:setAudioFrameListener。
    • Windows:setAudioFrameCallback。
    接口 说明
    onCapturedAudioFrame 获取本地麦克风采集到的音频源数据。在非自定义采集模式下,SDK 会负责麦克风的声音采集工作,但您可能也需要拿到 SDK 采集到的声音源数据,通过此回调函数就可以获取。
    onPlayAudioFrame 该函数会回调每一路远程用户的声音数据,这是混音前的数据。如果您要对某一路的语音进行语音识别,就可以用到这个回调。
    onMixedPlayAudioFrame 各路音频数据混合后,在送到扬声器播放之前,会通过此函数回调出来。
    注意:

    • 不要在上述回调函数中做任何耗时操作,建议直接拷贝,并通过另一线程进行处理,否则会导致声音断断续续或者回声抵消(AEC)失效的问题。
    • 上述回调函数中回调出来的数据都只允许读取和拷贝,不能修改,否则会导致各种不确定的后果。