Files
XCDesktop/remote/README.md
2026-03-08 01:34:54 +08:00

588 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 远程屏幕监控系统
一个基于 Node.js 的实时远程屏幕监控和控制系统,支持鼠标和键盘的远程操作、剪贴板同步、文件传输等功能。
## 功能特点
- 🎥 **实时屏幕流** - 低延迟的屏幕视频流传输,使用 FFmpeg 进行 MPEG1 编码
- 🖱️ **鼠标控制** - 远程鼠标移动、点击和滚轮操作
- ⌨️ **键盘控制** - 远程键盘输入,支持特殊键和组合键
- 📋 **剪贴板同步** - 支持文本和图片的双向剪贴板同步
- **文件传输** - 支持大文件分块上传、下载和文件管理
- 🔒 **安全认证** - bcrypt 密码哈希 + JWT Token 认证
- 🌐 **内网穿透** - 集成 FRP 客户端,支持外网访问
- 📦 **Git 服务** - 可选集成 Gitea提供代码托管服务
- 📝 **日志系统** - 完整的运行日志记录
- ⚙️ **灵活配置** - 支持配置文件和环境变量配置
## 快速开始
### 环境要求
- Node.js >= 16.0.0
- Windows 操作系统(输入控制功能需要)
- FFmpeg已内置安装
### 安装依赖
```bash
npm install
```
### 启动服务
```bash
npm run dev
# 或
npm start
```
访问 http://localhost:3000 查看屏幕流。
## 配置
配置文件位于 `config/default.json`,可配置项包括:
```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>`
```bash
# 设置服务器端口
REMOTE_SERVER_PORT=8080
# 设置密码
REMOTE_SECURITY_PASSWORD=your_password
# 设置 JWT 密钥
JWT_SECRET=your_jwt_secret
```
## API 接口
### 认证接口
#### 登录
```bash
POST /login
Content-Type: application/json
{
"password": "your_password"
}
```
响应:设置 `auth` Cookie 并重定向到首页。
#### API 登录
```bash
POST /api/auth/login
Content-Type: application/json
{
"password": "your_password"
}
```
响应:
```json
{
"success": true,
"token": "jwt_token_here"
}
```
#### 验证 Token
```bash
POST /api/auth/verify
Authorization: Bearer <token>
```
响应:
```json
{
"success": true,
"valid": true,
"userId": "default-user"
}
```
### 鼠标控制
```bash
POST /api/input/mouse/move
Content-Type: application/json
{
"x": 100,
"y": 200
}
```
```bash
POST /api/input/mouse/down
Content-Type: application/json
{
"button": "left" # "left", "right" 或 "middle"
}
```
```bash
POST /api/input/mouse/up
Content-Type: application/json
{
"button": "left"
}
```
```bash
POST /api/input/mouse/click
Content-Type: application/json
{
"button": "left"
}
```
```bash
POST /api/input/mouse/wheel
Content-Type: application/json
{
"delta": 120 # 正值向上滚动,负值向下滚动
}
```
### 键盘控制
```bash
POST /api/input/keyboard/down
Content-Type: application/json
{
"key": "enter"
}
```
```bash
POST /api/input/keyboard/up
Content-Type: application/json
{
"key": "enter"
}
```
```bash
POST /api/input/keyboard/press
Content-Type: application/json
{
"key": "enter"
}
```
```bash
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`
### 流媒体接口
```bash
GET /api/stream/info
```
响应:
```json
{
"success": true,
"stream": {
"status": "running",
"resolution": {
"width": 1920,
"height": 1080
},
"fps": 30,
"bitrate": "4000k",
"gop": 10,
"encoder": "mpeg1video"
}
}
```
```bash
POST /api/stream/start
```
```bash
POST /api/stream/stop
```
### 文件传输接口
```bash
GET /api/files
```
响应:
```json
{
"files": [
{
"name": "example.txt",
"size": 1024,
"modified": "2026-03-05T10:00:00.000Z",
"type": ".txt"
}
]
}
```
```bash
GET /api/files/browse?path=relative/path
```
响应:
```json
{
"items": [
{
"name": "folder",
"isDirectory": true,
"size": 0,
"modified": "2026-03-05T10:00:00.000Z",
"type": "directory"
}
],
"currentPath": "relative/path",
"parentPath": ""
}
```
```bash
POST /api/files/upload/start
Content-Type: application/json
{
"filename": "large_file.zip",
"totalChunks": 10,
"fileSize": 50000000
}
```
响应:
```json
{
"fileId": "abc123",
"chunkSize": 5242880,
"message": "Upload session started"
}
```
```bash
POST /api/files/upload/chunk
Content-Type: multipart/form-data
fileId: abc123
chunkIndex: 0
chunk: <binary data>
```
```bash
POST /api/files/upload/merge
Content-Type: application/json
{
"fileId": "abc123",
"totalChunks": 10,
"filename": "large_file.zip"
}
```
```bash
GET /api/files/:filename
```
支持 Range 请求头进行断点续传。
```bash
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
```
## 构建与部署
### 开发环境
```bash
npm run dev
```
### 生产环境打包
使用 pkg 打包为可执行文件:
```bash
npm run build
```
打包后的文件位于 `dist/` 目录:
- `remote-screen-monitor.exe` - 主程序
- `public/` - 前端静态文件
- `config/` - 配置文件
- `frp/` - FRP 客户端
- `ffmpeg.exe` - FFmpeg 编码器
### Windows 服务安装
使用 NSSM 将应用安装为 Windows 服务:
```powershell
# 安装服务
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使用指南](docs/指南/NSSM使用指南.md)。
## 安全注意事项
⚠️ **重要提示**
- 在公共网络上使用时,务必设置密码保护
- 建议使用 HTTPS/WSS通过反向代理如 Nginx
- 不要使用 root/Administrator 权限运行此服务
- 定期更换密码和 JWT 密钥
### 密码安全
系统支持 bcrypt 密码哈希。使用迁移脚本生成安全的密码哈希:
```bash
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