服务端合流
业务场景
合流是把多路音视频流混合成单流的技术。
在实时音视频互动环节,每个参与者都会发布一路流,但多路流在进行旁路转推、云端存储时多路流并不是最好的方式,例如:
- 旁路转推:需要将实时音视频直播转推给更多的观众,让观众可以实时看到会议实况,如果不进行混流,可能会造成多路流的同步问题以及带宽压力。
- 云端存储:需要将多人音视频通话的内容在云端存储,用于备查、内容审核或二次传播。如果不进行混流直接存储,可能会造成内容管理困难以及存储成本的上升。
服务端合流
服务端合流和客户端合流
合流的过程可以在客户端合流和服务端合流。
客户端合流对用户的手机配置、网络环境都有比较高的要求,合流的过程 CPU 使用会飙升,导致手机发烫;若负责合流的客户端网络环境不好,观众端可能无法看到流畅的画面,因此对于业务场景的限制也会比较大;但也正是因为合流转码的过程是在客户端完成,不会产生额外的成本,因此成本相对较低。
相对于客户端合流,由于服务端合流的过程在服务端完成,网络质量和对客户端的手机配置、网络环境没有严格要求,即使在客户端配置不高、网络环境一般的情况下,也可以保证观众端相对流畅的观看体验,因此可以适应更多的业务场景。但因为转码的过程是在服务端完成,会产生额外的合流计算费用。
手机 CPU 占有 | 网络要求 | 适用场景 | 成本 | |
---|---|---|---|---|
服务端合流 | 低 | 普通 | 较多 | 较高 |
客户端合流 | 高 | 较高 | 局限 | 较低 |
服务端合流的过程
以 N 人音视频互动同时旁路直播的场景为例: (1)互动阶段:每个互动参与者都会将自己的 1 路流发布至互动服务器(RTC Server)同时订阅远端的 N-1 路流,实现多人的实时音视频会话。 (2)合流阶段:服务端根据预先设置的合流后的画面配置(分辨率、帧率、码率),以及客户端发送的画面排布的信令,将 N 路流合成为 1 路流。 (3)直播阶段:媒体服务器(Media Streaming Server)将合流后的 1 路流以 RTMP/HLS 协议分发至普通观众端。
接入流程
服务端:设置合流后的音视频参数
合流后的推流画面尺寸、码率、帧率等参数是 APP 层全局设置,一个 APP 共享一套配置。七牛提供服务端 API 接口设置或用户管理界面两种设置方法。
在实时音视频云的 Portal 用户后台,左侧列表可以看到所有新建好的应用,点击具体某个应用 ID 可以查看详细的应用信息,点击编辑,即可设置合流参数。下面对关键配置进行说明: (1)关联直播空间:如果需要进行旁路直播或落存储,则必须配置对应使用的直播空间;若没有直播空间,需要进行创建。这里选择我们已经创建好的 sdk-live 直播空间。 (2)连麦合流转推:
- 是否启用:如果需要进行旁路转推,则必须开启该服务。
- 只合成音频:如果合流后希望只保留纯音频而没有任何视频帧,则需要选中该项;否则,即使所有的输入流的视频都设置不可见,合流仍然会输入黑色画面。
- 合流输出尺寸:合流画面的分辨率。
- 合流输出帧码率:合流画面的帧率、码率。
- StreamTitle:是转推至七牛直播空间的流名,支持设置魔法变量,魔法变量以$(XX)表示,目前魔法变量有四个:
魔法变量名 | 代表含义 |
---|---|
$(app) | 表示连麦应用的 ID |
$(hub) | 表示连麦应用关联的直播空间名称 |
$(roomName) | 表示连麦房间号 |
$(timestamp) | 表示时间戳 |
支持多个魔法变量拼接,例如:$(app)$(roomName) 表示 '应用ID房间号'。
下图中, 流名称 StreamTitle 填写** $(roomName) **,表示在对应的直播空间中,连麦互动的房间名称与对应旁路直播的流名称一致。
若希望通过 API 设置合流参数,可参考服务端 UpdateApp
的接口说明 设置合流参数。
Host rtc.qiniuapi.com
Post /v3/apps/<AppID>
Authorization: qiniu mac
{
"hub": "<Hub>",
"title": "<Title>",
"maxUsers": <MaxUsers>,
"noAutoKickUser": <NoAutoKickUser>,
"mergePublishRtmp": {
"enable": <Enable>,
"audioOnly": <AudioOnly>,
"height": <OutputHeight>,
"width": <OutputHeight>,
"fps": <OutputFps>,
"kbps": <OutputKbps>,
"url": "<URL>",
"streamTitle": "<StreamTitle>"
}
}
客户端:多用户的画面布局
在客户端 SDK 提供setMergeStreamLayout
这个接口,可以设置各个互动用户的画面布局的的位置、尺寸、以及层次(允许重叠)。
在流发布/订阅成功后,调用合流setMergeStreamLayout
即可开始进行合流,各个端的具体接口参考 :
各个端接口均有以下关键参数,具体参数名称及类型以各端文档为准。
参数含义 | 参数名 | 备注 |
---|---|---|
待合流的用户 Id | userId | 本次设置所对应的 userId |
在合流画面中的 x 轴坐标 | x | 左上角为合流画面坐标原点 |
在合流画面中的 y 轴坐标 | y | 左上角为合流画面坐标原点 |
合流画面中的层次 | z | 0 在最底层,层次越往上数字越大 |
在合流画面中的宽度 | width | 0 表示停止合并当前流到合流画面 |
在合流画面中的高度 | height | 0 表示停止合并当前流到合流画面 |
示例
假设 A 、B 两个用户分别输入两个流,初始分辨率均为 1280 × 720 。合流后希望得到画面分辨率同样为 1280 × 720 的合流画面。若想实现下图 A 的画面全部铺满合流画面、B 的画面的分辨率重置为 350 × 350 并占右下角的画面布局。
- A 的参数设置:userId = A , x = 0 , y = 0 , z = 0 , width = 1280 , height = 720
- B 的参数设置:userId = B , x = 930 , y = 370 , z = 1 , width = 350 , height =350
由于 B 的画面在合流后的分辨率和比例均与原始流不同,服务端会根据实际设置的比例和大小进行自适应调整再与 A 的画面进行合流。
合流权限配置建议
从最大的灵活性上考虑,在 SDK 的接口设计上,房间里的每一个用户都被允许配置合流布局,但实际的业务场景中对于合流布局的权限应该有所区分:
主播观众一对一连麦
在这种场景下,房间中固定只有 2 个用户,一个为主播一个为观众。一般来说这种情况下布局已经是固定的了,主播占据画面主部分,观众占据画面附部分。所以完全可以在端上通过判断当前用户角色直接调用自己角色相应的合流配置。即每个用户自己通过角色来控制自己的合流配置。
if (当前用户是主播) {
myRTC.setMergeStreamLayout({...主播的合流配置...})
} else {
myRTC.setMergeStreamLayout({...观众的合流配置...})
}
多人连麦
在多人连麦的场景下整个合流过程就显得比较复杂了。如果类似于一对一连麦的方案,让各个用户控制自己的合流配置,面对房间中随时会出现的用户离开/用户加入等情况,整个的合流布局就可能会因此发生变动。也就是说,一个用户的 加入/离开 可能会导致多个用户的合流配置需要更新,在这种情况下,我们不推荐单个用户控制自己的合流配置,转而让一个用户去控制房间中所有用户的合流配置可能是更好的方案。
我们的合流模版使用的也是这种方案,所以调用合流模版时需要确保房间中只有一个人调用。在这种设计下,让一个用户去监听房间所有的流状态事件,统一控制布局来控制这个房间所有用户的合流画面。
大家可能会发现,负责合流的用户在这个设计中扮演重要的角色,如果负责合流的用户退出,如何继续连麦?在这里,我们也分为 2 种情况讨论
(1)有房主概念的多人连麦 在这种场景前提下,房间会有一个房主的概念,房主退出房间关闭。所以在这种场景下,直接使用上文中多人连麦的逻辑就可以了,即将房主设置成负责合流的用户,当房主退出,就直接关闭房间就好。
(2)无房主概念的多人连麦(视频会议等) 在这种场景下,就会面临着负责合流的用户可能会退出的问题。事实上,就算负责合流的用户退出,合流也不会停止(除非调用 stopMergeStream)。所以,我们只需要重新选择一个房间内的用户来掌管合流权限就能无缝的继续控制合流画面更新。
在这里,重新选择房间内用户来控制合流权限就需要业务服务器的配合了,在合流权限交接的过程中,必须要保证 2 点。
- 交接前后房间中只能有一人控制合流
- 交接过程同时需要提供一定的信息,使得新合流用户可以复现当前的合流布局
这里再多说一句,因为 SDK 合流控制本身并没有太多的限制和要求,所以上述 2 种方案仅仅是其中一种解决方案,在有业务服务器的配合下,完全可以根据自己的实际业务需求定制自己的合流逻辑。
旁路直播
客户端开始进行合流以后,即可在七牛直播云中查看旁路直播。 上文中配置的旁路直播空间是“sdk-live”;旁路直播的流名称设置为魔法变量 $(roomName),我们可以选择 roomName= wetest 的房间开始合流。
打开七牛直播用户管理界面 ,进入“云直播”模块。 选择 “sdk-live” 直播空间,进入 “直播流管理” 模块,即可看到包括流名称为 wetest 在内的所有活跃流,可以查看该流的实时信息,以及 RTMP、HLS、FLV 的播放地址。