Files
XCDesktop/remote
ssdfasd 788757b785 feat(remote): 新增文件传输专用端口配置
- 添加 fileTransferPort 字段到 RemoteDevice 类型
- 新增 frp 穿透配置: 3003 -> 8083
- 文件传输功能改用专用端口,避免与远程桌面端口共用
- 配置对话框新增文件传输端口设置
2026-03-10 00:09:01 +08:00
..
2026-03-08 01:34:54 +08:00
2026-03-09 20:08:46 +08:00
2026-03-08 01:34:54 +08:00
2026-03-08 01:34:54 +08:00
2026-03-08 01:34:54 +08:00
2026-03-08 01:34:54 +08:00
2026-03-08 01:34:54 +08:00
2026-03-08 01:34:54 +08:00

远程屏幕监控系统

一个基于 Node.js 的实时远程屏幕监控和控制系统,支持鼠标和键盘的远程操作、剪贴板同步、文件传输等功能。

功能特点

  • 🎥 实时屏幕流 - 低延迟的屏幕视频流传输,使用 FFmpeg 进行 MPEG1 编码
  • 🖱️ 鼠标控制 - 远程鼠标移动、点击和滚轮操作
  • ⌨️ 键盘控制 - 远程键盘输入,支持特殊键和组合键
  • 📋 剪贴板同步 - 支持文本和图片的双向剪贴板同步
  • 文件传输 - 支持大文件分块上传、下载和文件管理
  • 🔒 安全认证 - bcrypt 密码哈希 + JWT Token 认证
  • 🌐 内网穿透 - 集成 FRP 客户端,支持外网访问
  • 📦 Git 服务 - 可选集成 Gitea提供代码托管服务
  • 📝 日志系统 - 完整的运行日志记录
  • ⚙️ 灵活配置 - 支持配置文件和环境变量配置

快速开始

环境要求

  • Node.js >= 16.0.0
  • Windows 操作系统(输入控制功能需要)
  • FFmpeg已内置安装

安装依赖

npm install

启动服务

npm run dev
# 或
npm start

访问 http://localhost:3000 查看屏幕流。

配置

配置文件位于 config/default.json,可配置项包括:

{
  "server": {
    "port": 3000,
    "host": "0.0.0.0"
  },
  "stream": {
    "fps": 30,
    "bitrate": "4000k",
    "gop": 10,
    "preset": "ultrafast",
    "resolution": {
      "width": 1920,
      "height": 1080
    }
  },
  "input": {
    "mouseEnabled": true,
    "keyboardEnabled": true,
    "sensitivity": 1.0
  },
  "security": {
    "password": "",
    "tokenExpiry": 3600
  },
  "frp": {
    "enabled": true,
    "frpcPath": "./frp/frpc.exe",
    "configPath": "./frp/frpc.toml"
  },
  "gitea": {
    "enabled": true
  }
}

配置说明

配置项 说明 默认值
server.port 服务器端口 3000
server.host 服务器监听地址 0.0.0.0
stream.fps 视频帧率 30
stream.bitrate 视频码率 4000k
stream.gop GOP 大小(关键帧间隔) 10
stream.preset 编码预设 ultrafast
stream.resolution 视频分辨率 1920x1080
input.mouseEnabled 是否启用鼠标控制 true
input.keyboardEnabled 是否启用键盘控制 true
input.sensitivity 鼠标灵敏度 1.0
security.password 访问密码(空表示不需要密码) ""
security.tokenExpiry Token 有效期(秒) 3600
frp.enabled 是否启用 FRP 内网穿透 true
gitea.enabled 是否启用 Gitea 服务 true

环境变量配置

所有配置项都可以通过环境变量覆盖,格式为 REMOTE_<SECTION>_<KEY>

# 设置服务器端口
REMOTE_SERVER_PORT=8080

# 设置密码
REMOTE_SECURITY_PASSWORD=your_password

# 设置 JWT 密钥
JWT_SECRET=your_jwt_secret

API 接口

认证接口

登录

POST /login
Content-Type: application/json

{
  "password": "your_password"
}

响应:设置 auth Cookie 并重定向到首页。

API 登录

POST /api/auth/login
Content-Type: application/json

{
  "password": "your_password"
}

响应:

{
  "success": true,
  "token": "jwt_token_here"
}

验证 Token

POST /api/auth/verify
Authorization: Bearer <token>

响应:

{
  "success": true,
  "valid": true,
  "userId": "default-user"
}

鼠标控制

POST /api/input/mouse/move
Content-Type: application/json

{
  "x": 100,
  "y": 200
}
POST /api/input/mouse/down
Content-Type: application/json

{
  "button": "left"  # "left", "right" 或 "middle"
}
POST /api/input/mouse/up
Content-Type: application/json

