tencent cloud

文档反馈

房间与媒体回调

最后更新时间:2023-08-09 14:18:31
    事件回调服务支持将实时音视频业务下的事件,以 HTTP/HTTPS 请求的形式通知到您的服务器。事件回调服务已集成房间事件组(Room Event)和媒体事件组(Media Event)以及录制事件组的一些事件(云端录制功能回调事件说明请参见 实现云端录制与回放),您可以向腾讯云提供相关的配置信息来开通该服务。

    配置信息

    实时音视频 TRTC 控制台支持自助配置回调信息,配置完成后即可接收事件回调通知。
    
    
    
    注意:
    您需要提前准备以下信息:
    必要项:接收回调通知的 HTTP/HTTPS 服务器地址。
    可选项:计算签名的密钥 key,由您自定义一个最大32个字符的 key,以大小写字母及数字组成。

    超时重试

    事件回调服务器在发送消息通知后,5秒内没有收到您的服务器的响应,即认为通知失败。首次通知失败后会立即重试,后续失败会以10秒的间隔继续重试,直到消息存续时间超过1分钟,不再重试。

    事件回调消息格式

    事件回调消息以 HTTP/HTTPS POST 请求发送给您的服务器,其中:
    字符编码格式:UTF-8。
    请求:body 格式为 JSON。
    应答:HTTP STATUS CODE = 200,服务端忽略应答包具体内容,为了协议友好,建议客户应答内容携带 JSON: {"code":0}。

    参数说明

    回调消息参数

    事件回调消息的 header 中包含以下字段:
    字段名
    Content-Type
    application/json
    Sign
    签名值
    SdkAppId
    sdk application id
    事件回调消息的 body 中包含以下字段:
    字段名
    类型
    含义
    EventGroupId
    Number
    EventType
    Number
    CallbackTs
    Number
    事件回调服务器向您的服务器发出回调请求的 Unix 时间戳,单位为毫秒
    EventInfo
    JSON Object

    事件组 ID

    字段名
    含义
    EVENT_GROUP_ROOM
    1
    房间事件组
    EVENT_GROUP_MEDIA
    2
    媒体事件组
    说明:
    录制事件组相关说明请参见 实现云端录制与回放

    事件类型

    字段名
    含义
    EVENT_TYPE_CREATE_ROOM
    101
    创建房间
    EVENT_TYPE_DISMISS_ROOM
    102
    解散房间
    EVENT_TYPE_ENTER_ROOM
    103
    进入房间
    EVENT_TYPE_EXIT_ROOM
    104
    退出房间
    EVENT_TYPE_CHANGE_ROLE
    105
    切换角色
    EVENT_TYPE_START_VIDEO
    201
    开始推送视频数据
    EVENT_TYPE_STOP_VIDEO
    202
    停止推送视频数据
    EVENT_TYPE_START_AUDIO
    203
    开始推送音频数据
    EVENT_TYPE_STOP_AUDIO
    204
    停止推送音频数据
    EVENT_TYPE_START_ASSIT
    205
    开始推送辅路数据
    EVENT_TYPE_STOP_ASSIT
    206
    停止推送辅路数据
    注意:
    退出房间只会回调104事件,不会回调202跟204事件。104事件相当于包含了202和204事件。手动关闭视频/音频,才会回调202/204事件。

    事件回调示例

    101
    102
    103
    104
    105
    201
    202
    203
    204
    205
    206
    { "EventGroupId": 1,
    "EventType": 101,
    "CallbackTs": 1687770730166,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687770730,
    "EventMsTs": 1687770730160,
    "UserId": "test"
    }
    }
    {
    "EventGroupId": 1,
    "EventType": 102,
    "CallbackTs": 1687771618531,
    "EventInfo": {
    "RoomId": "12345",
    "EventTs": 1687771618,
    "EventMsTs": 1687771618457
    }
    }
    {
    "EventGroupId": 1,
    "EventType": 103,
    "CallbackTs": 1687770731932,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687770731,
    "EventMsTs": 1687770731831,
    "UserId": "test",
    "Role": 21,
    "TerminalType": 2,
    "UserType": 3,
    "Reason": 1
    }
    }
    {
    "EventGroupId": 1,
    "EventType": 104,
    "CallbackTs": 1687770731922,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687770731,
    "EventMsTs": 1687770731898,
    "UserId": "test",
    "Role": 20,
    "Reason": 1
    }
    }
    {
    "EventGroupId": 1,
    "EventType": 105,
    "CallbackTs": 1687772245596,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687772245,
    "EventMsTs": 1687772245537,
    "UserId": "test",
    "Role": 21
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 201,
    "CallbackTs": 1687771803198,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687771803,
    "EventMsTs": 1687771803192,
    "UserId": "test"
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 202,
    "CallbackTs": 1687771919458,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687771919,
    "EventMsTs": 1687771919447,
    "UserId": "test",
    "Reason": 0
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 203,
    "CallbackTs": 1687771869377,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687771869,
    "EventMsTs": 1687771869365,
    "UserId": "test"
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 204,
    "CallbackTs": 1687770732498,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687770732,
    "EventMsTs": 1687770732383,
    "UserId": "test",
    "Reason": 0
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 205,
    "CallbackTs": 1687772013823,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687772013,
    "EventMsTs": 1687772013753,
    "UserId": "test"
    }
    }
    {
    "EventGroupId": 2,
    "EventType": 206,
    "CallbackTs": 1687772015054,
    "EventInfo": {
    "RoomId": 12345,
    "EventTs": 1687772015,
    "EventMsTs": 1687772015032,
    "UserId": "test",
    "Reason": 0
    }
    }

    事件信息

    字段名
    类型
    含义
    RoomId
    String/Number
    房间名(类型与客户端房间号类型一致)
    EventTs
    Number
    事件发生的 Unix 时间戳,单位为秒(兼容保留)
    EventMsTs
    Number
    事件发生的 Unix 时间戳,单位为毫秒
    UserId
    String
    用户 ID
    UniqueId
    Number
    唯一标识符(option:房间事件组携带)
    当客户端发生了一些特殊行为,例如切换网络、进程异常退出及重进等,此时您的回调服务器可能会收到同一个用户多次进房和退房回调,UniqueId 可用于标识用户的同一次进退房
    Role
    Number
    角色类型(option:进退房时携带)
    TerminalType
    Number
    终端类型(option:进房时携带)
    UserType
    Number
    用户类型(option:进房时携带)
    Reason
    Number
    具体原因 (option:进退房时携带)
    注意:
    我们已发布“过滤客户端特殊行为导致的重复回调”策略。如果您是2021年07月30日之后接入回调服务,默认走新策略,房间事件组不再携带 UniqueId(唯一标识符)。

    角色类型

    字段名
    含义
    MEMBER_TRTC_ANCHOR
    20
    主播
    MEMBER_TRTC_VIEWER
    21
    观众

    终端类型

    字段名
    含义
    TERMINAL_TYPE_WINDOWS
    1
    Windows 端
    TERMINAL_TYPE_ANDROID
    2
    Android 端
    TERMINAL_TYPE_IOS
    3
    iOS 端
    TERMINAL_TYPE_LINUX
    4
    Linux 端
    TERMINAL_TYPE_OTHER
    100
    其他

    用户类型

    字段名
    含义
    USER_TYPE_WEBRTC
    1
    webrtc
    USER_TYPE_APPLET
    2
    小程序
    USER_TYPE_NATIVE_SDK
    3
    Native SDK

    具体原因

    字段名
    含义
    进房
    1:正常进房
    2:切换网络
    3:超时重试
    4:跨房连麦进房
    退房
    1:正常退房
    2:超时离开
    3:房间用户被移出
    4:取消连麦退房
    5:强杀
    注意:Android 系统无法捕捉进程被强杀,只能等待后台超时离开,此时回调 reason 为2

    计算签名

    签名由 HMAC SHA256 加密算法计算得出,您的事件回调接收服务器收到回调消息后,通过同样的方式计算出签名,相同则说明是腾讯云的实时音视频的事件回调,没有被伪造。签名的计算如下所示:
    //签名 Sign 计算公式中 key 为计算签名 Sign 用的加密密钥。
    Sign = base64(hmacsha256(key, body))
    注意:
    body 为您收到回调请求的原始包体,不要做任何转化,示例如下:
    body="{\\n\\t\\"EventGroupId\\":\\t1,\\n\\t\\"EventType\\":\\t103,\\n\\t\\"CallbackTs\\":\\t1615554923704,\\n\\t\\"EventInfo\\":\\t{\\n\\t\\t\\"RoomId\\":\\t12345,\\n\\t\\t\\"EventTs\\":\\t1608441737,\\n\\t\\t\\"UserId\\":\\t\\"test\\",\\n\\t\\t\\"UniqueId\\":\\t1615554922656,\\n\\t\\t\\"Role\\":\\t20,\\n\\t\\t\\"Reason\\":\\t1\\n\\t}\\n}"

    签名校验示例

    Java
    Python
    PHP
    Golang
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Base64;
    //# 功能:第三方回调sign校验
    //# 参数:
    //#   key:控制台配置的密钥key
    //#   body:腾讯云回调返回的body体
    //#   sign:腾讯云回调返回的签名值sign
    //# 返回值:
    //#   Status:OK 表示校验通过,FAIL 表示校验失败,具体原因参考Info
    //#   Info:成功/失败信息
    
    public class checkSign {
        public static String getResultSign(String key, String body) throws Exception {
            Mac hmacSha256 = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
            hmacSha256.init(secret_key);
            return Base64.getEncoder().encodeToString(hmacSha256.doFinal(body.getBytes()));
        }
        public static void main(String[] args) throws Exception {
            String key = "123654";
            String body = "{\\n" + "\\t\\"EventGroupId\\":\\t2,\\n" + "\\t\\"EventType\\":\\t204,\\n" + "\\t\\"CallbackTs\\":\\t1664209748188,\\n" + "\\t\\"EventInfo\\":\\t{\\n" + "\\t\\t\\"RoomId\\":\\t8489,\\n" + "\\t\\t\\"EventTs\\":\\t1664209748,\\n" + "\\t\\t\\"EventMsTs\\":\\t1664209748180,\\n" + "\\t\\t\\"UserId\\":\\t\\"user_85034614\\",\\n" + "\\t\\t\\"Reason\\":\\t0\\n" + "\\t}\\n" + "}";
            String Sign = "kkoFeO3Oh2ZHnjtg8tEAQhtXK16/KI05W3BQff8IvGA=";
            String resultSign = getResultSign(key, body);
    
            if (resultSign.equals(Sign)) {
                System.out.println("{'Status': 'OK', 'Info': '校验通过'}");
            } else {
                System.out.println("{'Status': 'FAIL', 'Info': '校验失败'}");
            }
        }
    }
    # -*- coding: utf8 -*-
    import hmac
    import base64
    from hashlib import sha256
    
    # 功能:第三方回调sign校验
    # 参数:
    #   key:控制台配置的密钥key
    #   body:腾讯云回调返回的body体
    #   sign:腾讯云回调返回的签名值sign
    # 返回值:
    #   Status:OK 表示校验通过,FAIL 表示校验失败,具体原因参考Info
    #   Info:成功/失败信息
    
    def checkSign(key, body, sign):
        temp_dict = {}
        computSign = base64.b64encode(hmac.new(key.encode('utf-8'), body.encode('utf-8'), digestmod=sha256).digest()).decode('utf-8')
        print(computSign)
        if computSign == sign:
            temp_dict['Status'] = 'OK'
            temp_dict['Info'] = '校验通过'
            return temp_dict
        else:
            temp_dict['Status'] = 'FAIL'
            temp_dict['Info'] = '校验失败'
            return temp_dict
    
    if __name__ == '__main__':
        key = '123654'
        body = "{\\n" + "\\t\\"EventGroupId\\":\\t2,\\n" + "\\t\\"EventType\\":\\t204,\\n" + "\\t\\"CallbackTs\\":\\t1664209748188,\\n" + "\\t\\"EventInfo\\":\\t{\\n" + "\\t\\t\\"RoomId\\":\\t8489,\\n" + "\\t\\t\\"EventTs\\":\\t1664209748,\\n" + "\\t\\t\\"EventMsTs\\":\\t1664209748180,\\n" + "\\t\\t\\"UserId\\":\\t\\"user_85034614\\",\\n" + "\\t\\t\\"Reason\\":\\t0\\n" + "\\t}\\n" + "}"
        sign = 'kkoFeO3Oh2ZHnjtg8tEAQhtXK16/KI05W3BQff8IvGA='
        result = checkSign(key, body, sign)
        print(result)
    <?php
    
    class TlsEventSig {
    private $key = false;
    private $body = false;
    public function __construct( $key, $body ) {
    $this->key = $key;
    $this->body = $body;
    }
    
    private function __hmacsha256() {
    $hash = hash_hmac( 'sha256', $this->body, $this->key, true );
    return base64_encode( $hash);
    }
    public function genEventSig() {
    return $this->__hmacsha256();
    }
    }
    
    $key="789";
    $data="{\\n\\t\\"EventGroupId\\":\\t1,\\n\\t\\"EventType\\":\\t101,\\n\\t\\"CallbackTs\\":\\t1608086882372,\\n\\t\\"EventInfo\\":\\t{\\n\\t\\t\\"RoomId\\":\\t20222,\\n\\t\\t\\"EventTs\\":\\t1608086882,\\n\\t\\t\\"UserId\\":\\t\\"222222_phone\\"\\n\\t}\\n}";
    
    $api = new TlsEventSig($key, $data);
    echo $api->genEventSig();
    package main
    import "fmt"
    import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    )
    
    func main () {
    var data = "{\\n\\t\\"EventGroupId\\":\\t1,\\n\\t\\"EventType\\":\\t101,\\n\\t\\"CallbackTs\\":\\t1608086882372,\\n\\t\\"EventInfo\\":\\t{\\n\\t\\t\\"RoomId\\":\\t20222,\\n\\t\\t\\"EventTs\\":\\t1608086882,\\n\\t\\t\\"UserId\\":\\t\\"222222_phone\\"\\n\\t}\\n}"
    var key = "789"
    
    //JSRUN引擎2.0,支持多达30种语言在线运行,全仿真在线交互输入输出。
    fmt.Println(hmacsha256(data,key))
    }
    
    func hmacsha256(data string, key string) string {
    h := hmac.New(sha256.New, []byte(key))
    h.Write([]byte(data))
    return base64.StdEncoding.EncodeToString(h.Sum(nil))
    }
    
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持