Files
zyt/admin/CRITICAL_FIX.md
T
2026-03-04 15:32:30 +08:00

5.8 KiB

关键修复:TUICallKit 初始化问题

问题描述

在使用 TUICallKit 组件时,出现以下错误:

API<getDeviceList>: init or login is not complete
TUICallEngine 初始化登录未完成
<ERROR_INIT_FAIL: -1201>

根本原因

TUICallKit 组件在挂载(mount)时会立即调用内部 API(如 getDeviceList),但此时 TUICallKitServer.init() 可能还没有完全完成初始化。

即使我们在代码中等待了 await TUICallKitServer.init(),组件内部的初始化仍需要额外的时间。

解决方案

方案 1: 增加等待时间(当前采用)

// 1. 调用 init
await TUICallKitServer.init({
  userID: res.userId,
  userSig: res.userSig,
  SDKAppID: res.sdkAppId
})

// 2. 等待 2 秒确保初始化完全完成
await new Promise(resolve => setTimeout(resolve, 2000))

// 3. 显示组件
isInitialized.value = true

// 4. 等待 DOM 更新
await nextTick()

// 5. 再等待 500ms
await new Promise(resolve => setTimeout(resolve, 500))

// 6. 发起通话
await TUICallKitServer.call({ ... })

方案 2: 不使用 TUICallKit 组件(备选)

如果方案 1 仍然有问题,可以考虑不使用 TUICallKit 组件,而是使用 div 容器:

<!-- 不使用组件 -->
<div v-else id="TUICallKit" class="tui-call-kit"></div>

然后 TUICallKit 会自动将 UI 渲染到这个 div 中。

当前实现

关键代码

const startCall = async () => {
  try {
    initializing.value = true
    statusText.value = '正在获取签名...'
    
    // 1. 获取签名
    const res = await getCallSignature({ ... })
    
    statusText.value = '正在初始化通话组件...'
    
    // 2. 初始化
    await TUICallKitServer.init({
      userID: res.userId,
      userSig: res.userSig,
      SDKAppID: res.sdkAppId
    })
    
    statusText.value = '等待初始化完成...'
    
    // 3. 等待 2 秒(关键!)
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    statusText.value = '初始化完成,准备发起通话...'
    
    // 4. 显示组件
    isInitialized.value = true
    calling.value = true
    
    // 5. 等待 DOM 更新
    await nextTick()
    
    // 6. 再等待 500ms
    await new Promise(resolve => setTimeout(resolve, 500))
    
    // 7. 发起通话
    await TUICallKitServer.call({
      userID: callInfo.value.userId,
      type: TUICallType.VIDEO_CALL
    })
    
    feedback.msgSuccess('通话已发起,等待对方接听...')
    
  } catch (error) {
    // 错误处理
  }
}

模板代码

<template>
  <div class="video-call-container">
    <!-- 初始化前显示等待界面 -->
    <div v-if="!isInitialized" class="call-waiting">
      <el-icon class="loading-icon"><VideoCamera /></el-icon>
      <p>{{ statusText }}</p>
    </div>
    
    <!-- 初始化完成后显示容器 -->
    <div v-else id="TUICallKit" class="tui-call-kit"></div>
  </div>
</template>

时间线

0ms     用户点击"开始通话"
        ↓
100ms   开始获取签名
        ↓
500ms   签名获取完成
        ↓
600ms   调用 TUICallKitServer.init()
        ↓
1000ms  init() Promise resolved
        ↓
3000ms  等待 2000ms 完成(确保内部初始化完成)
        ↓
3000ms  设置 isInitialized = true
        ↓
3000ms  Vue 开始渲染容器
        ↓
3010ms  nextTick() 完成
        ↓
3510ms  等待 500ms 完成
        ↓
3510ms  调用 TUICallKitServer.call()
        ↓
3600ms  通话发起成功

为什么需要这么长的等待时间?

  1. TUICallKitServer.init() 的异步性

    • 虽然 Promise resolved,但内部可能还有异步操作
    • 需要初始化 WebRTC、设备检测等
  2. 设备枚举需要时间

    • getDeviceList 需要访问摄像头和麦克风
    • 浏览器需要时间来枚举设备
  3. 权限请求

    • 如果是首次访问,需要用户授权
    • 授权过程是异步的
  4. 组件渲染

    • Vue 的响应式更新需要时间
    • DOM 操作需要时间

调试建议

1. 查看控制台日志

console.log('1. 签名获取成功')
console.log('2. TUICallKit init 方法调用完成')
console.log('3. 等待完成,准备显示通话界面')
console.log('4. 准备发起通话')
console.log('5. 通话已发起')

2. 检查初始化状态

在浏览器控制台执行:

// 检查 TUICallKitServer 状态
console.log(window.TUICallKitServer)

3. 监控设备访问

打开浏览器开发者工具 → Console,查看是否有设备访问相关的日志。

如果仍然失败

增加等待时间

如果 2 秒还不够,可以增加到 3 秒:

await new Promise(resolve => setTimeout(resolve, 3000))

使用轮询检查

// 轮询检查初始化状态
let retries = 0
const maxRetries = 20
while (retries < maxRetries) {
  try {
    // 尝试调用一个需要初始化的 API
    await TUICallKitServer.call({ ... })
    break
  } catch (error) {
    if (error.code === -1201) {
      // 还没初始化完成,继续等待
      await new Promise(resolve => setTimeout(resolve, 500))
      retries++
    } else {
      throw error
    }
  }
}

联系技术支持

如果以上方法都不行,可能需要:

  1. 检查腾讯云 TRTC 配置
  2. 检查网络连接
  3. 查看腾讯云控制台的错误日志
  4. 联系腾讯云技术支持

参考资料

更新日志

  • 2024-03-02: 初始版本,等待时间 500ms + 300ms
  • 2024-03-02: 增加等待时间到 2000ms + 500ms
  • 2024-03-02: 添加 nextTick() 确保 DOM 更新
  • 2024-03-02: 改用 div 容器而不是 TUICallKit 组件