Electron
简介
远程控制是参会人在共享屏幕时,观看共享屏幕的其它参会人(控制端)通过发起远程控制,共享屏幕参会人(被控端)会收到请求控制的消息,同意控制后,发起者(控制端)就可以操作共享屏幕参会人(被控端)的电脑。
安装依赖
- 安装 @pano.video/robotjs
npm install @pano.video/robotjs
- 安装 node-gyp
npm install -g node-gyp
node-gyp rebuild
On macOS
- Python v3.6, v3.7, v3.8, or v3.9
- XCode Command Line Tools
On Windows
- Install Python v3.6, v3.7, v3.8, or v3.9
- Install Visual C++ Build Environment
- 配置 Python 环境变量
- 需要设置 allowRendererProcessReuse
import { app } from 'electron';
app.allowRendererProcessReuse = false;
- 使用下面命令给Electron重新编译Robotjs
11.x.x 版本使用透明window显示有Bug, 建议使用 Electron 10.x.x版本。
npm rebuild --runtime=electron --target=10.1.1 --disturl=https://atom.io/download/atom-shell --abi=64
target: Electron版本
abi : node-abi-version
控制端 (控制其它参会人电脑)
监听接收方共享resolution变化事件
import { RtcEngine } from '@pano.video/panortc-electron-sdk'; window.rtcEngine = new RtcEngine(); let captureRect = { x: 0, y: 0, width: 0, height: 0, }; window.rtcEngine.on( 'userScreenResolutionChanged', (userId, width, height) => { console.log( `ResolutionChanged, userId: ${userId}, width: ${width}, height: ${height}` ); if (controller.remoteUserId === userId) { captureRect = { x: 0, y: 0, width, height, }; if (controller) { // 设置共享区域 controller.setShareRect(captureRect); } } } );
发起远程控制请求 && 注册监听回调
if (!SessionManager.getInstance().isConnected) { console.log('信令连接正在初始化,请稍后重试'); return; } //移除之前的监听 removeObservers(); // 被远程控制的UserId const userId = '123'; // 初始化 RtcController let controller = new RtcController(userId); // 监听 远程控制回复 controller.once( RtcController.Events.onControlResponse, onControlResponse ); // 监听 远程控制被取消 controller.once( RtcController.Events.onControlCancelled, onControlCancelled ); // 监听 远程控制断开 controller.once( RtcController.Events.onConnectDisconnected, onConnectDisconnected ); // 发起远程控制请求 controller.requestControl(userId); console.log('远程控制请求已发起');
收到远程控制的回复 ( 同意 | 拒绝 | 长时间未响应)
onControlResponse = (result) => { const success = result === 0; let msg = ''; const userName = 'xxx'; switch (result) { case 0: msg = `您正在控制${userName}的屏幕`; break; case -16: msg = `${userName} 长时间没有响应你的请求控制,请稍后重试`; break; default: msg = '对方拒绝了你的远程控制请求'; break; } console.log(msg); if (success) { /* * TODO: 需要在共享屏幕上面添加一个div,用于控制远程桌面 * 大小和共享屏幕的div一致, zIndex 应大于 共享屏幕的div * ref 是 共享屏幕上面div 的应用 */ controller.startControl(ref); // // 设置共享区域 controller.setShareRect(captureRect); } else { // 重置控制状态 resetControlStatus(); } };
收到被控端取消远程控制的消息
onControlCancelled = () => { console.log('对方取消了远程控制'); // 重置控制状态 resetControlStatus(); };
收到远程控制断开的消息
onConnectDisconnected = () => { console.log('远程控制已断开...'); // 重置控制状态 resetControlStatus(); };
主动取消远程控制
cancelControl = () => { controller.cancelControl(userId); // 重置控制状态 resetControlStatus(); };
其它
// 移除监听 removeObservers = () => { controller.off( RtcController.Events.onControlResponse, onControlResponse ); controller.off( RtcController.Events.onControlCancelled, onControlCancelled ); controller.off( RtcController.Events.onConnectDisconnected, onConnectDisconnected ); }; // 重置控制状态 resetControlStatus = () => { removeObservers(); controller = undefined; };
被控端(共享屏幕的参会人)
注册监听远程控制连接的事件 && 抓屏区域变化事件
// 抓屏区域变化事件: let captureRect = { x: 0, y: 0, width: 0, height: 0, }; rtcEngine.on('screenCaptureRegionChanged', (x, y, width, height) => { console.log( `RegionChanged, x: ${x}, y: ${y}, width: ${width}, height: ${height}` ); captureRect = { x, y, width, height }; console.log('captureRec', captureRect); // 设置共享区域 remoteControl.setShareRect(captureRect); }); // 注册监听远程控制请求的事件 SessionManager.getInstance().on( SessionManager.Events.remoteControlConnected, onRemoteControlConnected );
远程控制连接建立回调
import robotjs from '@pano.video/robotjs'; // robotjs 用于操作鼠标和键盘 window.robotjs = robotjs; let remoteControl = undefined; // RtcController onRemoteControlConnected = (v) => { // 链接建立成功之后 removeObservers(); remoteControl = v; // v: RtcController // 设置 robotjs remoteControl.setRobot(window.robotjs); // 设置 抓屏区域 remoteControl.setShareRect(captureRect); // 监听 远程控制断开 remoteControl.on( RtcController.Events.onConnectDisconnected, onConnectDisconnected ); // 监听 远程控制请求 remoteControl.on( RtcController.Events.onControlRequest, showRequestModal ); // 监听 远程控制被取消 remoteControl.on( RtcController.Events.onControlCancelled, onControlCancelled ); // 监听 远程控制回复 remoteControl.on( RtcController.Events.onControlResponse, onControlResponse ); };
收到控制端取消远程控制的消息
onControlCancelled = () => { console.log('对方已取消远程控制'); // TODO Reset Status };
收到远程控制的回复 (长时间未响应请求)
onControlResponse = (result: number) => { // 长时间没有响应请求,Hide Comfirm 提示框 if (result === -16) { // TODO Reset Status } };
收到远程控制断开的消息
onConnectDisconnected = () => { // 关闭共享也会收到远程连接断开的消息,所以需要本地判断之前是否在远程控制 if (true /*判断是否正在被控制*/) { console.log('远程控制连接已断开'); // TODO Reset Status } };
收到远程控制请求的消息
showRequestModal = (msg /* msg : { from: string } */) => { // 获取到 发起请求的UserId const targetUserId = msg.from; // Show confirm console.log('收到远程控制请求的消息:'); const r = confirm("收到远程控制请求"); if (r === true) { // 接受远程控制请求 remoteControl.acceptControl(targetUserId); } else { // 拒绝远程控制请求 remoteControl.rejectControl(targetUserId); } };
取消远程控制
cancelRemoteControl = () => { remoteControl.remoteUserId && remoteControl.cancelControl(remoteControl.remoteUserId); };
在共享屏幕关闭的时候需要调用 Close
remoteControl.close()
注意事项
Mac 首次使用需要打开权限