网站响应式首页模板,如何判断网站seo做的好坏,做网站单页视频,安徽网WebRTC 基础
目录
什么是 WebRTCWebRTC 的基本概念WebRTC 的基本流程 连接建立流程图 WebRTC 的基本对象 RTCPeerConnectionRTCSessionDescriptionRTCIceCandidate WebRTC API 详解 RTCPeerConnection API媒体流 API 详细的代码示例 基本连接示例完整的 WebRTC 实现示例 总结…WebRTC 基础
目录
什么是 WebRTCWebRTC 的基本概念WebRTC 的基本流程 连接建立流程图 WebRTC 的基本对象 RTCPeerConnectionRTCSessionDescriptionRTCIceCandidate WebRTC API 详解 RTCPeerConnection API媒体流 API 详细的代码示例 基本连接示例完整的 WebRTC 实现示例 总结 什么是 WebRTC
WebRTCWeb Real-Time Communication是一项技术它使浏览器和移动应用程序能够通过简单的 API 直接进行点对点Peer-to-PeerP2P的音频、视频和数据传输而无需借助中间服务器。WebRTC 主要用于以下场景
视频通话在浏览器之间建立实时的视频聊天功能。音频通话支持高质量的语音通话。数据传输用于传输任意数据如文件、消息等。实时协作在多个客户端之间同步文档、白板等应用。
WebRTC 具有以下几个关键特点
实时性提供低延迟的音视频通信适用于需要即时反馈的场景。跨平台支持在不同设备和浏览器间进行通信广泛适用于桌面和移动端。安全性通过 SRTPSecure Real-time Transport Protocol对传输的数据进行加密确保通信的安全性。开源性WebRTC 是一个开源项目开发者可以自由使用和修改。 WebRTC 的基本概念
在深入了解 WebRTC 的使用之前理解以下几个关键概念至关重要
1. 媒体流MediaStream
媒体流表示音频或视频流是由多个媒体轨道MediaTrack组成的。每个轨道可以是音频轨道或视频轨道。WebRTC 通过 getUserMedia() API 获取媒体流并将其传输给对等端。
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream {// 使用获取到的媒体流}).catch(error {console.error(Error accessing media devices., error);});关于媒体流可以参考MediaStream 的媒体流对象 (stream) 和流媒体轨道 (track) 详解
2. 信令Signaling
信令是指在两个对等端之间交换元数据的过程。元数据包括
SDPSession Description Protocol描述会话的格式信息如媒体类型、编解码器、网络参数等。ICE 候选ICE Candidates用于 P2P 连接的网络候选信息。
WebRTC 并不规定如何实现信令通常由开发者通过 WebSocket、XHR 或其他协议来完成。完成信令交换相关操作的服务称作信令服务器
3. 会话描述协议SDP
SDP 是一种文本格式用于描述多媒体通信会话。它包含有关媒体格式、编解码器、带宽、网络等信息。SDP 是 WebRTC 连接建立过程中的关键要素之一。
4. ICEInteractive Connectivity Establishment
ICE 是一个用于帮助 P2P 连接在不同网络环境下建立的框架。ICE 会尝试使用各种网络候选(candidate)包括本地、STUN 和 TURN 服务器提供的候选以确保 P2P 连接的建立。
STUNSession Traversal Utilities for NAT帮助客户端发现其外部网络地址。TURNTraversal Using Relays around NAT用于在 P2P 连接无法直接建立时通过中继服务器转发流量。
上面的过程强烈建议参考这位作者的文章
一文详解 WebRTC 基础
5. 数据通道DataChannel
数据通道 是 WebRTC 提供的一种机制用于在对等端之间传输任意数据如文本、文件等。它通过 RTCDataChannel 对象来创建具有低延迟和高吞吐量的特点。
const dataChannel pc.createDataChannel(myDataChannel);// 监听消息接收事件
dataChannel.onmessage (event) {console.log(Received Message:, event.data);
};// 发送消息
dataChannel.send(Hello, WebRTC!);WebRTC 的基本流程
WebRTC 的连接建立过程分为以下几个步骤
1. 获取本地媒体流
使用 getUserMedia() API 获取本地的音频和视频流并将其添加到 RTCPeerConnection 中。
2. 创建 RTCPeerConnection 对象
实例化 RTCPeerConnection 对象并设置 ICE 服务器配置。RTCPeerConnection 是 WebRTC 的核心对象用于管理和控制 P2P 连接。
3. 创建 Offer 并设置本地描述
调用 createOffer() 创建一个会话描述SDP并使用 setLocalDescription() 将其设置为本地描述。
4. 通过信令通道发送 Offer
将生成的 SDP 通过信令通道发送给远端。
5. 远端接收 Offer 并生成 Answer
远端使用 setRemoteDescription() 接收 SDP并调用 createAnswer() 生成一个 Answer然后通过信令通道发送回给本地。
6. 本地接收 Answer 并设置远程描述
本地使用 setRemoteDescription() 接收远端的 Answer并将其设置为远程描述。
7. 交换 ICE 候选
通过 onicecandidate 事件监听 ICE 候选的生成并通过信令通道交换候选信息确保 P2P 连接的建立。
8. 连接建立并开始传输数据
当双方都交换完 SDP 和 ICE 候选后P2P 连接建立可以开始音视频和数据的传输。
连接建立流程图 #mermaid-svg-MVIa2sSazDRVuKar {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MVIa2sSazDRVuKar .error-icon{fill:#552222;}#mermaid-svg-MVIa2sSazDRVuKar .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MVIa2sSazDRVuKar .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-MVIa2sSazDRVuKar .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MVIa2sSazDRVuKar .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MVIa2sSazDRVuKar .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MVIa2sSazDRVuKar .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MVIa2sSazDRVuKar .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MVIa2sSazDRVuKar .marker.cross{stroke:#333333;}#mermaid-svg-MVIa2sSazDRVuKar svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MVIa2sSazDRVuKar .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MVIa2sSazDRVuKar .cluster-label text{fill:#333;}#mermaid-svg-MVIa2sSazDRVuKar .cluster-label span{color:#333;}#mermaid-svg-MVIa2sSazDRVuKar .label text,#mermaid-svg-MVIa2sSazDRVuKar span{fill:#333;color:#333;}#mermaid-svg-MVIa2sSazDRVuKar .node rect,#mermaid-svg-MVIa2sSazDRVuKar .node circle,#mermaid-svg-MVIa2sSazDRVuKar .node ellipse,#mermaid-svg-MVIa2sSazDRVuKar .node polygon,#mermaid-svg-MVIa2sSazDRVuKar .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MVIa2sSazDRVuKar .node .label{text-align:center;}#mermaid-svg-MVIa2sSazDRVuKar .node.clickable{cursor:pointer;}#mermaid-svg-MVIa2sSazDRVuKar .arrowheadPath{fill:#333333;}#mermaid-svg-MVIa2sSazDRVuKar .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MVIa2sSazDRVuKar .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MVIa2sSazDRVuKar .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-MVIa2sSazDRVuKar .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-MVIa2sSazDRVuKar .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MVIa2sSazDRVuKar .cluster text{fill:#333;}#mermaid-svg-MVIa2sSazDRVuKar .cluster span{color:#333;}#mermaid-svg-MVIa2sSazDRVuKar div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MVIa2sSazDRVuKar :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 获取本地媒体流 创建 RTCPeerConnection 创建 Offer 并设置本地描述 通过信令通道发送 Offer 远端接收 Offer 并生成 Answer 本地接收 Answer 并设置远程描述 交换 ICE 候选 连接建立并开始传输数据 信令交换流程图 #mermaid-svg-H1fruSSJV9h8FFHl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-H1fruSSJV9h8FFHl .error-icon{fill:#552222;}#mermaid-svg-H1fruSSJV9h8FFHl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H1fruSSJV9h8FFHl .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-H1fruSSJV9h8FFHl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H1fruSSJV9h8FFHl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H1fruSSJV9h8FFHl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H1fruSSJV9h8FFHl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H1fruSSJV9h8FFHl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H1fruSSJV9h8FFHl .marker.cross{stroke:#333333;}#mermaid-svg-H1fruSSJV9h8FFHl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H1fruSSJV9h8FFHl .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-H1fruSSJV9h8FFHl text.actortspan{fill:black;stroke:none;}#mermaid-svg-H1fruSSJV9h8FFHl .actor-line{stroke:grey;}#mermaid-svg-H1fruSSJV9h8FFHl .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-H1fruSSJV9h8FFHl .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-H1fruSSJV9h8FFHl #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-H1fruSSJV9h8FFHl .sequenceNumber{fill:white;}#mermaid-svg-H1fruSSJV9h8FFHl #sequencenumber{fill:#333;}#mermaid-svg-H1fruSSJV9h8FFHl #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-H1fruSSJV9h8FFHl .messageText{fill:#333;stroke:#333;}#mermaid-svg-H1fruSSJV9h8FFHl .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-H1fruSSJV9h8FFHl .labelText,#mermaid-svg-H1fruSSJV9h8FFHl .labelTexttspan{fill:black;stroke:none;}#mermaid-svg-H1fruSSJV9h8FFHl .loopText,#mermaid-svg-H1fruSSJV9h8FFHl .loopTexttspan{fill:black;stroke:none;}#mermaid-svg-H1fruSSJV9h8FFHl .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-H1fruSSJV9h8FFHl .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-H1fruSSJV9h8FFHl .noteText,#mermaid-svg-H1fruSSJV9h8FFHl .noteTexttspan{fill:black;stroke:none;}#mermaid-svg-H1fruSSJV9h8FFHl .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-H1fruSSJV9h8FFHl .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-H1fruSSJV9h8FFHl .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-H1fruSSJV9h8FFHl .actorPopupMenu{position:absolute;}#mermaid-svg-H1fruSSJV9h8FFHl .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-H1fruSSJV9h8FFHl .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-H1fruSSJV9h8FFHl .actor-man circle,#mermaid-svg-H1fruSSJV9h8FFHl line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-H1fruSSJV9h8FFHl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Offerer Signaling Server Answerer Send SDP Offer Forward SDP Offer Send SDP Answer Forward SDP Answer Set Remote Description Set Local Description Offerer Signaling Server Answerer WebRTC 的基本对象
RTCPeerConnection
可参考RTCPeerConnection API 详细介绍含RTCDataChannel
RTCPeerConnection 是 WebRTC 的核心对象用于管理 P2P 连接。它提供了以下主要功能
创建和维护 P2P 连接。处理 ICE 候选。发送和接收媒体流。
构造函数
const pc new RTCPeerConnection(configuration);configuration包含 ICE 服务器配置的对象。可以设置 STUN 和 TURN 服务器。 iceServers: 一个包含 STUN 和 TURN 服务器地址的数组例如const configuration {iceServers: [{ urls: stun:stun.l.google.com:19302 },{ urls: turn:your-turn-server.com, username: user, credential: pass }]
};主要方法和属性
createOffer(options)创建一个 SDP Offer用于发起连接。 options: 可选参数用于指定创建 Offer 的约束条件如是否仅包含视频轨道等。 createAnswer(options)创建一个 SDP Answer用于回应对方的 Offer。 options: 可选参数用于指定创建 Answer 的约束条件。 setLocalDescription(description)设置本地 SDP 描述。 description: 一个 RTCSessionDescription 对象通常是由 createOffer 或 createAnswer 方法生成的。 setRemoteDescription(description)设置远程 SDP 描述。 description: 一个 RTCSessionDescription 对象表示远端的 SDP 描述。 addIceCandidate(candidate)向连接中添加一个 ICE 候选。 candidate: 一个 RTCIceCandidate 对象表示新的 ICE 候选。
事件处理 onicecandidate当新的 ICE 候选生成时触发用于向远端发送 ICE 候选。 pc.onicecandidate (event) {if (event.candidate) {// 发送候选信息给远端}
};ontrack当新的媒体轨道音频或视频添加到连接时触发。 pc.ontrack (event) {const remoteStream event.streams[0];// 将远程媒体流添加到视频元素
};ondatachannel当远程对等端创建一个数据通道时触发。 pc.ondatachannel (event) {const receiveChannel event.channel;receiveChannel.onmessage (e) {console.log(Data Channel Message:, e.data);};
};RTCSessionDescription
RTCSessionDescription 对象用于表示 WebRTC 连接的 SDP 信息。它包含连接的媒体类型、编解码器和网络配置等信息。
构造函数
const description new RTCSessionDescription({ type, sdp });type描述的类型可以是 offer、answer 或 rollback。sdp包含 SDP 的字符串。
示例
const offer await pc.createOffer();
await pc.setLocalDescription(offer);const description new RTCSessionDescription({ type: offer, sdp: offer.sdp });RTCIceCandidate
RTCIceCandidate 对象表示 WebRTC 的 ICE 候选信息。它用于描述潜在的 P2P 连接路径。
构造函数
const candidate new RTCIceCandidate({ candidate, sdpMid, sdpMLineIndex });candidate表示候选的网络地址。sdpMid与候选相关的媒体流标识符。sdpMLineIndex与候选相关的媒体流索引。
示例
pc.addIceCandidate(new RTCIceCandidate(candidate));示例
const configuration { iceServers: [{ urls: stun:stun.l.google.com:19302 }] };
const pc new RTCPeerConnection(configuration);// 添加媒体轨道
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream {stream.getTracks().forEach(track pc.addTrack(track, stream));});// 处理 ICE 候选
pc.onicecandidate (event) {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack (event) {const remoteStream event.streams[0];document.querySelector(#remoteVideo).srcObject remoteStream;
};// 创建数据通道
const dataChannel pc.createDataChannel(chat);dataChannel.onmessage (event) {console.log(Received Message:, event.data);
};pc.createOffer().then(offer {return pc.setLocalDescription(offer);
}).then(() {// 发送 offer 到远端
}).catch(console.error);详细的代码示例
基本连接示例
以下是一个简单的 WebRTC 连接示例展示了如何建立一个基本的音视频连接。
// 创建 RTCPeerConnection 对象
const configuration { iceServers: [{ urls: stun:stun.l.google.com:19302 }] };
const pc new RTCPeerConnection(configuration);// 获取本地媒体流
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream {document.querySelector(#localVideo).srcObject stream;stream.getTracks().forEach(track pc.addTrack(track, stream));});// 处理 ICE 候选
pc.onicecandidate (event) {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack (event) {const remoteStream event.streams[0];document.querySelector(#remoteVideo).srcObject remoteStream;
};// 通过信令通道发送和接收 Offer/Answer
pc.createOffer().then(offer {return pc.setLocalDescription(offer);
}).then(() {// 发送 offer 到远端
}).catch(console.error);// 处理远端的 Answer
// pc.setRemoteDescription(new RTCSessionDescription(answer));完整的 WebRTC 实现示例
以下是一个更复杂的完整 WebRTC 示例涵盖了音视频连接、数据通道和错误处理。
const configuration { iceServers: [{ urls: stun:stun.l.google.com:19302 }] };
const pc new RTCPeerConnection(configuration);// 获取本地媒体流
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream {document.querySelector(#localVideo).srcObject stream;stream.getTracks().forEach(track pc.addTrack(track, stream));}).catch(error {console.error(Error accessing media devices., error);});// 处理 ICE 候选
pc.onicecandidate (event) {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack (event) {const remoteStream event.streams[0];document.querySelector(#remoteVideo).srcObject remoteStream;
};// 创建数据通道
const dataChannel pc.createDataChannel(chat);
dataChannel.onopen () console.log(Data channel is open);
dataChannel.onmessage (event) console.log(Received message:, event.data);
dataChannel.onclose () console.log(Data channel is closed);// 创建 Offer 并设置本地描述
pc.createOffer().then(offer {return pc.setLocalDescription(offer);
}).then(() {// 通过信令通道发送 Offer
}).catch(console.error);// 处理远端的 Answer
// pc.setRemoteDescription(new RTCSessionDescription(answer)).catch(console.error);// 添加错误处理
pc.oniceconnectionstatechange () {if (pc.iceConnectionState failed) {console.error(ICE connection failed.);}
};总结
WebRTC 为实时通信提供了强大的功能能够在不依赖中介服务器的情况下建立跨平台的 P2P 连接。本文介绍了WebRTC 基本概念和相关流程下文将主要介绍 WebRTC 创建端与接收端的代码实现。 参考来源
一文详解 WebRTC 基础