【将QQ内核融入应用】腾讯云即时通信TIM、实时音视频TRTC —— Web端接入经验分享

1,445 阅读6分钟

即时通信TIM官网地址 即时通信TIM SDK API文档地址 实时音视频TRTC官网地址 实时音视频TRTC SDK API文档地址

概念与可能造成疑惑的问题

  1. SDK 是什么? Github 地址 腾讯云将底层与后台代码封装混淆之后生成 SDK,用户下载 SDK 后,即可简单使用封装的功能。在这个包内包含了发送网络请求自动与腾讯云的服务器通信。 即时通信 IM 的前身是 QQ 的即时通信系统,我们抽离 QQ 的通用模块,并将其整合成适合终端接入的 IM SDK 及后台服务。 您可以把 IM SDK 理解为一个没有用户交互界面的 QQ,把 IM SDK 集成到您的 App 里,就相当于把一个 QQ 的内核集成在您的 App 内部。
  2. SDKAppID 与密钥的概念 在调 部分 SDK 接口时,需要传入的参数。 这两个东西需要从控制台生成。应用获得,与其他云平台操作步骤类似。 密钥是区分你是否是本人的关键,需要保管好,以防泄露。
  3. TIM 即时通信, TRTC 实时音视频,TRTC CALLING 三者的关系 TIM 专注于消息通信,TRTC 可以使用户进入一个房间进行音视频推流与接收,TRTC CALLING 可以向指定用户进行呼叫。可见问题:cloud.tencent.com/developer/a… img

img

  1. TRTC 音视频通话房间是什么? 不存在会自动生成,相当于一个不需要创建的频道。

1 TIM 即时通信接入

即时通信 IM 提供全球接入、单聊、群聊、消息推送、资料关系链托管、帐号鉴权等全方位解决方案,并提供完备的 App 接入、后台管理接口。 使用这些功能的逻辑是,下载腾讯云给出的SDK包,根据SDK包封装好的API进行调用。

引入 SDK 包 文档地址

推荐使用NPM 集成 创建实例并注册插件按照文档地址来即可,不再赘述。

用户登录注册/鉴权

官网文档 API文档

需要两个参数

  • UserID:旧称为 Identifier,用户登录即时通信 IM 时使用的用户名,即您 App 里的用户 ID。 例如,App 里有一个用户,该用户的 ID 是27149 ,那么您可以用27149作为登录即时通信 IM 的 UserID。
  • UserSig:用户登录即时通信 IM 时使用的密码,其本质是 App Server 用密钥对 UserID 等信息加密后的数据。 img

生成UserSig 文档

此处演示在前端生成方法: 直接用官方Demo里的js文件

image-20210730185603454.png

我们需要加以修改

原因:因为Demo里的 lib-generate-test-usersig.min.js是注册了全局方法GenerateTestUserSig()在 window 里,然后GenerateTestUserSig调用了这个方法,而我们的代码里没有注册过,所以我们不能直接使用,否则会提示找不到全局方法。

修改:将GenerateTestUserSig.js粘贴进lib-generate-test-usersig.min.js,并export 导出,这样需要生成UserSig的地方直接引入lib-generate-test-usersig.min.js里面的genTestUserSig()函数即可。

两个有启发的地方:这个博客github

image-20210730190038461.png

监听逻辑 与 SDK Ready

登录成功后,并不能马上使用SDK,而是需等待 sdk 处于 ready 状态后(监听事件 TIM.EVENT.SDK_READY)才能调用 sendMessage 等需要鉴权的接口。

这里我的解决方案是:在需要在调用的地方添加监听,在监听执行一次之后即撤销。

image-20210730192646931.png

群组相关

相关文档地址 群组系统介绍

群组自定义字段的使用

官网没有示例,使用方法为:

      let promise = window.tim.createGroup({
        type: TIM.TYPES.GRP_AVCHATROOM,
        name: state.formState.roomName,
        groupID: state.formState.roomID,
        introduction: state.formState.roomIntro,
        groupCustomField: [{ key: "partyBeginTime", value: partyBeginTime }],
      });

数组 + 键值对的形式,value 最好 toString()。 在取的时候是这样的 groupProfile.groupCustomField["0"].value

消息发送

API文档 需要注意的是创建消息的异步与发送消息异步的协调,而且自己发送的消息自己是不会收到的,如果需要显示自己发的消息,需要单独做处理。

其他很有用的文档地址

EVENT 事件列表文档 群成员对象的字段 接受到的消息的字段 这里接收到的消息存在一个数组里,每一个消息都是 e2 格式,需要遍历出来。

2 TRTC 实时音视频接入

API 文档地址

与 TIM 相同,第一步是引入SDK

官网地址 比 TIM 更简单一点。

加入房间

这里与 TIM 不同的是,不再有创建房间这一概念,加入即创建,退出即销毁。 加入房间通话后的流程为

  1. 创建TRTC client

        const client = TRTC.createClient({
          mode: "rtc",
          sdkAppId: window.options.SDKAppID,
          userId: state.formState.userID,
          userSig: state.userSig,
          useStringRoomId: true,
        });
    

    注意,如果 RoomID 你想整成字符串,需要跟上述代码一样 useStringRoomId: true,否则roomId 为 number 类型时,取值要求为 [1, 4294967294] 的整数; 详细限制请看这里

  2. client 加监听,进来之后需要监听,否则加入之后再监听可能错过消息

        client.on("stream-added", (event) => {
          const remoteStream = event.stream;
          console.log("远端流增加: " + remoteStream.getId());
          //订阅远端流
          client.subscribe(remoteStream);
        });
        client.on("stream-subscribed", (event) => {
          const remoteStream = event.stream;
          console.log("远端流订阅成功:" + remoteStream.getId());
          // 播放远端流
          remoteStream.play("remote_stream");
        });
    
  3. 初始化本地流 这里与 官方文档 无异,需要额外注意的一点是,这里无论如何不能重复执行,否则会出现两个乃至多个本地视频窗口

  4. 加入房间与推流,需要先加入之后再推流,这里我没有区分的需求,索性直接合起来写

        window.client
          .join({ roomId: roomID })
          .catch((error) => {
            console.error("进房失败 " + roomID + error);
            console.log(roomID);
          })
          .then(() => {
            console.log("进房成功");
            window.client
              .publish(localStream)
              .catch((error) => {
                console.error("本地流发布失败 " + error);
              })
              .then(() => {
                console.log("本地流发布成功");
              });
          });
    
  5. 取消推流与退出房间,取消推流时,本地的画面其实没有任何改变,对方那里自己的画面会消失,退出房间时,本地的对方画面消失,但都不会自动移除 video 元素,如有需要,自己移除。这里也与官网不一样,我合起来写了。

        console.log("leave1v1Room Action");
        window.client.unpublish(window.localStream).then(() => {
          console.log("取消推送");
          client
            .leave()
            .then(() => {
              // 退房成功,可再次调用client.join重新进房开启新的通话。
              console.log("leave success");
            })
            .catch((error) => {
              console.error("退房失败 " + error);
              // 错误不可恢复,需要刷新页面。
            });
        });
    

参考链接

www.cnblogs.com/fqh123/p/12… www.zhongweipeng.cn/2020/03/31/… blog.csdn.net/b7410852963…