当前位置: 首页 > news >正文

[特殊字符] 跨端视频通话实战:腾讯云 TRTC + IM(React Native Web)

前言

实时音视频通话已经成为远程办公、在线教育、远程医疗、客服系统等场景的标配功能。
本文将结合 腾讯云 TRTC(实时音视频)IM(即时通信),实现一个 React Native 移动端与 Web 端互通的视频通话 Demo

核心思路:

  • TRTC:承载音视频流,实现低延迟、高质量的视频通话。

  • IM:作为信令通道,实现呼叫、接听、挂断、状态同步。

最终效果:React Native 移动端和 Web H5 可以互相进行音视频通话。


一、环境准备

  1. 注册并开通腾讯云 TRTC 与 IM。

  2. 获取 SDKAppID密钥,用于生成 userSig

  3. 开发环境:

    • React Native:react-native-cli 或 Expo bare。

    • Web:npm install trtc-js-sdk tim-js-sdk


二、整体架构

1. 架构分工

  • IM:信令通道,处理呼叫邀请、接听、挂断、超时等逻辑。

  • TRTC:音视频流通道,负责推流和拉流。

  • 跨端支持:React Native 使用 trtc-react-native-sdk,Web 使用 trtc-js-sdk

2. 信令状态机

stateDiagram-v2[*] --> IdleIdle --> Calling : 发起呼叫Idle --> InCall : 被叫直接加入(快速接听)Calling --> InCall : 对方接听Calling --> Idle : 对方拒绝/超时InCall --> Ended : 挂断InCall --> Ended : 网络断开/异常退出Ended --> Idle : 重置状态

说明:

  • Idle:空闲状态,无通话。

  • Calling:呼叫方等待被叫响应。

  • InCall:双方进入房间,音视频通话中。

  • Ended:挂断或异常退出,通话结束。


3. 通话流程图

  发起方 A ------------------> 接收方 B|                               |发送呼叫信令 --------------------> 弹窗提示|                               |进入 TRTC 房间 <--------------- 接受邀请,进入房间|                               |视频通话进行中 <-------------- 双方流订阅成功|                               |发送挂断信令 -------------------> 退出房间|                               |退出房间 <--------------------- 停止播放/释放资源

三、信令约定

IM 消息体 JSON 示例:

// 呼叫邀请
{ "type": "call", "roomId": 1234 }// 接听同意
{ "type": "accept", "roomId": 1234 }// 拒绝通话
{ "type": "reject" }// 挂断
{ "type": "hangup" }// 超时未接听
{ "type": "timeout" }

四、核心实现

1. 初始化 IM

import TIM from 'tim-js-sdk';const tim = TIM.create({ SDKAppID: YOUR_APPID });
tim.login({ userID, userSig });// 监听消息
tim.on(TIM.EVENT.MESSAGE_RECEIVED, ({ data }) => {data.forEach(msg => {const payload = JSON.parse(msg.payload.data);console.log('收到消息:', payload);});
});

2. React Native 端逻辑

进入房间
import { TRTCCloud, TRTCCloudDef } from 'trtc-react-native-sdk';const trtc = TRTCCloud.sharedInstance();const enterRoom = (roomId, userId, userSig) => {trtc.enterRoom({sdkAppId: YOUR_APPID,userId,userSig,roomId,role: TRTCCloudDef.TRTCRoleAnchor}, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);trtc.startLocalPreview(true, viewId); // 打开摄像头trtc.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT); // 打开麦克风
};
挂断/退出房间
const hangUp = () => {trtc.stopLocalPreview();trtc.stopLocalAudio();trtc.exitRoom();tim.sendMessage({to: remoteUserId,conversationType: 'C2C',payload: { data: JSON.stringify({ type: 'hangup' }) }});
};
监听对方挂断
tim.on(TIM.EVENT.MESSAGE_RECEIVED, ({ data }) => {data.forEach(msg => {const payload = JSON.parse(msg.payload.data);if (payload.type === 'hangup') {trtc.stopLocalPreview();trtc.stopLocalAudio();trtc.exitRoom();alert('对方已挂断');}});
});

3. Web 端逻辑

进入房间
import TRTC from 'trtc-js-sdk';const client = TRTC.createClient({ mode: 'rtc', sdkAppId, userId, userSig });
await client.join({ roomId: 1234 });const localStream = TRTC.createStream({ audio: true, video: true });
await localStream.initialize();
await client.publish(localStream);client.on('stream-added', event => client.subscribe(event.stream));
client.on('stream-subscribed', event => {event.stream.play('remote-container'); // 渲染远端视频
});
挂断/退出房间
const hangUp = async () => {if (localStream) {await client.unpublish(localStream);localStream.stop();localStream.close();}await client.leave();tim.sendMessage({to: remoteUserId,conversationType: 'C2C',payload: { data: JSON.stringify({ type: 'hangup' }) }});
};
页面关闭/刷新处理
window.addEventListener('beforeunload', async () => {if (localStream) {await client.unpublish(localStream);localStream.stop();localStream.close();}await client.leave();
});

五、通话时序图