{
  "button": "left"
}
POST /api/input/mouse/click
Content-Type: application/json

{
  "button": "left"
}
POST /api/input/mouse/wheel
Content-Type: application/json

{
  "delta": 120  # 正值向上滚动,负值向下滚动
}

键盘控制

POST /api/input/keyboard/down
Content-Type: application/json

{
  "key": "enter"
}
POST /api/input/keyboard/up
Content-Type: application/json

{
  "key": "enter"
}
POST /api/input/keyboard/press
Content-Type: application/json

{
  "key": "enter"
}
POST /api/input/keyboard/type
Content-Type: application/json

{
  "text": "Hello World"
}

支持的特殊键:enter, backspace, tab, escape, delete, home, end, pageup, pagedown, up, down, left, right, f1-f12, ctrl, alt, shift, win, space

流媒体接口

GET /api/stream/info

响应:

{
  "success": true,
  "stream": {
    "status": "running",
    "resolution": {
      "width": 1920,
      "height": 1080
    },
    "fps": 30,
    "bitrate": "4000k",
    "gop": 10,
    "encoder": "mpeg1video"
  }
}
POST /api/stream/start
POST /api/stream/stop

文件传输接口

GET /api/files

响应:

{
  "files": [
    {
      "name": "example.txt",
      "size": 1024,
      "modified": "2026-03-05T10:00:00.000Z",
      "type": ".txt"
    }
  ]
}
GET /api/files/browse?path=relative/path

响应:

{
  "items": [
    {
      "name": "folder",
      "isDirectory": true,
      "size": 0,
      "modified": "2026-03-05T10:00:00.000Z",
      "type": "directory"
    }
  ],
  "currentPath": "relative/path",
  "parentPath": ""
}
POST /api/files/upload/start
Content-Type: application/json

{
  "filename": "large_file.zip",
  "totalChunks": 10,
  "fileSize": 50000000
}

响应:

{
  "fileId": "abc123",
  "chunkSize": 5242880,
  "message": "Upload session started"
}
POST /api/files/upload/chunk
Content-Type: multipart/form-data

fileId: abc123
chunkIndex: 0
chunk: <binary data>
POST /api/files/upload/merge
Content-Type: application/json

{
  "fileId": "abc123",
  "totalChunks": 10,
  "filename": "large_file.zip"
}
GET /api/files/:filename

支持 Range 请求头进行断点续传。

DELETE /api/files/:filename

WebSocket 消息类型

连接地址:ws://localhost:3000/ws

客户端发送

类型 说明 数据
mouseMove 鼠标移动 { type: "mouseMove", x: 100, y: 200 }
mouseDown 鼠标按下 { type: "mouseDown", button: "left" }
mouseUp 鼠标释放 { type: "mouseUp", button: "left" }
mouseWheel 鼠标滚轮 { type: "mouseWheel", delta: 120 }
keyDown 键盘按下 { type: "keyDown", key: "enter" }
keyUp 键盘释放 { type: "keyUp", key: "enter" }
clipboardGet 获取剪贴板 { type: "clipboardGet" }
clipboardSet 设置剪贴板 { type: "clipboardSet", contentType: "text", data: "content" }

服务端发送

类型 说明 数据
screenInfo 屏幕信息 { type: "screenInfo", width: 1920, height: 1080 }
clipboardData 剪贴板数据 { type: "clipboardData", contentType: "text", data: "content", size: 100 }
clipboardResult 剪贴板操作结果 { type: "clipboardResult", success: true }
clipboardTooLarge 剪贴板内容过大 { type: "clipboardTooLarge", size: 1000000 }

项目结构

