Files

588 lines
13 KiB
Markdown
Raw Permalink Normal View History

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已内置安装
### 安装依赖
```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