tencent cloud

文档反馈

云端录制回调

最后更新时间:2024-01-30 15:24:03
    本文针对 新版云端录制功能 的回调事件进行具体说明。

    配置信息

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

    超时重试

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

    回调接口

    您可以提供一个接收回调的 HTTP/HTTPS 服务网关来订阅回调消息。当相关事件发生时,云录制系统会回调事件通知到您的消息接收服务器。

    事件回调消息格式

    事件回调消息以 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
    事件组 ID, 云端录制固定为3
    EventType
    Number
    回调通知的事件类型
    CallbackTs
    Number
    事件回调服务器向您的服务器发出回调请求的 Unix 时间戳,单位为毫秒
    EventInfo
    JSON Object
    事件信息

    事件类型说明:

    字段名
    类型
    含义
    EVENT_TYPE_CLOUD_RECORDING_RECORDER_START
    301
    云端录制录制模块启动
    EVENT_TYPE_CLOUD_RECORDING_RECORDER_STOP
    302
    云端录制录制模块退出
    EVENT_TYPE_CLOUD_RECORDING_UPLOAD_START
    303
    云端录制文件上传任务启动,仅在选择对象存储时回调
    EVENT_TYPE_CLOUD_RECORDING_FILE_INFO
    304
    云端录制 生成 m3u8 索引文件,第一次生成并且上传成功后回调,仅在通过 API 录制 选择对象存储时回调
    EVENT_TYPE_CLOUD_RECORDING_UPLOAD_STOP
    305
    云端录制文件上传结束,仅在选择对象存储时回调
    EVENT_TYPE_CLOUD_RECORDING_FAILOVER
    306
    云端录制发生迁移,原有的录制任务被迁移到新负载上时触发
    EVENT_TYPE_CLOUD_RECORDING_FILE_SLICE
    307
    云端录制 生成 m3u8 索引文件(切出第一个 ts 切片)生成后回调,仅在通过 API 录制 选择对象存储时回调
    EVENT_TYPE_CLOUD_RECORDING_DOWNLOAD_IMAGE_ERROR
    309
    云端录制下载解码图片文件发生错误
    EVENT_TYPE_CLOUD_RECORDING_MP4_STOP
    310
    云端录制 MP4 录制任务结束,仅在通过 API录制 选择对象存储时回调(控制台开启自动录制,选择授权给点播的 cos 作为存储时,请关注311事件)
    EVENT_TYPE_CLOUD_RECORDING_VOD_COMMIT
    311
    云端录制 VOD 录制任务上传媒体资源完成,在选择云点播时和通过控制台自动录制存储至 cos 时回调(录制文件结束后携带点播索引信息,请订阅此类型回调事件)
    EVENT_TYPE_CLOUD_RECORDING_VOD_STOP
    312
    云端录制 VOD 录制任务结束,仅在选择云点播时回调
    注意
    301-309区间的回调状态为实时录制的中间状态,可以更加清晰的知晓录制任务的进行过程并记录状态,实际录制文件上传到点播成功会回调311事件,整体任务结束回调312事件。

    事件信息说明:

    字段名
    类型
    含义
    RoomId
    String/Number
    房间名(类型与客户端房间号类型一致)
    EventTs
    Number
    时间发生的 Unix 时间戳,单位为秒 (不建议使用该字段,建议使用EventMsTs)
    EventMsTs
    Number
    事件发生的 Unix 时间戳,单位为毫秒
    UserId
    String
    录制机器人的用户 ID
    TaskId
    String
    录制 ID,一次云端录制任务唯一的 ID
    Payload
    JsonObject
    根据不同事件类型定义不同
    
    事件类型为301
    (EVENT_TYPE_CLOUD_RECORDING_RECORDER_START)时 Payload 的定义:
    字段名
    类型
    含义
    Status
    Number
    0:代表录制模块启动成功
    1:代表录制模块启动失败
    {
    "EventGroupId": 3,
    "EventType": 301,
    "CallbackTs": 1622186275913,
    "EventInfo": {
    "RoomId": "xx",
    "EventTs": "1622186275",
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 0
    }
    }
    }
    
    事件类型为302
    (EVENT_TYPE_CLOUD_RECORDING_RECORDER_STOP)时 Payload 的定义:
    字段名
    类型
    含义
    LeaveCode
    Number
    0:代表录制模块正常调用停止录制退出
    1:录制机器人被客户踢出房间
    2:客户解散房间
    3:服务器将录制机器人踢出
    4:服务器解散房间
    99:代表房间内除了录制机器人没有其他用户流,超过指定时间退出
    100:房间超时退出
    101:同一用户重复进入相同房间导致机器人退出
    {
    "EventGroupId": 3,
    "EventType": 302,
    "CallbackTs": 1622186354806,
    "EventInfo": {
    "RoomId": "xx",
    "EventTs": "1622186354",
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "LeaveCode": 0
    }
    }
    }
    
    事件类型为303
    (EVENT_TYPE_CLOUD_RECORDING_UPLOAD_START)时 Payload 的定义:
    字段名
    类型
    含义
    Status
    Number
    0:代表上传模块正常启动 1:代表上传模块初始化失败。
    
    事件类型为304
    (EVENT_TYPE_CLOUD_RECORDING_FILE_INFO )时 Payload 的定义:
    字段名
    类型
    含义
    FileList
    String
    生成的 M3U8 文件名
    
    事件类型为305
    (EVENT_TYPE_CLOUD_RECORDING_UPLOAD_STOP)时 Payload 的定义:
    字段名
    类型
    含义
    LeaveCode
    Number
    0:代表此次录制上传任务已经完成,所有的文件均已上传到指定的第三方云存储 1:代表此次录制上传任务已经完成,但至少有一片文件滞留在服务器或者备份存储上 2:代表滞留在服务器或者备份存储上的文件已经恢复上传到指定的第三方云存储
    注意:305代表hls文件上传结束事件
    
    事件类型为306
    (EVENT_TYPE_CLOUD_RECORDING_FAILOVER)时 Payload 的定义:
    字段名
    类型
    含义
    Status
    Number
    0:代表此次迁移已经完成
    {
    "EventGroupId": 3,
    "EventType": 306,
    "CallbackTs": 1622191989674,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191989,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 0
    }
    }
    }
    
    事件类型为307
    (EVENT_TYPE_CLOUD_RECORDING_FILE_SLICE)时 Payload 的定义:
    字段名
    类型
    含义
    FileName
    String
    m3u8 文件名
    UserId
    String
    录制文件对应的用户 ID
    TrackType
    String
    音视频类型 audio/video/audio_video
    BeginTimeStamp
    String
    录制开始时,服务器Unix时间戳(毫秒)
    
    事件类型为309
    (EVENT_TYPE_CLOUD_RECORDING_DOWNLOAD_IMAGE_ERROR)时 Payload 的定义:
    字段名
    类型
    含义
    Url
    String
    下载失败的 URL
    {
    "EventGroupId": 3,
    "EventType": 309,
    "CallbackTs": 1622191989674,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191989,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Url": "http://xx"
    }
    }
    }
    
    事件类型为310
    (EVENT_TYPE_CLOUD_RECORDING_MP4_STOP)时 Payload 的定义:
    说明
    310 是上传mp4文件到客户指定第三方云存储COS完成后的回调事件,一个录制任务可能会回调多个310事件(每个事件对应一个录制文件信息)
    段名
    类型
    含义
    Status
    Number
    0:代表此次录制 mp4 任务已经正常退出,所有的文件均已上传到指定的第三方云存储
    1:代表此次录制 mp4 任务已经正常退出,但至少有一片文件滞留在服务 器或者备份存储上  2:代表此次录制 mp4 任务异常退出(可能原因是拉取 cos 的 hls 文件失败)
    FileList
    Array
    所有生成的 mp4 文件名
    FileMessage
    Array
    所有生成的 mp4 文件信息
    FileName
    String
    mp4 文件名
    UserId
    String
    mp4 文件对应的用户 ID(当录制模式为混流模式时,此字段为空)
    TrackType
    String
    audio 音频 / video 纯视频 / audio_video 音视频
    MediaId
    String
    主辅流标识,main 代表主流(摄像头),aux 代表辅流(屏幕分享),mix 代表混流录制
    StartTimeStamp
    Number
    mp4 文件开始的 Unix 时间戳(毫秒)
    EndTimeStamp
    Number
    mp4 文件结束的 Unix 时间戳(毫秒)
    {
    "EventGroupId": 3,
    "EventType": 310,
    "CallbackTs": 1622191965320,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191989,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 0,
    "FileList": ["xxxx1.mp4", "xxxx2.mp4"],
    "FileMessage": [
    {
    "FileName": "xxxx1.mp4",
    "UserId": "xxxx",
    "TrackType": "audio_video",
    "MediaId": "main",
    "StartTimeStamp": 1622186279145,
    "EndTimeStamp": 1622186282145
    },
    {
    "FileName": "xxxx2.mp4",
    "UserId": "xxxx",
    "TrackType": "audio_video",
    "MediaId": "main",
    "StartTimeStamp": 1622186279153,
    "EndTimeStamp": 1622186282153
    }
    ]
    
    }
    }
    }
    
    事件类型为311
    (EVENT_TYPE_CLOUD_RECORDING_VOD_COMMIT)时 Payload 的定义:
    字段名
    类型
    含义
    Status
    Number
    0:代表本录制文件正常上传至点播平台
    1:代表本录制文件滞留在服务器或者备份存储上
    2:代表本录制文件上传点播任务异常
    UserId
    String
    本录制文件对应的用户 ID(当录制模式为合流模式时,此字段为空)
    TrackType
    String
    audio 音频 / video 纯视频 / audio_video 音视频
    MediaId
    String
    主辅流标识,main代表主流(摄像头),aux代表辅流(屏幕分享),mix代表混流录制
    FileId
    String
    本录制文件在点播平台的唯一 ID
    VideoUrl
    String
    本录制文件在点播平台的播放地址
    CacheFile
    String
    本录制文件对应的 MP4/HLS 文件名
    StartTimeStamp
    Number
    本录制文件开始的 UNIX 时间戳(毫秒)
    EndTimeStamp
    Number
    本录制文件结束的 UNIX 时间戳(毫秒)
    Errmsg
    String
    statue 不为0时,对应的错误信息
    上传成功的回调:
    {
    "EventGroupId": 3,
    "EventType": 311,
    "CallbackTs": 1622191965320,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191965,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 0,
    "TencentVod": {
    "UserId": "xx",
    "TrackType": "audio_video",
    "MediaId": "main",
    "FileId": "xxxx",
    "VideoUrl": "http://xxxx",
    "CacheFile": "xxxx.mp4",
    "StartTimeStamp": 1622186279153,
    "EndTimeStamp": 1622186282153
    }
    }
    }
    }
    上传失败的回调:
    {
    "EventGroupId": 3,
    "EventType": 311,
    "CallbackTs": 1622191965320,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191965,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 1,
    "Errmsg": "xxx",
    "TencentVod": {
    "UserId": "123",
    "TrackType": "audio_video",
    "CacheFile": "xxx.mp4"
    }
    }
    }
    }
    说明
    录制完成收到311回调后到文件上传完成,根据您本次录制文件的大小不同可能需等待30s-3min。
    
    事件类型为312
    (EVENT_TYPE_CLOUD_RECORDING_VOD_STOP)时 Payload 的定义:
    字段名
    类型
    含义
    Status
    Number
    0:代表本次上传 VOD 任务已经正常退出
    1:代表本次上传 VOD 任务异常退出
    {
    "EventGroupId": 3,
    "EventType": 312,
    "CallbackTs": 1622191965320,
    "EventInfo": {
    "RoomId": "20015",
    "EventTs": 1622191965,
    "EventMsTs": 1622186275757,
    "UserId": "xx",
    "TaskId": "xx",
    "Payload": {
    "Status": 0
    }
    }
    }

    计算签名

    签名由 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 电话支持