As live streaming has become ubiquitous, more and more enterprises and developers are building their own live streaming platforms. During the process, they need to handle complex requirements such as live stream push and pull, live transcoding, live screencapturing, live stream mix, live chat room, live room interaction (like, gift, and co-anchoring), and live room status management. This document takes Tencent Cloud products (IM and CSS) as examples to describe how to implement a live room, along with possible problems and considerations, giving a glimpse of the live streaming business and requirements.
To set up a live room in Tencent Cloud, you need to create an IM application in the console as shown below:
The live streaming feature is required to set up a live room and can be implemented through CSS. You need to add a push domain and a playback domain as shown below:
For detailed directions, see Adding Your Own Domain.
The application created during the preparations is the Free edition, which applies only to development. In the production environment, you need to activate the Pro or Ultimate edition as needed. For more information on differences between different editions, see Pricing.
In live streaming scenarios, you need some extra configurations after creating the application.
In the IM account system, the password required by a user login is calculated by the server with a key provided by IM. For more information, see Generating UserSig. In the development phase, to avoid holding back development on the client, you can also calculate the UserSig
in the console as shown below:
During live streaming, an admin may need to send messages to a live room and mute (remove) non-compliant users, which can be done through IM server APIs. To call these APIs, you need to create an IM admin account. By default, IM provides an account with the UserID
of administrator
. You can also create multiple admin accounts as needed. Note that you can create up to five admin accounts.
To implement lucky draws based on on-screen comments, message statistics collection, sensitive content detection, and other requirements, you need to use the IM callback module, where the IM backend calls back the business backend in certain scenarios. You only need to provide an HTTP API and configure it in the Callback configuration module in the console as shown below:
After completing the preparations, you need to integrate the IM and CSS client SDKs into your project. You can select an integration option as needed.
For IM integration, see Instant Messaging.
For CSS integration, see User Guide.
The following describes common features in a live room and provides best practices with implementation code.
A live room has the following statuses:
No. | Live Room Status |
---|---|
1 | To be started |
2 | On live |
3 | Paused |
4 | Ended |
5 | Played back |
No. | Characteristics |
---|---|
1 | Users in a live room need to be notified in real time of the change of the live room status. |
2 | Users new to a live room need to get the current status of the live room. |
Two implementation schemes are provided, and their pros and cons are as analyzed below.
Implementation Scheme | Pros | Cons |
---|---|---|
The business backend maintains the live room status and uses the IM server API to send custom group messages to notify users of the status. | When the live room status needs to be obtained frequently, storing the status on the business backend reduces the frequency to call the IM SDK, compared to storing the status in the IM group profile. This implementation scheme makes it possible to get the live room status when the IM SDK is not integrated. |
The business backend needs to provide an extra module for reading and writing the live room status. Exceptions are more likely to occur when the live room data is obtained, as the data comes from both the business backend and IM group profile. Custom messages may be lost when sent. When there are a large number of messages, low-priority ones will be discarded first, which affects the display of the live room status. Therefore, we recommend you use high-priority custom messages. |
You can store the live room status through a custom group field or group attribute and notify group users through the callback for group attribute change of the client SDK. | You don't need to provide an extra module for reading and writing the live room status. Theoretically, the callback for group attribute change won't be lost. Live room data is obtained from the group profile, which serves as a unified data source that reduces exceptions. |
You need to get the group profile frequently in the high-exposure module, which increases the pressure on IM. If the IM SDK module is not integrated, you need to call the IM server SDK on the business backend to get the group profile, and the number of calls is limited. |
Based on the analysis above, we recommend you combine the two schemes to maintain the live room status:
The user chat section in live streaming scenarios has the following characteristics:
lastMessage
) doesn't need to be managed.Therefore, you can select audio-video groups (AVChatRoom) as the Group type for the live room based on the group characteristics of IM.
IM audio-video groups (AVChatRooms) have the following features:
Note:The IM SDK for web allows users to join only one audio-video group (AVChatRoom) at a time. If a user logs in to an client and enters live room A, multi-client login is enabled in the console, and the user logs in to another client and enters live room B, the user will be removed from live room A.
The live room notice (topic) is necessary for each live room and can be seen by users after entering the room. In addition, audio-video group members need to be notified of notice changes in real time. You can store the live room notice on the business backend or in the IM group profile, just like the live room status; however, there are some additional things that require your attention:
The live room notice can be set through the server APIs or the group attribute in the client SDK. The client gets the current group information through the group attribute and listens for OnGroupInfoChange
in GroupListener
to get the changed group attribute.
Sample code:
// Get the group profile from the client
V2TIMManager.getGroupManager().getGroupsInfo(groupIDList, new V2TIMValueCallback<List<V2TIMGroupInfoResult>>() {
@Override
public void onSuccess(List<V2TIMGroupInfoResult> v2TIMGroupInfoResults) {
// Obtained the group profile successfully
}
@Override
public void onError(int code, String desc) {
// Failed to obtain the group profile
}
});
// Modify the group profile on the client
V2TIMGroupInfo v2TIMGroupInfo = new V2TIMGroupInfo();
v2TIMGroupInfo.setGroupID("Group ID of the group to be modified");
v2TIMGroupInfo.setFaceUrl("http://xxxx");
V2TIMManager.getGroupManager().setGroupInfo(v2TIMGroupInfo, new V2TIMCallback() {
@Override
public void onSuccess() {
// Modified the group profile successfully
}
@Override
public void onError(int code, String desc) {
// Failed to modify the group profile
}
});
See the sample code for group profile processing in other SDKs here.
A live room features a large number of user messages. Each user may frequently send messages. When the number of messages sent reaches the IM frequency control threshold, the IM backend will discard some messages to ensure the system running stability. It's necessary to apply such a threshold, as messages are less readable when the client receives too many of them.
Group messages are divided into three levels by priority. The backend delivers high-priority messages first. Therefore, select appropriate priorities according to the importance of messages.
The following lists the priorities from high to low:
Priority | Description |
---|---|
High | High priority |
Normal | Medium priority |
Low | Low priority |
Messages are discarded according to the following policy:
Number-based frequency control limits the maximum number of messages sent per second in a single group. The default value is 40 messages per second. When the number of sent messages exceeds the limit, the backend will first deliver higher-priority messages, with messages with the same priority delivered randomly.
A message that has been restricted by frequency control is not delivered or stored in the message history, but a success response will be returned to the sender. Callback before delivering group message is triggered, but callback after delivering group message is not triggered.
Therefore, it's necessary to set message priorities for a live room.
Live room messages are prioritized based on their importance as follows:
Note:In general, messages sent by client users are displayed on the screen regardless of their priority. When there are a large number of messages, it's acceptable for users to lose a small number of messages from other users.
Sample code for setting message priorities:
// Create a custom message
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage("Custom one-to-one message".getBytes());
// Set the message priority to high
v2TIMMessage.setPriority(V2TIMMessage.V2TIM_PRIORITY_HIGH)
// Send the message
V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, "receiver_userID", null, V2TIMMessage.V2TIM_PRIORITY_NORMAL, false, null, new V2TIMSendCallback<V2TIMMessage>() {
@Override
public void onProgress(int progress) {
// The progress is not called back for the custom message.
}
<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">// The custom group message sent successfully</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">// Failed to send the custom group message</span>
}
});
See the sample code for message priority setting in other SDKs here.
99
included in the parameter.The concept of user level applies to most of the live rooms. You can determine a weighted user level based on the following:
For online duration and the number of messages, you need to use the IM callbacks, which can be configured as instructed in the preparations. Callbacks in the console are as shown below:
The flowchart for information collection is as shown below:
Sample data of the callback after sending a message:
{
"CallbackCommand": "Group.CallbackAfterSendMsg", // Callback command
"GroupId": "@TGS#2J4SZEAEL", // Group ID
"Type": "Public", // Group type
"From_Account": "jared", // Sender
"Operator_Account":"admin", // Request initiator
"Random": 123456, // Random number
"MsgSeq": 123, // Sequence number of the message
"MsgTime": 1490686222, // Time of the message
"OnlineOnlyFlag": 1, // The value is `1` if it is an online message and `0` (default) if it’s not. For audio-video groups, the value is `0`.
"MsgBody": [ // Message body. For more information, see the `TIMMessage` message object.
{
"MsgType": "TIMTextElem", // Text
"MsgContent":{
"Text": "red packet"
}
}
],
"CloudCustomData": "your cloud custom data"
}
You can identify ordinary, like, and gift messages based on the message type in MsgBody
. For more information on all the fields, see Callback After Sending a Group Message.
Sample data of the callback for the change of the user online status:
{
"CallbackCommand": "State.StateChange",
"EventTime": 1629883332497,
"Info": {
"Action": "Login",
"To_Account": "testuser316",
"Reason": "Register"
},
"KickedDevice": [
{
"Platform": "Windows"
},
{
"Platform": "Android"
}
]
}
You can identify the user online status based on the field in Info
, so as to count the online duration. For more information on all the fields, see State Change Callbacks.
Note:In addition, live room popularity is often displayed and used as a criterion for live room recommendation. It is determined in a similar way to user level and can be implemented through the callback system of IM.
Historical messages are not stored by default for audio-video groups (AVChatRoom). When a new user enters the live room, the user can only see messages sent after the entry. To optimize the user experience, you can configure the number of historical messages that can be pulled as shown below:
Note:This feature is available only for the Ultimate edition, and up to 20 historical messages in the past 24 hours can be pulled.
Historical messages in audio-video groups are pulled in the same way as others. Sample code:
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // Pull older cloud messages
option.setGetTimeBegin(1640966400); // Start from 2022-01-01 00:00:00
option.setGetTimePeriod(1 * 24 * 60 * 60); // Pull the messages of the whole day
option.setCount(Integer.MAX_VALUE); // Return all the messages within the time range
option.setGroupID(#you group id#); // Pull group messages
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);
}
});
See the sample code for historical message pulling in other SDKs here.
Displaying the number of online users in a live room is a common feature. There are two implementation schemes, each with pros and cons.
If there is only one live room, it's sufficient to pull the number of online users through the API of the client SDK. If there are multiple live rooms that require a large number of exposure positions to display the number of online users, the second scheme is recommended.
Note:Your server can send the message of online user count statistics to the client in a scheduled manner, for example, once every five seconds. However, this will incur extra network overheads if the number of online users in the live room doesn't change sharply. We recommend you update the number by monitoring its change rate.
You can determine the priority of the accuracy and real-timeness of the number of online users in the live room as needed.
The code for getting the number of online users in a live room is as follows:
2TIMManager.getGroupManager().getGroupOnlineMemberCount("group_avchatroom", new V2TIMValueCallback<Integer>() {
@Override
public void onSuccess(Integer integer) {
// Obtained the number of online members in the audio-video group (AVChatRoom) successfully
}
@Override
public void onError(int code, String desc) {
// Failed to obtain the number of online members in the audio-video group (AVChatRoom)
}
});
In a live room, you can mute all or a specified user in different scenarios.
In general, the server SDK is used for muting. To mute all, set the MuteAllMember
field of the group attribute as instructed in Modifying the Profile of a Group. To mute a specified user, set the group member attribute as instructed in Bulk Muting and Unmuting.
When the live room admin sets group muting on the backend, the client should put the input box of the target user in the disabled status after receiving the callback event; otherwise, the user will receive the message sending failure prompt when sending a message. After the user is unmuted, the client should also put the input box in the enabled status.
Callback code on the client:
// Mute the `userB` group member for one minute
V2TIMManager.getGroupManager().muteGroupMember("groupA", "userB", 60, new V2TIMCallback() {
@Override
public void onSuccess() {
// Muted the group member successfully
}
@Override
public void onError(int code, String desc) {
// Failed to mute the group member
}
});
// Mute all members
V2TIMGroupInfo info = new V2TIMGroupInfo();
info.setGroupID("groupA");
info.setAllMuted(true);
V2TIMManager.getGroupManager().setGroupInfo(info, new V2TIMCallback() {
@Override
public void onSuccess() {
// Muted all successfully
}
@Override
public void onError(int code, String desc) {
// Failed to mute all
}
});
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberInfoChanged(String groupID, List<V2TIMGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) {
// Listen for the muting of a group member
for (V2TIMGroupMemberChangeInfo memberChangeInfo : v2TIMGroupMemberChangeInfoList) {
// ID of the muted user
String userID = memberChangeInfo.getUserID();
// Muting duration
long muteTime = memberChangeInfo.getMuteTime();
}
}
@Override
public void onGroupInfoChanged(String groupID, List<V2TIMGroupChangeInfo> changeInfos) {
// Listen for the muting of all
for (V2TIMGroupChangeInfo groupChangeInfo : changeInfos) {
if (groupChangeInfo.getType() == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) {
// Whether all members are muted
boolean isMuteAll = groupChangeInfo.getBoolValue();
}
}
}
});
See the sample code for group listening in other SDKs here.
Note that the change of the group member muting status will not be delivered to the client by default and needs to be configured in the console.
Note:Client SDKs do not support user muting in live rooms at the moment. You can use the corresponding server APIs to mute and unmute users.
You can call the banning API on the server to kick users out of a live room and ban them from joining for a certain period of time.
Configuration items in the console are as shown below:
Note:You can use the API for kicking users out of a live room to implement the banning feature in the client SDK on 6.6.x or later or the SDK for Flutter on 4.1.1 or later.
Sample code:
List<String> userIDList = new ArrayList<>();
userIDList.add("userB");
V2TIMManager.getGroupManager().kickGroupMember("groupA", userIDList, "", new V2TIMValueCallback<List<V2TIMGroupMemberOperationResult>>() {
@Override
public void onSuccess(List<V2TIMGroupMemberOperationResult> v2TIMGroupMemberOperationResults) {
// Removed the member successfully
}
@Override
public void onError(int code, String desc) {
// Failed to remove the member
}
});
V2TIMManager.getInstance().addGroupListener(new V2TIMGroupListener() {
@Override
public void onMemberKicked(String groupID, V2TIMGroupMemberInfo opUser,
List<V2TIMGroupMemberInfo> memberList) {
// A group member was removed.
}
});
Filtering the sensitive content in a live room is another important feature, which can be implemented as follows:
Sample data of the callback before sending a message:
{
"CallbackCommand": "Group.CallbackBeforeSendMsg", // Callback command
"GroupId": "@TGS#2J4SZEAEL", // Group ID
"Type": "Public", // Group type
"From_Account": "jared", // Sender
"Operator_Account":"admin", // Request initiator
"Random": 123456, // Random number
"OnlineOnlyFlag": 1, // The value is `1` if it is an online message and `0` (default) if it’s not. For audio-video groups, the value is `0`.
"MsgBody": [ // Message body. For more information, see the `TIMMessage` message object.
{
"MsgType": "TIMTextElem", // Text
"MsgContent":{
"Text": "red packet"
}
}
],
"CloudCustomData": "your cloud custom data"
}
You can identify the message type based on the MsgType
field in MsgBody
. For more information on the fields, see Callback Before Sending a Group Message.
You can choose to handle a non-compliant message in a specific way, which can be implemented through the data packet in the callback returned to the IM backend.
{
"ActionStatus": "OK",
"ErrorInfo": "",
"ErrorCode": 0 // Different `ErrorCode` values have different meanings.
}
ErrorCode | Description |
---|---|
0 | Speaking is allowed, and messages can be delivered. |
1 | Speaking is denied, and the client returns 10016 . |
2 | Silent discarding is enabled, and the client returns messages normally. |
You can use them as needed.
The flowchart for detecting sensitive content is as shown below:
You can call the getGroupMemberList
API to get the list of online group members in a live room for display. As an audio-video group (AVChatRoom) has a large number of members, the feature of pulling the list of all the members is unavailable. The Ultimate edition and non-Ultimate edition differ in settings:
getGroupMemberList
to pull the latest 30 group members.getGroupMemberList
to pull the latest 1,000 group members. This feature needs to be enabled in the IM console. If it is not enabled, only the latest 30 group members will be pulled, just as in the non-Ultimate edition.The configuration in the console is as shown below:
If you are a non-Ultimate edition user, you can maintain the list of online group members on the client through getGroupMemberList
and the onGroupMemberEnter
and onGroupMemberQuit
callbacks of the group listening. However, after users leave and re-enter the live room, only the latest 30 group members can be pulled.
// Use the `filter` parameter to specify only the profile of the group owner is to be pulled
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) {
// Messages failed to be pulled
}
<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">// Conversations pulled successfully</span>
}
});
Similar to message statistics, lucky draws in live streaming also require the callback after sending a message. Specifically, the message content is detected, and users that hit the keywords of a lucky draw are added to the pool.
Audio-video groups (AVChatRoom
) support on-screen comments, gifts, and like messages to build a friendly interaction experience.
The broadcast feature is similar to a system notice feature in the live room, but it differs from the latter in that it belongs to messaging. When the system admin delivers a broadcast message, all the live rooms under the SDKAppID
will receive it.
The broadcast feature is currently available only for the Ultimate edition and needs to be enabled in the console.
For detailed directions on how to send a broadcast message on the business backend, see Broadcast Messaging of Audio-Video Group.
Note:If you are not an Ultimate edition user, you can implement the feature by sending a custom group message on the server.
Currently, CSS offers the following ways to push a stream:
Note:Before starting stream push, an anchor needs to configure a push address. Refer to Push Configuration or Address Generator to generate a push address.
The client can get live streams in different ways:
Note:You need to configure a playback address to pull a stream, which can be generated as instructed in Playback Configuration or through the Address Generator. For more information on SDK integration, see 2. Playback.
To meet more requirements for live streaming, you can use the live director to process live streams. Currently, the live director supports the following features:
CSS has the following advanced features in addition to stream push and pull:
New users can get 20 GB free traffic valid for one year after activating CSS, and excessive traffic will be billed daily in pay-as-you-go mode. CSS value-added features are disabled by default, such as live watermarking, transcoding, recording, screencapturing, and porn detection. They can be enabled as needed and will be billed afterward. For more information, see Overview.
By default, CSS does not limit the number of online viewers for a live stream as long as the network and other conditions permit. However, if you have configured a bandwidth limit, new viewers cannot watch the live stream if there are so many existing viewers that the bandwidth limit is exceeded. In this case, the number of online viewers is limited.
Message.nick
, and Message.avatar
fields are empty during message sending?Call the getUserInfo
API to get the Message.nick
and Message.avatar
fields in the user's information and use them as the fields for message sending.
Possible causes include the following:
If the problem persists, submit a ticket for assistance.
Contact us for more information.
Was this page helpful?