合流录制
更新时间: 2021/03/28 14:25:33
本地服务端录制支持单流录制和合流录制模式,默认为单流录制模式,您可以参考本文档在您的本地项目中实现本地服务端合流录制。
本地服务端录制支持以下两种录制模式:
-
单流录制模式。
分别录制房间内每个成员的音频流和视频流。每个成员均有其对应的音频文件和视频文件,您也可以指定每个成员均生成一个音视频文件。
-
合流录制模式。
房间内所有或指定成员的音视频混合录制为一个音视频文件;或房间内所有或指定成员的音频混合录制为一个纯音频文件,所有或指定成员的视频混合录制为一个纯视频文件。
-
单流+合流录制模式。
同时开启单流和合流录制模式,在分别录制房间内每个成员音频和视频流的同时,将房间内所有或指定音视频流混合录制为一个音视频文件。
- 请在开始录制前设置录制模式,开始录制后不支持切换录制模式。
- 如果有用户没有发送音频或视频流,一般不会生成该用户的音频或视频录制文件。本文档以房间内每个用户都发送音频和视频为例。
启用合流录制
-
单独开启合流录制:
在初始化时将参数 mixing_enable 设为 true,并将 auto_subscribe_audio、auto_subscribe_video 设置为 false,即可单独开启合流录制。
-
开启单流+合流录制:
在初始化时将参数 mixing_enable 设为 true,即可在单流录制的同时启用合流模式。在分别录制房间内每个成员音频和视频流的同时,另外将房间内所有或指定音视频流混合录制为一个音视频文件。
根据录制内容的不同,录制生成的文件如下表所示:
录制内容 | 参数设置 | 录制生成文件 |
---|---|---|
仅录制音频 |
|
每个成员生成一个 wav 或 m4a 音频文件。 |
仅录制视频 |
|
每个成员生成一个 yuv 或 mp4 视频文件。 |
同时录制音视频 |
|
|
设置音视频编码配置
合流模式下,您可以自己设置录制文件的音视频编码配置。默认情况下,合流模式和单流模式使用同一套录制参数,即 audioProfile 和 video_record_resolution 设置的录制参数。您也可以参考本文档为合流模式设置特殊的录制参数。 初始化时,将 mixing_param_split 设置为 true,表示合流模式下使用单独的音视频录制参数。此时单流录制仍然使用 audioProfile 和 video_record_resolution 设置的音视频编码配置。合流的录制参数通过 mixing_audioProfile 和 mixing_video_record_resolution 设置。
音频编码配置
合流模式下,您可以自己设置录制文件的音视频编码配置。
mixing_param_split 设置为 true 时,通过 mixing_audioProfile 参数设置合流录制独有的音频编码模式、采样率、声道数和码率。
- kNERtcAudioProfileDefault:默认音频设置,采样率 48 kHz,单声道,编码码率为 48 Kbps。
- kNERtcAudioProfileHight:高音质,采样率 48 kHz,单声道,编码码率 128 Kbps。
- kNERtcAudioProfileStero:高音质立体声,采样率 48 kHz,双声道,编码码率 128Kbps。
设置视频编码配置
mixing_param_split 设置为 true 时,通过 mixing_video_record_resolution 参数可以设置合流录制独有的视频编码相关参数,例如视频码率、帧率、画布宽度和高度。推荐的视频编码配置请参考分辨率、帧率和码率对照表。
设置合流布局
在合流模式录制视频时,您需要在调用 startMixingRecord() 前先调用 setVideoMixingLayout() 进行合流布局。目前支持自适应布局和自定义布局两种模式。详细说明请参考设置合流布局。
注意事项
默认情况下,如果某用户中途停止发流,该用户画面会显示为黑色。您可以通过以下方式设置用户背景图片,当指定用户未发送视频流时,显示该背景图片。
-
初始化时,将 initialize 的 keep_last_frame 参数设置为 true,将该用户的最后一帧视频画面作为其视频画面。
-
加入房间后,通过 setuserbackground 自定义设置用户背景图片,设置后,该用户关闭视频流之后,会显示指定图片作为其视频画面。
示例代码
例如,为合流录制模式下录制一个直播房间里的音视频,音频编码配置为高音质,视频编码配置分别为 640、480、15、400000,合流布局设为自适应布局。
示例代码如下:
cppnerecord::IRecordEngine *engine = (nerecord::IRecordEngine *)createNERecordEngine();
nerecord::NERecordEngineContext ctx;
ctx.auto_subscribe_audio = true;
ctx.auto_subscribe_video = true;
ctx.audio_enable = true;
ctx.video_enable = true;
ctx.default_stream_type = nerecord::kNERtcRemoteVideoStreamTypeHigh;
ctx.mixed_audio_video = true;
ctx.mixing_enable = true;
ctx.decodeAudio = nerecord::kNERtcAudioFormatAAC;
ctx.decodeVideo = nerecord::kNERtcVideoFormatH264;
ctx.video_record_resolution.vanvasWidth = 640;
ctx.video_record_resolution.vanvasHeight = 480;
ctx.video_record_resolution.bps = 400000;
ctx.video_record_resolution.fps = 15;
ctx.snapshot_interval = 10;
ctx.audioProfile = nerecord::kNERtcAudioProfileHight;
engine->initialize(ctx);
engine->joinChannel(<token>, <channel_name>, <uid>);
nerecord::VideoMixingLayout layout;
layout.layout = kNERtcLayoutGrid;
layout.backgroundColor = "#ffffff";
engine->setVideoMixingLayout(layout);
engine->startService();
/*录制中*/
engine->stopService();
engine->leaveChannel();
engine->release();
destroyNERecordEngine((void *&)engine);