Skip to content

实时音视频

qinwei edited this page Dec 16, 2022 · 6 revisions

RTC

RTC(Real time communication)实时通信,是实时音视频的一个简称,它最大的特点就是低延时和无卡顿,一般都可以达到毫秒级延迟。在房间场景有大量应用,比如聊天室麦上主持聊天、游戏开黑房语音交流、直播间连麦、在线K歌等。

要实现一套实时音视频服务的搭建还是比较困难的,虽然 RTC 发展了很多年,但是音视频的技术门槛高,涉及到的传输协议多且复杂,如果采用纯自建的方式,成本会有点大,所以一般都会购买外部云商的服务来实现。

SONA 中使用的是 即构和腾讯云的TRTC ,所有对接云商的工作都集成了,只需要配置相关的云商 appid 和 秘钥、域名等,不需要额外工作。并且可以支持热切,在不同云商之间进行切换,万一某一个云商出现故障,可以瞬间切换到其他云商。 如果需要对接其他的外部云商,也可以非常简单的集成进来。

比心内部也自研了一套 WebRTC 服务,叫做 Starlink,基于 mediasoup 二次开发。使用mercury长连网关做rtc信令传输,并集成进 sona 中,提供和外部云商同等的功能,目前在一些小流量场景使用,后续功能完善后,也会考虑开源出来

音视频配置

在 t_product_config 和 t_room_config 配置表中有几个 音视频相关的配置字段

  • stream_supplier 流供应商(TENCENT/ZEGO)
  • type 流类型 AUDIO=音频 VIDEO=视频
  • push_mode 推流模式
  • pull_mode 拉流模式(MULTI,MIXED)
  • need_replay 是否需要流录制
  • bitrate 播放器码率

在 sona-service 的 apollo 上添加 即构和 TRTC 相关的配置 apollo

每个房间都可以指定外部云商, 推/拉流的方式, 播放器类型, 码率等. 也可以按照房间ID进行特殊配置, 该配置在APP调用 sona/enter 接口的时候会返回给APP端进行使用。

音视频架构

音视频

麦上用户(主播)使用 RTC 推拉流,即构会将所有流转推给 CDN,麦下用户(观众)通过 rtmp 从 CDN 拉流

腾讯云的 TRTC 和 即构类似

可以通过房间配置,指定观众采用拉CDN单流还是CDN混流

云商回调

云商会提供相应的回调,包括 推流回调、关流回调、录制回调、混流回调等

所有流记录都存储在 t_room_stream 表中,方便后续审查做内容回溯

CREATE TABLE `t_room_stream` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `stream_id` varchar(255) NOT NULL COMMENT '流ID',
  `product_code` varchar(16) NOT NULL DEFAULT '' COMMENT '产品码',
  `room_id` bigint(32) NOT NULL DEFAULT '0' COMMENT '房间ID',
  `biz_room_id` varchar(512) DEFAULT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1:打开 0:关闭 -1:未开始',
  `uid` bigint(32) NOT NULL DEFAULT '0' COMMENT '用户UID',
  `source` int(2) NOT NULL DEFAULT '1' COMMENT '来源 1:zego 2:tecent',
  `rtmp_url` varchar(1023) NOT NULL DEFAULT '' COMMENT 'rtmp_url',
  `hls_url` varchar(1023) NOT NULL DEFAULT '' COMMENT 'hls_url',
  `hdl_url` varchar(1023) NOT NULL DEFAULT '' COMMENT 'hdl_url',
  `pic_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'pic_url',
  `replay_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'replay_url',
  `begin_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开始时间',
  `close_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '关闭时间',
  `end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间',
  `close_type` int(2) NOT NULL DEFAULT '-1' COMMENT '0-正常关闭 1-后台超时关闭 2-同一主播直播关闭之前 没有关闭的流',
  `err_msg` varchar(256) NOT NULL DEFAULT '' COMMENT '错误描述',
  `ext` varchar(1024) NOT NULL DEFAULT '' COMMENT '扩展信息',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unq_stream_id` (`stream_id`),
  KEY `idx_room_id_status_uid` (`room_id`,`status`,`uid`),
  KEY `idx_room_id_status_source` (`room_id`,`status`,`source`),
  KEY `idx_uid_status` (`uid`,`status`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='sona音视频流记录表';

ZEGO 控制台配置回调地址

TRTC 控制台配置回调地址

流回调

云商回调的处理都在 sona-service 中的 cn.bixin.sona.api.room.SonaStreamCallbackRemoteService

public interface SonaStreamCallbackRemoteService {

    /**
     * 处理创建回调
     */
    Response<Boolean> handleCreateStreamCallback(CreateStreamCallback request);

    /**
     * 处理关闭流回调
     *
     * @param callback: {@link CloseStreamCallback}
     * @return: true success, otherwise false
     */
    Response<Boolean> handleCloseStreamCallback(CloseStreamCallback callback);

    /**
     * 处理回放回调
     *
     * @param callback: {@link CreateReplayCallback}
     * @return: true success, otherwise false
     */
    Response<Boolean> handleCreateReplayCallback(CreateReplayCallback callback);

    /**
     * 处理混流开始回调
     *
     * @param callback: {@link CloseStreamCallback}
     * @return: true success, otherwise false
     */
    Response<Boolean> handleMixStreamStartCallback(MixStreamStartCallback callback);

    /**
     * 处理混流结束回调
     *
     * @param callback: {@link CreateReplayCallback}
     * @return: true success, otherwise false
     */
    Response<Boolean> handleMixStreamEndCallback(MixStreamEndCallback callback);
}

如果想要增加其他云商,可以按照下述步骤:

  1. 在 sona-web 里面添加对应云商的回调接口,封装参数调用 SonaStreamCallbackRemoteService 对应的方法,可以参考 ZegoControllerTencentController
  2. 继承 cn.bixin.sona.server.room.strategy.stream.DefaultStrategy,实现新云商相关的逻辑处理
  3. 在房间配置表里设置 stream_supplier 为新的云商name
  4. 在 sona/enter 接口中返回新云商的配置,比如 appid、secret等

混流

如果当前房间配置了混流模式,sona 服务端会基于云商的推流回调,然后调用云商的发起混流接口,这样观众就可以通过sona/enter获取到后端下发的 streamUrl 从CDN拉取混流了

针对于混流时调用Zego API(外网调用)可能会受到网络的波动而造成一些异常情况, 例如: 发起混流请求过频, 混流接口超时, 混流失败等.

所以必须有一些可降级的措施, 目前降级的措施为: 通过捕捉Zego返回码判断混流失败的原因, 在重试一定次数后如果还失败, 将会调用热切服务, 将混流配置(MIXED)修改为单流(MULTI), 并通过房间消息同步给各个客户端

云商热切

云商服务有时候也会出现故障,sona 提供了 热切操作来规避这种风险,可以同云商之间 单流-混流 的切换,也可以不同云商之间的切换。

在sona 后台管理系统中提供了 云商热切 页面,可以在页面上进行操作,根据 roomId 进行切换 sona-admin

热切的实现也比较简单,调用热切接口之后,会先更新 房间配置信息,然后判断当前房间是否有在线用户,有的话就通过房间消息推送给当前房间内的所有用户,告知客户端配置切换。

Clone this wiki locally