移动端Web接入腾讯云TRTC实践(React+TS)

实时音视频服务在项目中出现的频率越来越高的,自己写webRTC的成本相对腾讯云的TRTC-SDK要多大得多,最近公司项目移动端和PC端Web(React+TS)小程序(Taro)中都有使用到,这里针对移动端web做实时通话做个记录与大家交流下

TRTC流程图

移动端Web接入腾讯云TRTC实践(React+TS)_第1张图片

相信准备接入或者已经在接入TRTC的小伙伴是看过文档实时音视频,这里不说这些概念了,直接上代码

一、安装TRTC依赖

pnpm i trtc-js-sdk @types/trtc-js-sdk -D

二、初始化TRTC实例

import TRTC from 'trtc-js-sdk'
// 创建TRTC实例
trtcInstance.current = TRTC.createClient({ 
    sdkAppId, // 腾讯云申请的appId
    userSig, // 用户签名,后端获取
    userId, // 随机生成的用户ID,不可重复
    mode: 'rtc' // 实时音视频通话模式
})
// 创建本地流Stream
localStreamRef.current = TRTC.createStream({ userId, audio: true, video: false })
// 绑定TRTC事件
bindTRTCEvent()

三、绑定TRTC事件

// TRTCEvent 可自行从trtc-js-sdk中获取到

trtcInstance.current?.on(TRTCEvent.NETWORK_QUALITY, (event) => {
  subscribeTrtcNetwork?.(event)
  // 监听网络变化 
  if (event.uplinkNetworkQuality > 3 || uplinkLoss > 3) {
     // 本地用户网络差,uplinkLoss(丢包率) 的值可自行调试
  } else if (network.downlinkNetworkQuality > 3 || network.downlinkLoss > 3) {
     // 远端用户网络差,downlinkLoss(丢包率) 的值可自行调试
  }
})
// 添加远程流
trtcInstance.current?.on(TRTCEvent.STREAM_ADDED, (event) => {
  const remoteStream = event.stream
  trtcInstance.current?.subscribe(remoteStream)
    .then(() => {
       // 远端用户进入房间
    })
    .catch((error) => {
      // 远端进入房间失败
    })
})
// 订阅远程流
trtcInstance.current?.on(TRTCEvent.STREAM_SUBSCRIBED, (event) => {
  const remoteStream = event.stream
  remoteStream.on('error', (error) => {
    // 远端流异常
  })
  // 创建播放容器
  const remotePlayerElement = document.createElement('div')
  remotePlayerElement.id = 'remote-stream-' + remoteStream.getId()
  document.body.appendChild(remotePlayerElement)
  remoteStream.play(remotePlayerElement.id)
})
// 有用户被赶出事件
trtcInstance.current?.on(TRTCEvent.CLIENT_BANNED, (error) => {
    // 远端用户异常推出房间
})
// 远端用户推流断开
trtcInstance.current?.on(TRTCEvent.STREAM_REMOVED, (event) => {
  // 远端用户推流断开
  const remoteStream = event.stream
  remoteStream.stop()
  remoteStream.close() // 离开房间释放资源
})
// 远端用户离开房间
trtcInstance.current?.on(TRTCEvent.PEER_LEAVE, (event) => {
  // 远端用户离开房间
})

四、进入房间

await trtcInstance.current?.join({ roomId })
// 初始化本地音视频流
await localStream.current?.initialize?.()
// 本地需创建一个localStream的dom
localStream.current?.play?.('localStream')
if (localStream?.current) {
    await trtcInstance.current?.publish?.(localStream.current)
}

五、退出房间

if (trtcInstance.current &&  localStream.current) {
  await trtcInstance.current?.unpublish?.(localStreamRef?.current)
  await trtcInstance.current?.leave()
  localStreamRef.current?.stop()
  localStreamRef.current?.close()
}

六、完整demo (hooks,无UI)

import { useRef } from 'react'
import TRTC, { Client, LocalStream } from 'trtc-js-sdk'

