网站上面的小图标怎么做的,网站上的图标用什么软件做的,福州网站平台建设公司,网络推广培训推荐介绍
WebRTC (Web Real-Time Communications) 是一个实时通讯技术#xff0c;也是实时音视频技术的标准和框架。简单来说WebRTC是一个集大成的实时音视频技术集#xff0c;包含了各种客户端api、音视频编/解码lib、流媒体传输协议、回声消除、安全传输等。对于开发者来说可以…介绍
WebRTC (Web Real-Time Communications) 是一个实时通讯技术也是实时音视频技术的标准和框架。简单来说WebRTC是一个集大成的实时音视频技术集包含了各种客户端api、音视频编/解码lib、流媒体传输协议、回声消除、安全传输等。对于开发者来说可以借助webrtc非常方便的实现低延时视频通话能力。目前大多主流的直播系统、会议系统基本都是基于WebRTC来实现。
三种架构
WebRTC针对不同场景以及性能考虑提供了三种架构Mesh架构、MCU、FSU。
Mesh架构
Mesh架构需要所有参与连接的peer建立与所有其他peer的媒体连接两两连接。该架构需要n-1个上下行以此带来的带宽消耗流量、编/解码消耗设备性能成线性增长。该架构只能适用3-4个人的小型会议场景。
MCU架构
所有参与连接的peer将本地媒体流推到远程媒体服务器由媒体服务器进行混流然后再推到所有连接的peer端。该架构的优点就是只需要1路上下行随着peer人数不断增加依然不会对用户造成带宽、手机性能影响。该架构将压力转嫁到服务端由专用媒体服务器来完成混流转推等功能。
SFU架构
相对于MCU来说SFU只做转发媒体服务器压力有限。与Mesh架构相比只需要n-1个下行1个上行减少了服务器压力。在大规模的场合该架构具有伸缩性。
点对点视频连接
根据上面我们对基本WebRTC有了最基本的认识下面就从点对点实际例子来从代码角度进一步了解其原理。
先从下图来看看使用MCU来实现点对点需要哪些东西 在介绍流程之前先简单介绍下上图中出现的名词代表什么意思
Peer通信双方设备。Signaling Server 信令服务器用于交互连接双方的信令数据SDP、ICE等以保证通信的对等连接建立。NAT处理私有网络和公共网络之间的地址转换问题因为大多数设置都处于内网中需要转换为公共网络才能进行外网访问STUN用于发现设备的公共地址通过NAT转换的公网地址辅助穿越NAT进行点对点连接。TURN在无法建立直接连接时提供数据中继确保通信的可靠性。对等连接异常时的兜底方案。SDP会话描述协议用于描述和协商媒体会话的协议它定义了会话的所有技术细节包括媒体格式、编解码器、网络地址等。ICE用于发现和选择最优网络路径的框架确保在各种网络环境下都能成功建立和维持连接。
代码实现
实现点对点连接主要是两点1、信令数据交互 2、对等连接建立 在代码中使用到了socket.io来将设备和信令服务器通信使用了simple-peer来建立对等连接由于该demo在本地运行所以没有使用STUN/TRUN服务器有兴趣的可以使用Chrome提供的公共服务器stun:stun.l.google.com:19302 主要步骤如下
1、和信令服务器建立连接,并获取自身的socketId作为唯一标识2、申请方将信令由simple-peer生成通过信令服务器到达接受方3、接受方接受将发起方的信令保存到对等连接peer中并且将自己的信令通过信令服务器给到发送方4、发送方将接受方的信令数据保存到对等连接peer中至此发送方-接受方对等连接建立完成5、在发送方和接受方监听peer的stream来获取视频流然后展示在页面
和信令服务器建立连接
新建一个server,js使用nodeexpress搭建的简易信令服务器用于交换双方信令。通过create-react-app来创建一个前端页面。
信令服务器代码如下
const express require(express);
const http require(http);
const cors require(cors);const app express();
const server http.createServer(app);
app.use(cors);
const io require(socket.io)(server, {cors: {origin: *,methods: [POST, GET],},
});server.listen(5001, () {console.log(listening on 5000 ...);
});io.on(connection, (socket) {// 分发socket idsocket.emit(offer, socket.id);// 发送发起方的信令数据别answersocket.on(callUser, (data) {io.to(data.answerId).emit(callUser, data);});// 发送接收放信令给申请方socket.on(answerSignalInfo, (data) {io.to(data.to).emit(answerSignalInfo, data);});socket.on(disconnect, () {socket.broadcast.emit(callEnded, socket);});
});// frontend
// 通过socket.io和服务器进行连接
const socket io(http://localhost:5001);// 获取自身的socket id
socket.on(offer, (offerId) {console.log(offer socket ID, offerId);setOfferId(offerId);getLocalStream(); // 获取本地视频流
});传递信令数据
// 通过simple-peer 交换信令数据 offer - 信令服务器 - answer
const peer new Peer({initiator: true, // 是否是发起方stream: localStream, // 传递的视频流trickle: false, // 点对点传输获取单个信号// 设置STUN服务器Chrome提供的公共服务器config: {iceServers: [{ urls: stun:stun.l.google.com:19302 }],},
});
peer.on(signal, (data: any) {socket.emit(callUser, {singleData: data, // 发送通话方的信令数据answerId: answerId, // 需要和谁通话from: offerId, // 谁申请通话});
});接收信令数据
接收方接收发起方的信令数据并保存到Peer中然后将自身的信令数据返回给发起方
const peer new Peer({initiator: false,stream: localStream,trickle: false,config: {iceServers: [{ urls: stun:stun.l.google.com:19302 }],},
});
peer.on(signal, (data) {socket.emit(answerSignalInfo, {answerSignalInfo: data,to: offerUserInfo?.id,from: offerId,});
});if (offerUserInfo?.singleData) {peer.signal(offerUserInfo.singleData);
}对等连接建立获取双方视频流
交互信令之后通过simple-peer成功建立对等连接监听stream视频流然后显示在页面上
// 监听通过对等连接传递的stream
peer.on(stream, (stream) {if (remoteVideoRef.current) {remoteVideoRef.current.srcObject stream;remoteVideoRef.current.play();}
});完整页面代码CSS样式文件省略
import React, { useCallback, useEffect, useRef, useState } from react;
import { io } from socket.io-client;
import Peer from simple-peer;
import ./App.css;const socket io(http://localhost:5001);type UserInfo {singleData: any;id: string;
};function App() {// 用于引用 DOM 元素const localVideoRef useRefHTMLVideoElement(null);const remoteVideoRef useRefHTMLVideoElement(null);// 用于管理状态const [localStream, setLocalStream] useStateMediaStream | undefined();const [offerId, setOfferId] useState();const [answerId, setAnswerId] useState();const [offerUserInfo, setOfferUserInfo] useStateUserInfo();// 获取本地视频流const getLocalStream useCallback(async () {try {const stream await navigator.mediaDevices.getUserMedia({video: {width: { ideal: 200 }, // 理想的宽度height: { ideal: 200 }, // 理想的高度},audio: false,});console.log(local media, stream);setLocalStream(stream);if (localVideoRef.current) {localVideoRef.current.srcObject stream;}} catch (error) {console.error(Error accessing media devices., error);}}, []);// 手动设置通话方idconst onChange useCallback((e: React.ChangeEventHTMLInputElement) {console.log(onChange call id, e);setAnswerId(e.target.value);}, []);// 获取信令牌服务器发送的socket idconst init useCallback(() {socket.on(offer, (offerId) {console.log(offer socket ID, offerId);setOfferId(offerId);getLocalStream(); // 获取本地视频流});// 监听信令服务器发送的通话申请方的信令牌数据socket.on(callUser, ({ singleData, answerId, from }) {console.log(${from}发起通话, from);setOfferUserInfo({singleData: singleData,id: from,});});}, [getLocalStream]);// 创建和发送 offerconst startCall useCallback(async () {// 通过simple-peer 交换信令数据 offer - 信令服务器 - answerconst peer new Peer({initiator: true,stream: localStream,trickle: false,// 设置STUN服务器Chrome提供的公共服务器config: {iceServers: [{ urls: stun:stun.l.google.com:19302 }],},});peer.on(signal, (data: any) {socket.emit(callUser, {singleData: data, // 发送通话方的信令数据answerId: answerId, // 需要和谁通话from: offerId, // 谁申请通话});});// 获取到接收方的信令数据socket.on(answerSignalInfo, (data) {console.log(${data.from}已经接受通话, data, peer);peer.signal(data.answerSignalInfo);});// 监听通过对等连接传递的streampeer.on(stream, (stream) {if (remoteVideoRef.current) {remoteVideoRef.current.srcObject stream;remoteVideoRef.current.play();}});// setPeer(peer);}, [answerId, localStream, offerId, remoteVideoRef]);const acceptCall useCallback(() {const peer new Peer({initiator: false,stream: localStream,trickle: false,config: {iceServers: [{ urls: stun:stun.l.google.com:19302 }],},});peer.on(signal, (data) {socket.emit(answerSignalInfo, {answerSignalInfo: data,to: offerUserInfo?.id,from: offerId,});});if (offerUserInfo?.singleData) {peer.signal(offerUserInfo.singleData);}// 监听通过对等连接传递的streampeer.on(stream, (stream) {if (remoteVideoRef.current) {remoteVideoRef.current.srcObject stream;remoteVideoRef.current.play();}});}, [localStream, offerUserInfo, offerId, remoteVideoRef]);useEffect(() {init();}, [init]);return (div classNameAppvideo autoPlay muted ref{localVideoRef} classNamevideo /video autoPlay muted ref{remoteVideoRef} classNamevideo /input value{answerId} onChange{onChange} placeholdercall id /button onClick{startCall}发起通话/buttonbutton onClick{acceptCall}同意通话/button/div);
}export default App;至此可以启动项目并本地浏览器打开两个tab即可体验点对点视频服务。
总结
点对点通信主要就是信令数据的交换知道通信双方具体的配置信息通信参数、IP地址等以保证对等连接的成功建立然后传递视频流在页面展示。 其中信令服务器仅用于对等连接前的信令交换不会进行数据传输。NAT是将设备内网地址转换为外网公共地址。STUN来获取设置的公网地址。TURN服务器是用于对等连接异常时的兜底方案可进行数据传输。