最近有一个功能需要在网页web端实现对另一个设备的控制,参考了网上的教程是用webrtc实现,梳理了整体的实现过程
最终效果
整体逻辑
主要分为三部分:web端(控制端)、中继服务端、被控端,各部分的工作内容如下
web端
- 建立
Websocket与服务端通信 - 建立
Webrct通道与被控端通信 - 远程桌面
视频流的渲染 - 反向控制(
键、鼠:按比例将数据下发)
被控端
- 建立
Websocket与服务端通信 - 建立
Webrct通道与控制端通信 - 设备屏幕截图、截屏压缩处理、将截取的图片转成流推送【屏幕截图、截屏压缩处理耗时处理】
- 解析和响应控制(键、鼠:按比例将数据解析后模拟鼠标事件)
中继服务端
它是在建立连接之前交换信息的任何一种通信渠道,
turn服务的搭建- 开发websocket服务、账号管理、消息转发
流程
整体功能流程
实现过程
主要梳理的是web前端部分的实现过程,分为4部分:
- 建立
Websocket与服务端通信 - 建立
Webrct通道与被控端通信 - 远程桌面
视频流的渲染 - 反向控制(
键、鼠:按比例将数据下发)
Websocket 与服务端通信
websocket的连接是为了后续建立p2p连接做的前置工作。websocket的通信比较简单,soket连接直接使用new WebSocket(地址)可以实例化sokcet对象,sokcet对象的回调函数有onopen/onerror/onclose/onmessage等,可以在对应的回调里执行相关操作
this.socket = new WebSocket(this.socketUrl)
this.socket.onopen = () => {}
this.socket.onerror = (error) => {}
this.socket.onclose = (error) => {}
this.socket.onmessage = (Message) => {}
Webrct 通道建立
Webrct 通道建立也就是我们常提到的p2p连接,第一步控制端和被控端都与中继服务建立了websoket连接后,可以借用中继服务交换Offer 和 Answer,成功建立p2p连接。对应的是流程图中的这部分
websocket连接成功后,中继服务器转发给控制端connected指令,控制端onmessage接收到指令connected后,控制端要做的事情有:
-
- 执行
初始化peer的操作
- 执行
-
创建数据通道
-
- 给中继服务
发送ready消息
- 给中继服务
this.socket.onmessage = (Message) => {
const obj = JSON.parse(Message.data)
const command = obj.command
let data = null
switch (command) {
case 'connected': // 链接成功
// 1. 初始化 peer
const PeerConnection =
window.RTCPeerConnection ||
window.mozRTCPeerConnection ||
window.webkitRTCPeerConnection
this.peer = new PeerConnection(SERVERS, PC_OPTIONS)
// 2. 创建数据通道
this.channel = this.peer.createDataChannel('msgdatachannel')
// 3. 发送ready消息
data = JSON.stringify({
'command': 'ready'
})
this.send(data)
break
default: {
console.log(Message.data)
}
}
}
中继服务收到ready后转发给被控端,被控端也进行初始化peerB的操作,初始化完成同样发送ready给中继服务,中继再转发给控制端,控制端就能在onmessage回调里接收到ready指令后,就能进行offer创建的操作,创建offer后,再把offer发送给中继服务
this.socket.onmessage = (Message) => {
const obj = JSON.parse(Message.data)
const command = obj.command
switch (command) {
case 'ready':
// 创建offer
this.peer.createOffer(
(desc) => {
this.peer.setLocalDescription(desc, () => {
const obj = JSON.stringify({
'command': 'offer',
'desc': desc
})
// 发送offer给中继服务
this.send(obj)
}
}
)
break
default: {
console.log(Message.data)
}
}
}
中继服务收到offer后转发给被控端,被控端创建answer,同样再通过中继服务转发给控制端,此时连接完成,会自动调用peer和peerB的onopen事件,后续就可以进行指令的发送和视频流的接收了。
远程桌面视频流的渲染
在peer.onaddstream可以监听到视频流,然后通过标签play即可
this.peer.onaddstream = (e) => {
try {
const vid2 = document.getElementById('remote-control')
vid2.srcObject = e.stream
vid2.onloadedmetadata = function() {
vid2.play()
}
} catch (ex) {
this.socket.close()
}
}
鼠标/键盘指令的发送
已经建立了p2p连接,并且在前面已经创建了数据通道,指令可以通过channel.send发送,常用指令定义参考如下
完整代码
参考文章
developer.mozilla.org/en-US/docs/…
原创文章,记录成长,也希望对你有帮助!喜欢请点赞哦~
作者:前端小小梦
主页:了解更多,点击个人主页