const useTRTC = () => {
  const trtcInstance = useRef<Client | null>(null)
  const localStream = useRef<LocalStream | null>(null)
  
  const init = () => {
      try {
        // 创建TRTC实例
        trtcInstance.current = TRTC.createClient({ 
            sdkAppId, // 腾讯云申请的appId
            userSig, // 用户签名,后端获取
            userId, // 随机生成的用户ID,不可重复
            mode: 'rtc' // 实时音视频通话模式
        })
        // 创建本地流Stream
        localStream.current = TRTC.createStream({ userId, audio: true, video: false })
        // 绑定TRTC事件
        bindTRTCEvent()
      } catch(error) {
        console.log('初始化TRTC失败', error)
      } 
  }
  
  const enterRoom = async () => {
    try {
         await trtcInstance.current?.join({ roomId })
        // 初始化本地音视频流
        await localStream.current?.initialize?.()
        // 本地需创建一个localStream的dom
        localStream.current?.play?.('localStream')
        if (localStream?.current) {
            await trtcInstance.current?.publish?.(localStream.current)
        }
    } catch (error) {
        console.log('进入房间失败', error)
    }
  }
  
  const exitRoom = async () => {
    if (trtcInstance.current &&  localStream.current) {
      await trtcInstance.current?.unpublish?.(localStream?.current)
      await trtcInstance.current?.leave()
      localStream.current?.stop()
      localStream.current?.close()
    }
  }
  
  const bindTRTCEvent = () => {
    trtcInstance.current?.on(TRTCEvent.NETWORK_QUALITY, (event) => {
      subscribeTrtcNetwork?.(event)
      // 监听网络变化 
      if (event.uplinkNetworkQuality > 3 || uplinkLoss > 3) {
         // 本地用户网络差,uplinkLoss(丢包率) 的值可自行调试
      } else if (network.downlinkNetworkQuality > 3 || network.downlinkLoss > 3) {
         // 远端用户网络差,downlinkLoss(丢包率) 的值可自行调试
      }
    })
// 添加远程流
    trtcInstance.current?.on(TRTCEvent.STREAM_ADDED, (event) => {
        const remoteStream = event.stream
        trtcInstance.current?.subscribe(remoteStream)
          .then(() => {
             // 远端用户进入房间
          })
          .catch((error) => {
            // 远端进入房间失败
          })
    })
    // 订阅远程流
    trtcInstance.current?.on(TRTCEvent.STREAM_SUBSCRIBED, (event) => {
        const remoteStream = event.stream
        remoteStream.on('error', (error) => {
          // 远端流异常
        })
        // 创建播放容器
        const remotePlayerElement = document.createElement('div')
        remotePlayerElement.id = 'remote-stream-' + remoteStream.getId()
        document.body.appendChild(remotePlayerElement)
        remoteStream.play(remotePlayerElement.id)
    })
    // 有用户被赶出事件
    trtcInstance.current?.on(TRTCEvent.CLIENT_BANNED, (error) => {
        // 远端用户异常推出房间
    })
    // 远端用户推流断开
    trtcInstance.current?.on(TRTCEvent.STREAM_REMOVED, (event) => {
        // 远端用户推流断开
        const remoteStream = event.stream
        remoteStream.stop()
        remoteStream.close() // 离开房间释放资源
    })
    // 远端用户离开房间
    trtcInstance.current?.on(TRTCEvent.PEER_LEAVE, (event) => {
        // 远端用户离开房间
    })
  }
  return {
      init,
      enterRoom,
      exitRoom,
      ....
  }
}

以上是TRTC的流程,除了这些,我们还有其他的重要流程,如:

  • 授权麦克风、摄像头权限(这里只针对麦克风)
  • 关闭麦克风
  • 通话期间保持常亮
  • 当前标签页是否进入后台
  • …(其他的还有的可交流)

注意:由于浏览器的安全策略,音视频自动播放必须用户与页面产生交互,否则无法自动播放;

移动端目前无法实现听筒和扬声器的切换(如果有小伙伴有实现方案,可以交流下)

其他更多的业务层的逻辑了,如有疑惑的,欢迎探讨,如果对你有帮助的,请手动点赞,谢谢!

你可能感兴趣的:(前端,腾讯云,react.js,typescript,实时音视频)