sequenceDiagramparticipant A as 呼叫方 (RN)participant IM as IM 信令participant B as 被叫方 (Web)participant TRTC as TRTC 服务A->>IM: 发送呼叫消息 {type:"call",roomId}IM->>B: 推送呼叫消息B->>B: 弹出接听/拒绝 UIB->>IM: 同意 {type:"accept",roomId}IM->>A: 通知接听A->>TRTC: enterRoom(roomId)B->>TRTC: enterRoom(roomId)TRTC-->>A: 远端流事件TRTC-->>B: 远端流事件A->>B: 视频通话中A->>IM: 发送 {type:"hangup"}IM->>B: 通知挂断B->>TRTC: exitRoom()A->>TRTC: exitRoom()

六、常见问题与解决

  1. 进房成功但看不到对方

    • 未调用 subscribe/play(Web)或 startRemoteView(RN)。

    • UDP 被阻塞 → 放通 TRTC 官方端口。

  2. userId 冲突

    • 每个用户必须唯一,否则会互踢。

  3. 浏览器自动播放限制

    • H5 页面必须用户点击才能播放视频。

  4. 退出异常导致“假用户”残留

    • 挂断、刷新页面、APP 退出时必须调用 exitRoom/leave

  5. 弱网适配

    • SDK 内置弱网抗抖,但建议开启视频降级策略,优先保证音频。

    • 使用 client.getTransportStats() 监控网络质量。


七、最佳实践

  1. 信令与媒体分层

    • IM 专注信令,TRTC 专注媒体流。

  2. UI 状态机

    • Idle → Calling → InCall → Ended

    • 每个状态对应 UI 和 TRTC/IM 逻辑。

  3. 错误码处理

    • TRTC 返回错误码时,结合官方文档快速定位。

  4. 安全

    • userSig 必须由服务端生成,防止泄露。


文章转载自:

http://5DchqYtQ.mrtdq.cn
http://3TjDaBxt.mrtdq.cn
http://M8tyvN4r.mrtdq.cn
http://v5551mC3.mrtdq.cn
http://Ubomewqp.mrtdq.cn
http://VJ6WzR5j.mrtdq.cn
http://DJh2zHz9.mrtdq.cn
http://UuOxFl0C.mrtdq.cn
http://HHUCYfTO.mrtdq.cn
http://GMsiF7Wb.mrtdq.cn
http://3b25Tq6y.mrtdq.cn
http://hZhB5x9J.mrtdq.cn
http://MgqTDl8a.mrtdq.cn
http://NwNBmsqG.mrtdq.cn
http://MV67k7f5.mrtdq.cn
http://5spWUwfd.mrtdq.cn
http://NO2JRAbP.mrtdq.cn
http://DlfNYTiZ.mrtdq.cn
http://mkybBgQ4.mrtdq.cn
http://JTS0CQx3.mrtdq.cn
http://ys3Vz8gg.mrtdq.cn
http://450w2nzW.mrtdq.cn
http://P8OdGMWK.mrtdq.cn
http://Pd46kXOL.mrtdq.cn
http://hGsQQtss.mrtdq.cn
http://QkStgFQ2.mrtdq.cn
http://cj4NGY5f.mrtdq.cn
http://eknnpkYc.mrtdq.cn
http://tInjdy11.mrtdq.cn
http://BHFDzTK1.mrtdq.cn
http://www.dtcms.com/a/372768.html

相关文章:

  • 【重学 MySQL】九十八、MySQL用户管理全指南:创建、修改、删除
  • 2025时序数据库选型,以IoTDB为主从架构基因到AI赋能来解析
  • 如何用表单快速构建一个用户反馈系统?
  • 2020/12 JLPT听力原文 问题四
  • 基于ConvFormer的双条件域自适应方法的故障诊断模型
  • Day 14: RAG检索增强生成核心技术 - 从原理到实战的完整指南 [特殊字符]
  • mysql 回表查询(二次查询,如何检查,如何规避)
  • vue3+ts使用html2canvas,实现页面截图
  • 疾病语音数据集 WAV格式音频
  • 07 下载配置很完善的yum软件源
  • 【PCIe EP 设备入门学习专栏 -- 8.2.2 PCIe EP Controller Register Types 介绍】
  • 排序---冒泡排序(Bubble Sort)
  • C++/QT day8(9.8)
  • 【Linux网络编程】传输层协议-----UDP协议
  • 医疗连续体机器人模块化控制界面设计与Python库应用研究(上)
  • 分享|构建产教融合的一体化人工智能实验室综合解决方案
  • 从固定 px 到响应式:Vue + Vite 项目响应式改造实战,解决前端不适配的问题
  • java面试:了解MVCC么,详细解释一下
  • ChatGPT 协作调优:把 SQL 查询从 5s 优化到 300ms 的全过程
  • 长春高新需要新叙事
  • Python用PSO优化SVM与RBFN在自动驾驶系统仿真、手写数字分类应用研究
  • android studio JNI 环境配置实现 java 调用 c/c++
  • 安卓非原创--基于Android Studio 实现的新闻App
  • Flutter Android Studio开发实用技巧
  • Android Studio适配butterknife遇到的坑
  • 论文精读(五):面向链接预测的知识图谱表示学习方法综述
  • 使用AI工具一句话生成PPT
  • 《嵌入式硬件(五):IMX6ULL所需的基础》
  • Vue响应式更新 vs React状态更新:两种范式的底层逻辑与实践差异
  • Qt UDP 网络编程详解