remote/
├── src/
│   ├── config/               # 配置管理
│   │   ├── index.js          # 配置加载器
│   │   └── schema.js         # 配置验证模式
│   ├── controllers/          # 控制器层
│   │   ├── AuthController.js # 认证控制器
│   │   ├── InputController.js# 输入控制器
│   │   └── StreamController.js# 流媒体控制器
│   ├── core/                 # 核心模块
│   │   ├── App.js            # 应用主类
│   │   ├── Container.js      # 依赖注入容器
│   │   ├── EventBus.js       # 事件总线
│   │   ├── ErrorHandler.js   # 错误处理器
│   │   └── events.js         # 事件类型定义
│   ├── middlewares/          # 中间件
│   │   ├── auth.js           # 认证中间件
│   │   ├── error.js          # 错误处理中间件
│   │   └── rateLimit.js      # 限流中间件
│   ├── routes/               # 路由层
│   │   ├── index.js          # 路由汇总
│   │   ├── auth.js           # 认证路由
│   │   ├── files.js          # 文件路由
│   │   ├── input.js          # 输入路由
│   │   └── stream.js         # 流媒体路由
│   ├── server/               # 服务器层
│   │   ├── Server.js         # HTTP 服务器
│   │   ├── WebSocketServer.js# WebSocket 服务器
│   │   ├── StreamBroadcaster.js# 流广播器
│   │   ├── InputHandler.js   # 输入处理器
│   │   └── messageTypes.js   # 消息类型定义
│   ├── services/             # 服务层
│   │   ├── auth/             # 认证服务
│   │   │   ├── AuthService.js
│   │   │   └── TokenManager.js
│   │   ├── clipboard/        # 剪贴板服务
│   │   │   └── ClipboardService.js
│   │   ├── file/             # 文件服务
│   │   │   └── FileService.js
│   │   ├── input/            # 输入服务
│   │   │   ├── InputService.js
│   │   │   └── PowerShellInput.js
│   │   ├── network/          # 网络服务
│   │   │   ├── FRPService.js
│   │   │   └── GiteaService.js
│   │   ├── stream/           # 流媒体服务
│   │   │   ├── FFmpegEncoder.js
│   │   │   ├── ScreenCapture.js
│   │   │   └── StreamService.js
│   │   └── index.js          # 服务汇总
│   ├── utils/                # 工具类
│   │   ├── config.js         # 配置工具
│   │   ├── logger.js         # 日志工具
│   │   └── paths.js          # 路径工具
│   └── index.js              # 应用入口
├── config/
│   └── default.json          # 默认配置
├── docs/                     # 文档目录
│   ├── 开发/                  # 开发文档
│   └── 指南/                  # 使用指南
├── frp/                      # FRP 内网穿透
│   ├── frpc.exe
│   ├── frpc.toml
│   └── frpc-runtime.toml
├── gitea/                    # Gitea Git 服务
├── logs/                     # 日志目录
│   ├── combined.log          # 所有日志
│   └── error.log             # 错误日志
├── public/                   # 前端静态文件
│   ├── css/
│   │   └── main.css
│   ├── js/
│   │   ├── app.js            # 应用入口
│   │   ├── file-panel.js     # 文件传输面板
│   │   ├── input.js          # 输入处理
│   │   ├── jsmpeg.min.js     # JSMpeg 播放器
│   │   ├── player.js         # 视频播放器
│   │   └── utils.js          # 工具函数
│   └── index.html
├── scripts/
│   └── migrate-password.js   # 密码迁移脚本
├── uploads/                  # 上传文件目录
├── .gitignore
├── package.json
└── README.md

构建与部署

开发环境

npm run dev

生产环境打包

使用 pkg 打包为可执行文件:

npm run build

打包后的文件位于 dist/ 目录:

  • remote-screen-monitor.exe - 主程序
  • public/ - 前端静态文件
  • config/ - 配置文件
  • frp/ - FRP 客户端
  • ffmpeg.exe - FFmpeg 编码器

Windows 服务安装

使用 NSSM 将应用安装为 Windows 服务:

# 安装服务
nssm install RemoteApp "C:\path\to\remote-screen-monitor.exe"

# 设置工作目录
nssm set RemoteApp AppDirectory "C:\path\to\app"

# 设置启动类型
nssm set RemoteApp Start SERVICE_AUTO_START

# 启动服务
nssm start RemoteApp

详细说明请参考 NSSM使用指南

安全注意事项

⚠️ 重要提示

  • 在公共网络上使用时,务必设置密码保护
  • 建议使用 HTTPS/WSS通过反向代理如 Nginx
  • 不要使用 root/Administrator 权限运行此服务
  • 定期更换密码和 JWT 密钥

密码安全

系统支持 bcrypt 密码哈希。使用迁移脚本生成安全的密码哈希:

node scripts/migrate-password.js

将生成的哈希值设置到环境变量 REMOTE_SECURITY_PASSWORD 中。

故障排除

鼠标/键盘控制不工作

确保以管理员权限运行Windows某些操作可能需要提升的权限。

视频流卡顿

  • 降低 FPS 或分辨率
  • 降低视频码率
  • 检查网络带宽

日志查看

日志文件位于 logs/ 目录:

  • logs/combined.log - 所有日志
  • logs/error.log - 错误日志

技术栈

  • 后端: Node.js, Express 5.x, ws (WebSocket), winston (日志)
  • 前端: HTML5 Canvas, JSMpeg 播放器
  • 视频编码: FFmpeg (mpeg1video)
  • 输入模拟: PowerShell + Windows API (user32.dll)
  • 认证: bcrypt, jsonwebtoken
  • 文件处理: multer, fs-extra
  • 内网穿透: FRP (Fast Reverse Proxy)
  • 打包: pkg

许可证

ISC