ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于WebRTC与Canvas的SaaS客服远程演示与实时协作方案

基于WebRTC与Canvas的SaaS客服远程演示与实时协作方案 1. 项目背景SaaS客服的看不见摸不着之痛SaaS产品的客服大概是整个公司里最难做的岗位之一。产品看不见摸不着客户遇到问题的时候你没法像卖实体商品一样把东西递到他手里让他自己摆弄。于是大量的时间耗在你打开右上角的设置哪个右上角就那个齿轮图标没有齿轮啊这样的拉锯战里。我一直想解决这个问题直到把TWT Chat的实时通信能力和WebRTC、Canvas标注结合起来做了一套远程演示实时协作的全栈方案才真正把客服支援从讲电话变成了手把手带教。这个方案解决的事情一句话就能说清客服通过TWT Chat开一个支持房间客户点链接进入客服端开启屏幕共享把自己的操作界面实时推到客户屏幕中央同时双方在同一个画布上圈画标注客服写下这里点这个按钮客户也能反向圈出自己卡住的地方遇到需要客户亲自动手的环节客服还能把操作权交过去客户在界面上点客服在旁边盯着纠正。整个过程由全栈代码支撑前端处理交互与渲染后端管理会话、权限和全程记录。这篇文章不是给你讲PPT概念而是把我实际落地这套方案时踩过的坑、验证过的设计、调优过的参数都整理出来。适合三类人看SaaS产品经理想了解客服场景的技术边界前端工程师想搞懂实时协作类功能怎么从零接起来后端工程师想弄明白信令、状态同步和权限控制的难点在哪里。下面我从痛点说起再逐层给出方案尽量做到你照着思路就能搭出一版可用原型。1.1 三大痛点说不清、看不见、改不动先说客服场景里最典型的三个问题。第一个是说不清。SaaS界面的操作链路往往很长从入口到功能可能要跨四五个页面客服在电话里描述你先点左侧菜单的第三个图标再点右上角的蓝色按钮对方大概率是懵的。纯文字的客服话术在这种场景下效率极低一次问题平均要来回沟通七八轮才能确认对方到底卡在哪一步。第二个是看不见。客户报障时往往会说我这页面跟你们文档里不一样但客服看不到客户的屏幕只能靠猜。远程控制类的工具在一些场景里合规门槛高客户也会有隐私顾虑直接全屏控制并不现实。我们需要的是一种轻量、透明、可随时退出的可见性而不是入侵式的控制。第三个是改不动。就算客服讲清楚了很多操作必须客户自己完成比如点一个配置开关、填一个表单字段。客户边听边操作心里本来就紧张客服又看不到他操作到哪里出了问题只能从头再描述一遍。这种沟通-操作的断层是客服满意度上不去的根源。这三点叠加在一起逼迫我们必须换一种交互方式。1.2 为什么必须上远程演示实时协作分析完痛点方案方向其实就清楚了把说变成看把看升级为一起操作。远程演示解决看不见和说不清客服把屏幕共享出来客户跟着画面走不需要任何抽象的描述实时协作解决改不动双方在共享画布上交互必要时移交操作权让客户在指导下亲手完成。我一开始也犹豫过要不要直接上现成的远程协助工具类似TeamViewer那类。后来否掉了原因有三个一是外部工具没法嵌入我们自己的产品界面客服要先开一个独立软件会话记录也拿不到二是成本不低按坐席按年收费算下来一套演示功能比我们半个客服系统还贵三是数据和合规层面客户的操作数据经过第三方服务器SaaS客户本身就对数据流向敏感。与其这样不如基于TWT Chat自研一条轻量通道把演示和协作彻底做成自己产品的一部分。方案定了之后全栈架构的设计才有明确的落点。2. 技术选型与全栈架构设计2.1 需求倒推先列通信能力清单选型之前我习惯先写需求清单把抽象的远程演示实时协作拆成一组可验证的能力项。基于客服的真实使用流程我列了七条第一客服能一键创建支持房间并生成短链接第二客户无需安装任何客户端浏览器打开链接就能进第三房间内支持实时屏幕画面传输第四双方能在共享内容上做标注并看到对方的操作轨迹第五操作权可以在客服和客户之间切换第六全程操作事件可记录方便事后复盘第七会话结束后房间自动销毁数据按企业策略留存。这七条看着不多但每一条都会牵扯到具体的技术选型。第一条和第二条决定了我必须有一个托管式的房间管理系统而不是自己从头写长连接服务第三条决定我要用WebRTC的屏幕分享而不是简单的图片轮播第四条决定画布同步和消息通道的可靠性第五条把权限模型变成了实时状态机第六条要求所有客户端动作都要上报到服务端落库。写到这里技术边界已经基本划出来了选型也就有了明确的目标。2.2 为什么选了TWT Chat而不是自研IM很多团队看到实时两个字第一反应是自己搭WebSocket服务。我团队早期也这么干过后来被现实教育了。自研IM的坑不在发消息本身而在那些平时根本想不到的角落连接保活、网络切换重连、消息时序、离线消息补推、多端一致性、频道权限管理再到各种移动端浏览器的兼容差异。这些东西每一个单独拿出来都不算难但合在一起足够拖住一个前端和一个后端全职干两个月而且上线后还得持续维护。TWT Chat的优势恰恰在这里它在实时消息和信令通道这件事上是成熟的。我把房间管理、消息投递、在线状态、断线重连这些事情全部交给它自己只需要关心业务层的画布同步逻辑和权限状态机。选它还有个实际原因支持自定义信令消息WebRTC的offer、answer、ICE candidate都可以直接塞进消息通道里传这等于把最麻烦的NAT穿透信令部分也包掉了。成本上按并发或消息量计费对客服场景来说远比自建服务器加带宽可控。我当时也认真对比过几类方案直接雇人自研IM、用通用聊天SDK套壳、用开源自托管IM组件。通用聊天SDK的问题在于它的消息模型是围绕对话设计的对自定义信令和实时协作文档的支持往往很别扭开源自托管组件部署起来不复杂但高可用和跨地域加速需要自己养运维团队没有这个余力。综合下来TWT Chat这种托管实时通道业务自研的组合最切合需求也是很多SaaS团队会走的路子。2.3 整体架构与数据流架构上我把它分成三层。最底层是TWT Chat的实时基础设施负责维持客户端与会话服务之间的稳定长连接内部具体的节点调度我不用关心只需要拿到两个关键东西一个是roomId标识一场支持会话一个是可自定义的信道所有业务消息都从这条信道走。中间层是业务服务端用Node.js写的一组接口职责包括创建房间时向TWT申请合法凭证、把客户链接和客服ID绑定、记录全量操作事件、控制会话生命周期。业务服务端不参与画布内容的实时转发那些高频消息直接走客户端之间的实时通道服务端只做异步的事件落库。这么设计是避免服务端成为性能瓶颈画布操作一秒钟可能产生几十条消息如果每条都经服务端中转再转存数据库成本会高得离谱延迟也扛不住。最上层是两端的前端应用。客服端和管理后台跑在PC浏览器里客户扫码或点链接进入后是一个独立的极简页面。客户端的页面刻意做得很轻只保留视频画面区、共享画布区和聊天栏避免客户被复杂界面打扰。数据流的走向是客服端把屏幕共享流通过WebRTC发给客户端双方对画布的操作通过TWT信令通道同步给彼此业务事件加入房间、交接操作权、结束会话全部发给服务端记录。整个链路里WebRTC管画面TWT管信令和协作消息业务服务端管状态和审计各司其职。3. 核心实现前端交互与协作链路3.1 客服端发起演示的操作流程客服端流程的核心是把五个步骤串起来建房间、取屏幕流、发信令、共享画面、开启画布协作。第一步是创建支持房间前端调用TWT SDK的createRoom方法传入会话类型和使用的凭证拿到roomId后由业务接口生成短链接客服把链接通过原有IM工具发给客户。第二步是获取屏幕共享流这一步用的是浏览器原生能力navigator.mediaDevices.getDisplayMedia。需要注意这个接口必须由用户手势触发也就是客服点击开始演示按钮后立刻调用弹窗选择共享整个屏幕还是单个窗口。我建议在客服端把默认选项引导到应用窗口而不是整个屏幕一方面保护客服自己的隐私别把微信聊天窗口共享出去另一方面窗口模式的画面更聚焦客户的观看体验反而更好。拿到MediaStream之后把它绑定到客服端本地的video元素上用于预览同时通过RTCPeerConnection把轨道添加到连接里。第三步是信令交换客服端创建offer通过TWT的信令通道发给客户客户回answer双方再交换ICE候选P2P连接就建立了。这几步虽然是WebRTC的标准流程但每一步都通过TWT的消息发送接口转发等于把信令接力棒交给了托管通道省去了自己维护WebSocket服务器的麻烦。3.2 客户端的极简接入体验客户端的核心诉求是零安装、零门槛。客户在浏览器里打开短链接页面先展示一个进入确认界面说明客服将向你共享屏幕画面你可以随时结束会话这个告知环节不只是体验问题还是在替合规兜底。点击进入后前端完成两件事用URL参数里的roomId加入TWT房间再初始化一个RTCPeerConnection等待接收客服端的offer并进行answer流程。在客户端的渲染上画面分为两个区域上方是共享画面下方是尺寸可调的画布层。画布层默认透明只有双方开始标注时才显示笔迹。页面右上角常驻一个退出按钮一键离开房间并释放所有媒体连接。对于移动端我用的是响应式布局共享画面可以双指缩放画布标注也能用手势操作因为实际客服场景里有相当一部分客户是用手机看演示的这个体验必须提前做好。3.3 画布同步与光标跟随画布协作是最容易做翻车的地方。我采用的方案是共享画面区域上覆盖两层Canvas一层专门画客服的标注另一层画客户的标注两层透明叠加视觉上呈现为同一块白板。每个Canvas监听pointerdown、pointermove、pointerup事件把坐标、线条宽度、颜色打包成一条协作消息通过TWT信道广播给对方。这里最大的坑是坐标系换算。屏幕共享流的实际像素和客户浏览器里渲染画布的大小几乎不可能一致如果直接把客服端的画布坐标发给客户用画出来的笔迹一定会错位。我的办法是约定一个逻辑坐标系所有事件里的坐标都以相对画布宽高的比例传输客户端收到后按自己的画布实际尺寸换算。比如客服端在宽度80%位置点了一下消息体里存的是0.8而不是像素值客户端的画笔就会落到自己画布的80%位置。测试下来这个方案在窗口缩放和移动端横竖屏切换时都能保持对齐。光标跟随则是在消息里增加一个type为cursor的事件频率做了降频处理每100毫秒最多发一条避免高频移动产生消息风暴。光标的视觉样式在对方端是半透明圆形自己这边的光标始终是正常系统样式不会互相干扰。降频的副作用是快速移动时轨迹会有一点点卡顿但实测在客服引导场景下完全够用画面干净清晰反而比高频乱跳更利于理解。3.4 操作权移交的权限模型权限模型我只设计了四种状态演示中、协作中、客户操作中、已结束。初始状态是演示中客服端共享画面为主客户只能看和标注实际操作权仍属于客服。协作中表示双方都能在画布上标注但不能控制界面。客户操作中则是一次正式的操作权移交客服端会显示一个明显的观察模式遮罩屏幕共享照常进行但画面标注的视觉重点从客服转移到客户那边的动作上。状态切换由客服端发起的控制消息触发客户同意后会有一条系统消息留在会话记录里。这个同意环节非常关键它保证了操作权移交不是一个单方面的动作双向都有感知。权限状态机我在业务服务端也维护了一份副本尽管画布消息走实时通道但状态变更必须经过服务端确认这样如果有人绕过前端直接调接口服务端能拦住非法状态变更不至于出现两边权限状态不一致的混乱局面。4. 后端服务与会话管理4.1 会话创建与客服分配逻辑后端我选了Node.js配合Express接口不多但职责明确。第一个接口是创建会话格式大致是POST /api/support/session请求体里带上客服ID和客户标识服务端先去TWT申请房间凭证再往数据库插入一条会话记录状态为active最后把roomId和短链接拼好返回给客服端。短链接我用的是无状态的跳转码跳转时再解析成正式参数好处是链接短、好传播客服报障时复制一条短链接发过去也美观。客服分配逻辑没有做复杂的排队策略。我们产品目前的客服团队是按客户分组划分的所以分配逻辑就是根据客户所属企业找到对应的客服组如果该组有在线客服就直接把会话绑到他名下没有在线客服则标记为待分配进入统一队列。这个逻辑虽然简单但满足现阶段业务需要未来如果需要负载均衡式的分配只需在分配函数里增加一个在线人数权重即可改造成本很低。4.2 业务事件记录与回放能力全栈方案里我特意保留了事件记录因为客服团队非常需要事后复盘。复盘不是只看聊天记录就够的而是要还原当时双方的操作轨迹。服务端在会话进行中会持续接收客户端的埋点事件事件种类包括加入房间、开始演示、标注操作、光标移动抽样、操作权移交、退出房间每一条都带时间戳和角色标识按会话ID归档。归档后的数据有两种用途。一种是运营分析统计单次会话的平均标注数、操作权移交次数、持续时长用来评估客服的引导效率另一种是回放把事件按时间轴重放到一个模拟画布上客服主管可以在后台看一段完整的服务过程。回放的实现比实时画面简单得多因为不需要视频流只需要按时间戳重放画布事件就行。为了控制存储量我没有存原始屏幕视频这既省了存储成本也降低了敏感画面泄露的风险。4.3 安全与合规设计客服远程演示功能天然会触碰敏感数据安全设计这块不能省。首先是房间令牌TWT的room凭证我设置了短有效期默认15分钟客服创建房间后如果客户迟迟没进来会话要自动刷新凭证防止长期有效的链接被滥用。其次是客户身份短链接本身不承载客户身份信息关键操作都要求客户在进入页面时填写专属的访问码访问码由业务系统生成与服务端记录的客户账号绑定。再说数据合规。屏幕共享画面本身不会被服务端录制只有事件数据会落库这一点我在隐私说明里写得很清楚。操作权移交、屏幕共享开始和结束等关键动作都会写入审计日志保留时间按企业策略配置默认180天。网络层面TWT的通道全程走TLSWebRTC的媒体流也强制使用加密浏览器默认就会做加密协商但服务端配置时要注意别把协商策略降级否则容易被人抓到明文协商的空子。5. 部署配置与参数调优5.1 关键参数对照表这套方案里我实际调优过一组参数每次调整背后都有明确的业务原因。我把它们列成一张表方便你直接对照。参数初始值调优后调优原因TWT房间凭证有效期5分钟15分钟客户进房前可能要切换网络或重新登录5分钟经常过期WebRTC ICE超时5秒10秒部分企业网络穿透慢5秒在弱网下频繁失败标注消息降频阈值无限制每50ms合并1条高速划线时消息量暴涨合并后体验基本无感光标消息降频每帧发送每100ms发送1条高频光标消息占用信道降频后画面更流畅会话事件抽样全量光标事件抽样10%落库的光标事件量太大抽样对复盘影响可忽略客户端视频码率上限2.5Mbps1.5Mbps操作界面多为静态画面高码率纯粹浪费带宽这几个参数不是拍脑袋定的每条都经历过线上现象倒推。比如ICE超时从5秒改成10秒是因为上线第二天有大量客户反馈进房间后一直转圈排查日志发现ICE candidate交换在7到8秒才完成5秒的超时被误杀。改成10秒后转圈问题基本消失代价是极端弱网下进入房间的等待变长一点点但总比进不去强。5.2 网络环境的坑如果要给这套方案挑一个最让人头疼的外部因素那就是客户侧的复杂网络。有的客户在企业内网UDP被封或QoS严重有的客户的办公室Wi-Fi是访客网络跨部门带宽互相挤压。WebRTC在理想网络环境下非常顺滑但在这种环境里没有配置好TURN服务的方案就像没带救生圈下水。我的教训是TURN服务一定不能省而且要选就近节点。我在生产环境里配了多地域的TURN集群客户接入时会根据IP地理位置分配到最近的TURN节点。这里要特别提醒TURN服务器不仅仅是备胎当双方网络无法建立P2P时所有媒体流量都会经过TURN中转它的带宽成本是实打实的。所以我在客服端做了一个策略优先尝试P2PP2P失败超过3秒再切换TURN避免正常的P2P连接也被迫走中转浪费成本。客户端的WebRTC事件能暴露连接类型我把这个信息透传到服务端记录每个会话最终使用的传输路径便于复盘网络问题时定位。6. 常见问题与排查实录6.1 连接不稳定总是中途断开这类问题的排查思路是先把信令断了和媒体断了分开。如果是客户端的画面黑屏但标注还能同步那说明TWT的信令通道还活着出问题的是WebRTC媒体链路反过来如果双方都收不到画布更新但视频正常那就是信令消息出了问题。我实际遇到最多的是前者根源多为企业网络对UDP的拦截导致P2P媒体流中断浏览器会自动尝试ICE重协商但重协商要重新交换candidate整个过程在弱网下很慢。解决方法有两层。一层是在前端监听ICEConnectionState变化一旦进入disconnected状态就主动触发一次ICE restart而不是等浏览器自己慢慢恢复另一层是服务端配置了TURN兜底并且在前端做了3秒内未恢复就切TURN的强逻辑。这两层叠加后实际掉线率下降了约七成。要提醒的是ICE restart要小心处理别每秒钟触发一次否则会造成信令风暴我当时加了一个15秒的冷却窗口。6.2 画布笔迹错位标注画到屏幕外画布错位通常有两个来源一是坐标系换算没做好二是画布层的尺寸没跟上页面布局变化。坐标系的坑我在前面已经讲过统一用相对比例传输后基本不会错。真正棘手的是第二个来源客户在演示过程中手动缩放页面或旋转了屏幕而画布层尺寸没有同步更新导致接收端换算出的坐标落在可视区域之外。排查这类问题时我先在协议层加了版本号和画布尺寸字段每次画布尺寸变化或者页面可见性恢复后双方都要交换一次最新的画布元信息这样即使在播放中途发生布局变化也能在几百毫秒内重新对齐。另外一个偏门但常见的坑是浏览器缩放率用户如果在浏览器里用Ctrl加滚轮放大了整个页面Canvas拿到的事件坐标是逻辑像素还是物理像素很容易混淆。我在初始化时统一用getBoundingClientRect()配合事件的offsetX和offsetY取相对坐标从源头规避了这个偏差。6.3 屏幕共享黑屏客户只能看到一片黑黑屏问题排查起来有几类原因。最常见的是客服端在选择共享窗口时选了被遮挡的窗口画面被其他窗口完全盖住WebRTC采集到的内容就是黑的。其次是浏览器安全策略变更某些版本的浏览器在窗口最小化后不采集画面内容需要客服保持共享的目标窗口可见。这类问题前端能做的干预有限只能通过提示引导用户在共享时保持窗口在前台。真正需要代码处理的是另一种共享开始时一切正常中途客服端锁屏或者切换了虚拟桌面导致采集流中断。我在客服端做了一个心跳检测每10秒读取一次屏幕流的视频轨道的readyState如果发现ended且客服没有主动结束共享就弹出一个重新共享的引导提示并自动暂停画布协作避免客户对着一个黑屏蒙圈。实测这个提示能显著降低人工介入的成本客户端的负面反馈也少了很多。6.4 高并发房间时消息延迟变大刚上线时我们预估并发不高单机服务端挂着跑结果活动推广日一下子涌进来两百多个同时在线房间客户开始反馈画布跟手度下降。我查了TWT侧的消息统计发现是消费者端接收频率太高大量高频标注消息挤占了信道带宽。定位后做了两件事第一请求服务端提升该实例的消息QoS配置在管理后台直接调整第二在前端把标注消息从每条都发改成本地聚合并节流在高频划线场景下按50ms窗口聚合后再发出。聚合后的效果很直接信道内消息量降到原来的三分之一而视觉上几乎没有区别。这里也让我意识到实时协作类的性能问题很大一部分可以通过降低无效消息量解决而不是一味加服务器配置。后来我还给客户端加了一个低带宽模式自动降低画布消息频率和视频码率作为弱网环境下的最后手段这个开关放在设置面板里由客户自己按需开启。收尾几点项目体会最后分享几个这个项目让我印象最深的点。第一实时协作功能不能只盯着实时一定要预留事件记录和回放的通道客服团队复盘时真的会用这些数据而且这些数据也是你向客户证明服务质量的重要依据。第二权限模型宁可先严格后放宽操作权移交必须有客户侧确认这一点省了非常多的扯皮和投诉。第三网络问题不要指望一个方案能覆盖所有场景P2P加TURN兜底、ICE restart、消息降频这些都是老经验但每个都要结合自己的用户画像去调参。做这套方案之前我以为难点在WebRTC和画布同步做完之后才发现真正的难点是让所有环节在真实、复杂的客户网络环境下都能保持可用。希望我的这些记录能给正在踩类似坑的人一些参考。
返回列表