mediasoup-client Transport 完全指南:sendTransport 与 recvTransport 实战详解
mediasoup-client Transport 完全指南sendTransport 与 recvTransport 实战详解【免费下载链接】mediasoup-clientmediasoup client side JavaScript library项目地址: https://gitcode.com/gh_mirrors/me/mediasoup-client如果你正在开发 WebRTC 实时音视频应用那么 mediasoup-client Transport 是无论如何都绕不开的核心概念。作为 mediasoup 官方浏览器端 JavaScript 库mediasoup-client 通过sendTransport与recvTransport两条通道分别完成媒体上行推送与下行接收理解它们的分工与协作方式是搭建稳定、可扩展的 SFU 音视频通话系统的第一步。本指南将从零开始带你彻底搞懂 Transport 的原理、创建流程与实战要点。一、什么是 mediasoup-client TransportTransport 的本质一条端到端的媒体通道在 mediasoup 架构中服务端mediasoup server为每个参与者创建一个名为Transport的逻辑实体它内部封装了一条 WebRTC 连接RTCPeerConnection所需的 ICE 与 DTLS 参数。而 mediasoup-client 的作用就是在浏览器端复刻出与服务端一一对应的 Transport 实例。客户端 Transport 的核心代码位于 src/Transport.ts其类定义中有一个关键字段direction: send | recv它决定了这条通道的用途方向创建方法核心用途核心 APIsenddevice.createSendTransport()上行推送本地音视频produce()、produceData()recvdevice.createRecvTransport()下行拉取远端音视频consume()、consumeData()客户端 Transport 的三大核心参数创建 Transport 时必须传入来自服务端的四件套参数缺一不可对应 src/Device.ts 中的类型校验逻辑id服务端 Transport 的唯一标识iceParametersICE 用户名片段与密码iceCandidatesICE 候选者列表dtlsParametersDTLS 指纹与角色这些参数由服务端通过信令WebSocket 等下发客户端拿到后原样传入即可。二、sendTransport 实战如何发布本地音视频第一步创建 sendTransport 的正确姿势sendTransport 负责把本地画面和声音推给远端典型创建流程如下const sendTransport device.createSendTransport({ id, iceParameters, iceCandidates, dtlsParameters, sctpParameters, // 如需 DataChannel 传数据则必须提供 });创建之后必须立刻注册connect事件监听否则后续调用produce()会直接抛错Transport 内部会在 src/Transport.ts 的produce()方法中检查监听器是否存在。第二步connect 事件——打通 DTLS 握手connect事件是整个流程中最容易踩坑的一环。当浏览器需要建立媒体连接时会触发该事件你需要把本地生成的dtlsParameters通过信令发给服务端sendTransport.on(connect, async ({ dtlsParameters }, callback, errback) { try { await signaling.request(transport-connect, { transportId: sendTransport.id, dtlsParameters, }); callback(); // 服务端处理成功通知 Transport 继续 } catch (error) { errback(error); // 失败则回传错误 } });第三步produce 事件与 produce() 的完整配合produce()调用后Transport 会先在本地创建 RTP Sender然后触发produce事件把协商好的rtpParameters交给你发往服务端sendTransport.on(produce, async ({ kind, rtpParameters, appData }, callback, errback) { try { const { id } await signaling.request(produce, { transportId: sendTransport.id, kind, rtpParameters, appData, }); callback({ id }); // 把服务端返回的 producer id 传回 } catch (error) { errback(error); } }); // 推送摄像头画面 const stream await navigator.mediaDevices.getUserMedia({ video: true }); const producer await sendTransport.produce({ track: stream.getVideoTracks()[0] });关键点produce事件的callback({ id })必须传回服务端生成的 producer idTransport 会用它在本地创建 Producer 实例见 src/Transport.ts 的produce()实现。第四步DataChannel 数据通道produceData需要传输二进制消息或低延迟数据时可以在 sendTransport 上创建 DataProducerconst dataProducer await sendTransport.produceData({ ordered: true, label: chat });此时同样需要监听producedata事件把sctpStreamParameters上报给服务端换取 id。三、recvTransport 实战如何接收远端音视频创建 recvTransport 的差异点recvTransport 与 sendTransport 的创建参数完全一致唯一区别是方向const recvTransport device.createRecvTransport({ id, iceParameters, iceCandidates, dtlsParameters, sctpParameters, }); recvTransport.on(connect, async ({ dtlsParameters }, callback, errback) { // 同样通过信令完成 DTLS 协商 });consume() 一键拉流订阅远端 Producer当远端有新的 Producer 加入时服务端会通过信令通知你此时调用consume()即可在 recvTransport 上创建 Consumerconst consumer await recvTransport.consume({ id: consumerId, // 服务端下发的 consumer id producerId, // 对应的 producer id kind: video, // audio 或 video rtpParameters, // 服务端下发的接收参数 });注意consume()返回的 Consumer 默认是paused状态需要调用consumer.resume()才会真正开始接收媒体流。拿到consumer.track后把它addTrack到video元素即可播放画面。consumeData()接收数据通道对应 sendTransport 的produceData()recvTransport 侧使用consumeData()订阅 DataConsumer实现聊天消息、文件分片等下行数据接收。四、Transport 事件监听清单与连接状态管理无论是 sendTransport 还是 recvTransport都共享同一套事件体系定义于 src/Transport.ts 的TransportEvents事件触发时机实战建议connect需要建立 DTLS 连接时必监听转发 dtlsParametersproduce/producedata创建 Producer 时sendTransport 必监听connectionstatechange连接状态变化用于 UI 显示与断线重连icegatheringstatechangeICE 收集状态变化调试网络问题利器icecandidateerrorICE 候选者出错排查 NAT/防火墙问题监听connectionstatechange是提升用户体验的关键状态机依次为new → connecting → connected → failed/disconnected/closed当出现disconnected时可调用transport.restartIce()触发 ICE 重启实现网络恢复。五、Transport 常用方法速查表restartIce()传入服务端新的iceParameters完成 ICE 重启断线重连必备updateIceServers()动态更新 ICE 服务器如 TURN 凭证过期时刷新getStats()获取底层RTCPeerConnection的统计报告用于带宽监控close()关闭 Transport同时级联关闭其下所有 Producer/Consumer此外每个 Transport 都暴露了observer属性可以通过监听newproducer、newconsumer等事件实现旁观者模式这在调试和统计场景中非常有用。六、新手最容易踩的 5 个坑忘记监听connect事件produce()/consume()直接抛TypeError。produce回调未返回 idProducer 创建失败务必callback({ id })。Consumer 忘记resume()画面黑屏、无声因为默认是暂停状态。在device.load()之前创建 Transport会抛InvalidStateError(not loaded)。sendTransport 与 recvTransport 混用consume()只能用于 recvproduce()只能用于 send方向错误会抛UnsupportedError。七、总结一张图看懂双 Transport 协作一次完整的双向通话需要两个 Transport 并行工作sendTransport把自己的麦克风/摄像头通过produce()推给服务端recvTransport把对方的音视频通过consume()拉回来播放两者互不干扰、各自独立管理连接状态这正是 mediasoup 设计上收发分离的优雅之处。掌握了 sendTransport 与 recvTransport 的创建、事件处理与生命周期管理你就已经掌握了 mediasoup-client 最核心的 80% 能力。建议对照 src/Transport.ts 源码和 src/Device.ts 中的createSendTransport()/createRecvTransport()实现亲手跑通一遍信令流程很快就能写出属于自己的 WebRTC 音视频应用。【免费下载链接】mediasoup-clientmediasoup client side JavaScript library项目地址: https://gitcode.com/gh_mirrors/me/mediasoup-client创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考