直播在生活中可谓是无处不在,越来越多的企业、开发者们正在搭建自己的直播平台。由于直播平台本身所涉及到的如推拉直播流、直播转码、直播截图、直播混流、直播间聊天室、直播间互动(点赞、送礼、连麦)、直播间状态管理等需求往往比较复杂,本文章以腾讯云相关产品(腾讯云即时通信 IM、腾讯云直播 CSS )为基础,梳理了在搭建直播间过程中常见的需求的实现方案,以及可能遇到的问题、需要注意的细节点等,希望能帮助开发者们快速的理解业务、实现需求。
使用腾讯云搭建直播间首先要在 控制台 创建一个即时通信 IM 应用,如下图所示:
搭建直播间,少不了直播功能,直播功能可以通过 云直播 来实现。需要添加推流及播放域名,如下图所示:
操作详情请参见 添加自有域名。
准备工作步骤一中创建的应用为体验版,只适合在开发阶段使用,正式环境用户可结合自己业务需求,开通专业版或旗舰版。不同版本之间的差异可参见 即时通信 IM 价格文档。
在直播场景中,除了创建应用之外,还需要一些额外的配置:
在 IM 的账号体系中,用户登录需要的密码由用户服务端使用 IM 提供的密钥计算,用户可参见 UserSig计算 文档,在开发阶段,为了不阻塞客户端开发,也可在 控制台计算 UserSig ,如下图所示:
在直播过程中,可能需要管理员向直播间发送消息、禁言(踢出)违规用户等,这时就需要使用 即时通信 IM 服务端 API 来进行相应的处理,调用服务端api前需要 创建 IM 管理员账号,IM 默认提供一个 UserID 为 administrator 的账号供开发者使用,开发者也可以根据业务的场景,创建多个管理员账号。需要注意的是,IM 最多创建五个管理员账号。
在实现直播间弹幕抽奖、消息统计、敏感内容检测等需求时,需要用到 IM 的回调模块,即 IM 后台在某些特定的场景回调开发者业务后台。开发者只需要提供一个 HTTP 的接口并且配置在 控制台 > 回调配置 模块即可,如下图所示:
在准备工作都完成好后,需要将即时通信 IM 以及云直播 CSS 的客户端 SDK 集成到用户项目中去。开发者可以根据自己业务需要,选择不同的集成方案。
即时通信 IM 可参见 IM 快速集成系列文档,
云直播 CSS 可参见 直播 SDK 快速集成系列文档。
接下来文章梳理了直播间中常见的功能点,提供最佳实践方案供开发者参见,并附上相关实现代码。
直播间的状态一般分为如下几种:
序号 | 直播间的状态 |
---|---|
1 | 直播待开始 |
2 | 直播中 |
3 | 直播暂停 |
4 | 直播结束 |
5 | 直播回放中 |
序号 | 特点 |
---|---|
1 | 直播间状态的更改需要实时通知直播间用户 |
2 | 新进入直播间用户需要获取当前直播间状态 |
综上,这里提供两种实现方案。并分析两种方案的优缺点。
两种实现方案 | 优点 | 缺点 |
---|---|---|
业务后台维护直播间状态,使用 IM 服务端 API 发送 群自定义消息 通知群内用户。 | 需要频繁多次获取直播间状态时,相比于将直播间状态存 IM 群资料,直播间状态存业务后台可以减少 IM SDK 的调用频率。 提供在未集成 IM SDK 地方提供获取直播间状态的可能。 |
需要业务后台额外提供读写直播间状态模块。 增加获取直播间数据异常概率,直播间数据来自业务后台和 IM 群资料两部分。 发送自定义消息有丢失的可能,当消息量特别大时,低优先级消息会优先被丢弃从而影响直播间状态的显示。因此这里建议使用高优先自定义消息。 |
通过群自定义字段或者群属性存储直播间状态,通过客户端 SDK 群属性更改回调 通知群内用户。 | 开发者不需要提供额外的读写直播间状态模块。 群属性变更回调理论上不存在丢失可能。 直播间数据都从群资料中获取,统一数据源,减少异常。 |
在高曝光模块需要频繁获取群资料,增大 IM 压力。 在未集成 IM SDK 模块,需要通过业务后台调用 IM 服务端 SDK 获取群资料。且调用频率有限制。 |
通过上面的分析,我们建议使用方案一与方案二相结合的方式,维护直播间状态:
在直播这个场景,用户聊天区域有以下特点:
所以根据 IM 的 群特性,这里选择 AVChatRoom 作为直播间的群类型。
即时通信 IM 的直播群(AVChatRoom)有以下特点:
说明:IM Web SDK 限制同一用户在同一时间内,只能进入一个 AVChatRoom,在 IM 的多端登录场景,如果用户登录终端一在直播间 A 观看直播,在 控制台配置 允许多端登录情况下,该用户登录终端二进入直播间 B 观看,这时终端一的直播间 A 会被退群。
直播间公告(主题)是每个直播间必备的内容,用户进入直播间可以看到该直播间的基本信息。同时,直播间公告也需要更改后实时通知给直播群中的群成员。与群直播状态类似,可以将直播状态存储在客户业务后台或者 IM 的群资料。区别于直播间状态,直播间公告有一些额外的事项,需要开发者关注。如下:
直播间公告可通过 服务端 API 或者客户端 SDK 设置群属性来设置。客户端通过获取群属性来获取当前群信息,可通过监听 GroupListener 中的 OnGroupInfoChange 来获取更改的群属性。
相关代码示例:
// 客户端获取群资料
V2TIMManager.getGroupManager().getGroupsInfo(groupIDList, new V2TIMValueCallback<List<V2TIMGroupInfoResult>>() {
@Override
public void onSuccess(List<V2TIMGroupInfoResult> v2TIMGroupInfoResults) {
// 获取群资料成功
}
@Override
public void onError(int code, String desc) {
// 获取群资料失败
}
});
// 客户端修改群资料
V2TIMGroupInfo v2TIMGroupInfo = new V2TIMGroupInfo();
v2TIMGroupInfo.setGroupID("需要修改的群 ID");
v2TIMGroupInfo.setFaceUrl("http://xxxx");
V2TIMManager.getGroupManager().setGroupInfo(v2TIMGroupInfo, new V2TIMCallback() {
@Override
public void onSuccess() {
// 修改群资料成功
}
@Override
public void onError(int code, String desc) {
// 修改群资料失败
}
});
直播间的特色之一是用户的消息量非常大,每个用户可能都会频繁的刷消息。当上行消息达到 IM 的频控阈值时,IM 后台会丢弃部分消息,来保证系统的稳定运行。其实当消息达到客户端的频率太高,消息的可读性也降低了,所以对直播群消息进行频控是非常有必要的。
群消息分为 3 个优先级,后台会优先下发高优先级的消息。因此用户应根据消息的重要程度,来选择合适的优先级。
3个优先级从高到低,分别如下:
优先级 | 含义 |
---|---|
High | 高优先级 |
Normal | 正常优先级 |
Low | 低优先级 |
消息丢弃策略如下:
总消息数频控是指单个群每秒最多能发送的消息数限制,默认值为 40条/秒,采用每秒平均限频。消息数量超过限制后,后台优先下发优先级相对较高的消息,同等优先级的消息随机排序。
被频控限制的消息,不会下发,不会存入历史消息,但会给发送人返回成功;会触发 群内发言之前回调,但不会触发 群内发言之后回调。
综上:制定直播间消息优先级规则是很有必要的。
对于直播间消息,我们按对于用户的重要性来进行优先级的划分从高到低依次是:
说明:通常来说,C 端用户自己发送的消息,不论消息优先级的高低,都是一定要上屏的。在消息量特别大时,用户能够接受丢失少部分其他用户的消息。
设置消息优先级代码示例:
// 创建自定义消息
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage("单聊自定义消息".getBytes());
// 设置消息优先级为高优先级消息
v2TIMMessage.setPriority(V2TIMMessage.V2TIM_PRIORITY_HIGH)
// 发送消息
V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, "receiver_userID", null, V2TIMMessage.V2TIM_PRIORITY_NORMAL, false, null, new V2TIMSendCallback<V2TIMMessage>() {
@Override
public void onProgress(int progress) {
// 自定义消息不会回调进度
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onSuccess</span><span class="hljs-params">(V2TIMMessage message)</span> </span>{
<span class="hljs-comment">// 发送群聊自定义消息成功</span>
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onError</span><span class="hljs-params">(<span class="hljs-keyword">int</span> code, String desc)</span> </span>{
<span class="hljs-comment">// 发送群聊自定义消息失败</span>
}
});
大多直播间都会有用户等级的概念,开发者可能会根据以下几点按照一定的权重来计算用户的等级:
其中和 IM 相关的如统计在线时长、统计消息量等我们都需要使用 IM 的回调来实现。在第一个准备工作的模块中,有配置回调的相关指引,控制台 中具体的回调如图:
统计相关信息的流程图如图:
消息发送后回调数据示例:
{
"CallbackCommand": "Group.CallbackAfterSendMsg", // 回调命令
"GroupId": "@TGS#2J4SZEAEL", // 群组 ID
"Type": "Public", // 群组类型
"From_Account": "jared", // 发送者
"Operator_Account":"admin", // 请求的发起者
"Random": 123456, // 随机数
"MsgSeq": 123, // 消息的序列号
"MsgTime": 1490686222, // 消息的时间
"OnlineOnlyFlag": 1, //在线消息,为1,否则为0;直播群忽略此属性,为默认值0。
"MsgBody": [ // 消息体,参见 TIMMessage 消息对象
{
"MsgType": "TIMTextElem", // 文本
"MsgContent": {
"Text": "red packet"
}
}
],
"CloudCustomData": "your cloud custom data"
}
开发者可根据数据中的 MsgBody 中的消息类型区分普通消息和点赞送礼消息。全部字段含义可参见 服务端 API 文档。
用户在线状态改变回调数据示例:
{
"CallbackCommand": "State.StateChange",
"EventTime": 1629883332497,
"Info": {
"Action": "Login",
"To_Account": "testuser316",
"Reason": "Register"
},
"KickedDevice": [
{
"Platform": "Windows"
},
{
"Platform": "Android"
}
]
}
开发者可根据 Info 中的字段判断用户的在线状态,从而统计用户的在线时长。全部字段含义可参见 服务端 API。
说明:此外,不少直播间都会展示直播间热度,并且根据直播间热度,讲直播间推荐给用户观看,直播间热度的统计方式和用户等级统计方式类似,也可以通过 IM 提供的回调系统来进行实现,这里就不在做过多的讲解。
使用 AVChatRoom 默认不存储直播间历史消息,当新用户进入直播间后,只能看到进入直播间后用户发送的消息。为了优化新进群用户的体验,可在控制台配置直播群用户拉取进群前消息条数,如图:
说明:此功能仅旗舰版用户才可开通,且仅支持拉群24小时内最多20条历史消息。
直播群用户拉取进群前历史消息与拉起其他群历史消息一样,代码示例:
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // 拉取云端的更老的消息
option.setGetTimeBegin(1640966400); // 从 2022-01-01 00:00:00 开始
option.setGetTimePeriod(1 * 24 * 60 * 60); // 拉取一整天的消息
option.setCount(Integer.MAX_VALUE); // 返回时间范围内所有的消息
option.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
Log.i("imsdk", "success");
}
@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
直播间实时展示在线人数在直播场景也是一个十分常见的需求,实现方案分为两种,但两种也是各有优劣。
通过客户端 SDK 提供的接口拉取在线人数的方式获取在线人数对于单直播间模式的用户来说基本可以满足用户需求。但对于 App 有多个直播间且需要在大量曝光位置展示直播间在线人数的需求,建议使用第二种方案来统计在线人数。
说明:开发者服务端在向客户端发送在线人数统计消息时,可采用定时发送的方式,如每五秒发一次。但这种方式,在直播间人数变化不大时有额外的网络开销。建议开发者按照群人数变化率监测的方式来进行更新。
直播间在线人数的准确性与实时性的优先级,开发者可以根据自身的业务来设置。
获取直播间在线人数代码如下:
2TIMManager.getGroupManager().getGroupOnlineMemberCount("group_avchatroom", new V2TIMValueCallback<Integer>() {
@Override
public void onSuccess(Integer integer) {
// 获取直播群在线人数成功
}
@Override
public void onError(int code, String desc) {
// 获取直播群在线人数失败
}
});
直播间禁言分为两种,一种是整个直播间禁言,另一种是针对某个用户禁言。两种禁言都有其使用的业务场景。
一般来说我们使用服务端 SDK 来设置禁言。整个直播间禁言,通过 设置群属性 的全员禁言字段来设置。对单个群成员禁言,通过 设置群成员属性 来设置。
当直播间管理者在后台设置群禁言后,客户端在收到对应的回调事件后,应该把用户的输入框设置为 disable 状态。以免用户在发消息时提示发送消息失败。在解除禁言后也应该将输入框设置为 enable 状态。
客户端对应的回调代码如下:
// 禁言群成员 userB 1分钟
V2TIMManager.getGroupManager().muteGroupMember("groupA", "userB", 60, new V2TIMCallback() {
@Override
public void onSuccess() {
// 禁言群成员成功
}
@Override
public void onError(int code, String desc) {
// 禁言群成员失败
}
});
// 全员禁言
V2TIMGroupInfo info = new V2TIMGroupInfo();
info.setGroupID("groupA");
info.setAllMuted(true);
V2TIMManager.getGroupManager().setGroupInfo(info, new V2TIMCallback() {
@Override
public void onSuccess() {
// 全员禁言成功
}
@Override
public void onError(int code, String desc) {
// 全员禁言失败
}
});
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberInfoChanged(String groupID, List<V2TIMGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) {
// 禁言群成员监听
for (V2TIMGroupMemberChangeInfo memberChangeInfo : v2TIMGroupMemberChangeInfoList) {
// 被禁言用户 ID
String userID = memberChangeInfo.getUserID();
// 禁言时间
long muteTime = memberChangeInfo.getMuteTime();
}
}
@Override
public void onGroupInfoChanged(String groupID, List<V2TIMGroupChangeInfo> changeInfos) {
// 全员禁言监听
for (V2TIMGroupChangeInfo groupChangeInfo : changeInfos) {
if (groupChangeInfo.getType() == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) {
// 是否全员禁言
boolean isMuteAll = groupChangeInfo.getBoolValue();
}
}
}
});
需要注意的是,群成员禁言状态的变更默认不会下发通知给客户端,需要到 控制台进行配置:
说明:
开发者可以通过服务端 封禁 的接口,来踢出直播间成员,并且封禁一段时间不允许被踢成员再次进群。
控制台相关配置 如图所示:
注意:在客户端 SDK 6.6.X 及以上版本、Flutter SDK 4.1.1 及以上版本,可以使用直播间踢人接口实现封禁功能。
可参考代码如下:
List<String> userIDList = new ArrayList<>();
userIDList.add("userB");
V2TIMManager.getGroupManager().kickGroupMember("groupA", userIDList, "", new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {
@Override
public void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {
// 踢人成功
}
@Override
public void onError(int code, String desc) {
// 踢人失败
}
});
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberKicked(String groupID, V2TIMGroupMemberInfo opUser,
List<V2TIMGroupMemberInfo> memberList) {
// 群成员被踢通知
}
});
过滤直播间敏感内容也是直播业务非常重要的功能,实现方案如下:
发送消息前回调数据示例:
{
"CallbackCommand": "Group.CallbackBeforeSendMsg", // 回调命令
"GroupId": "@TGS#2J4SZEAEL", // 群组 ID
"Type": "Public", // 群组类型
"From_Account": "jared", // 发送者
"Operator_Account":"admin", // 请求的发起者
"Random": 123456, // 随机数
"OnlineOnlyFlag": 1, //在线消息,为1,否则为0;直播群忽略此属性,为默认值0。
"MsgBody": [ // 消息体,参见 TIMMessage 消息对象
{
"MsgType": "TIMTextElem", // 文本
"MsgContent": {
"Text": "red packet"
}
}
],
"CloudCustomData": "your cloud custom data"
}
开发者可通过 MsgBody 中 MsgType 字段判断消息类型。完整字段说明可参见 回调文档。
开发者可以选择对不合法的消息进行不一样的处理,可在回调中回包给 IM 后台来控制。
{
"ActionStatus": "OK",
"ErrorInfo": "",
"ErrorCode": 0 // 不同的ErrorCode有不同的含义
}
ErrorCode | 含义 |
---|---|
0 | 为允许发言,正常下发消息 |
1 | 为拒绝发言,客户端返回10016 |
2 | 为静默丢弃,客户端返回正常 |
开发者可根据自身业务进行选择使用
敏感内容检测流程图如图所示:
在需要展示直播间在线群成员列表时,可以通过getGroupMemberList
接口获取群成员列表,但 AVChatRoom 由于人数众多,不提供拉取全量成员列表的功能。根据旗舰版和非旗舰版区分不同的表现:
getGroupMemberList
拉取最近进群的 30 位群成员。getGroupMemberList
拉取最近进群的 1000 位群成员。此功能需要在 IM 控制台开启开关,如果不开启,默认跟非旗舰版一样,仅拉取最近进群 30 位群成员。控制台配置如图2.6:
如果是非旗舰版,开发者也可通过getGroupMemberList
与群监听中的 onGroupMemberEnter 和 onGroupMemberQuit 回调,在客户端维护当前在线群成员列表。但此方案用户退出直播间重新进入后,也只能获取最新的30位群成员。
// 通过 filter 参数指定只拉取群主的资料
int role = V2TIMGroupMemberFullInfo.V2TIM_GROUP_MEMBER_FILTER_OWNER;
V2TIMManager.getGroupManager().getGroupMemberList("testGroup", role, 0,
new V2TIMValueCallback<V2TIMGroupMemberInfoResult>() {
@Override
public void onError(int code, String desc) {
// 拉取失败
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onSuccess</span><span class="hljs-params">(V2TIMGroupMemberInfoResult v2TIMGroupMemberInfoResult)</span> </span>{
<span class="hljs-comment">// 拉取成功</span>
}
});
直播抽奖与消息统计类似,都需要用到发消息后回调,通过检测消息内容,将命中抽奖关键词的用户加入抽奖池。在此不做过多的补充。
AVChatRoom 支持弹幕、 送礼和点赞等多消息类型,轻松打造良好的直播聊天互动体验。
大喇叭功能相当于一个直播间维度的系统公告功能,但有别于公告,大喇叭功能属于消息。当系统管理员下发大喇叭消息时,SDKAppID 下所有直播间均可收到该大喇叭消息。
大喇叭功能目前属于旗舰版功能,且需要在控制台开通。
业务后台发送大喇叭消息可参见文档:直播群广播消息
说明:若开发者版本非旗舰版,可在服务端发送群自定义消息进行实现。
目前腾讯云直播推流有以下几种方式:
说明:
用户端获取直播流的方式也有不同的方式如:
说明:
为了满足直播场景更多的需求,开发者可以使用云 导播台 对直播流进行处理,目前导播台支持如下功能:
云直播除了推拉流业务,还有更多高级功能如:
新用户开通云直播服务,会免费获得 20GB 的流量,有效期1年。此时测试产生的流量可以使用其抵扣,超出套餐部分按照后付费日结计费。同时也欢迎使用直播增值功能如:直播水印、转码、录制、截图、鉴黄等,增值功能默认关闭,按需开启使用并计费,详细功能了解可参见 产品概述。
腾讯云直播默认不限制观看直播的在线人数,只要网络等条件允许都可以观看直播。如果用户配置了带宽限制,当观看人数过多、超出了限制带宽时新的用户无法观看,此情况下在线人数是有限制的。
Message.nick
与 Message.avatar
字段都为空,该怎么处理才能在界面上正常展示昵称和头像?可通过 getUserInfo 接口,获取自己的用户信息中的 nick 和 avatar 字段作为消息发送发的 nick 和 avatar 字段。
出现丢消息的可能原因如下:
如果您已排除以上可能性,您可以 提交工单 联系我们。
搜索群号:853084820,我们会提供更加详细的解答。
本页内容是否解决了您的问题?