diff --git a/README.md b/README.md index 483e0a0..248fd90 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ 面向32台终端的内网低延迟屏幕广播系统,支持网络投屏、硬件接口互通、一键自动化运维。 +本项目提供 **Python (PySide6)** 和 **Rust (egui)** 两个版本的投屏控制客户端。 + ## 需求说明 当前会议投屏需求涉及通过视频矩阵系统向32台终端设备进行同步投屏。具体模式可分为以下两类: @@ -18,6 +20,17 @@ 参考文档: +## 客户端版本对比 + +| 特性 | Python (PySide6) | Rust (egui) | +|------|------------------|-------------| +| **GUI 框架** | PySide6 (Qt) | egui (即时模式) | +| **编译方式** | PyInstaller | Cargo + GNU 工具链 | +| **文件大小** | ~50MB | ~4MB | +| **启动速度** | 较慢 | 快 | +| **依赖** | 需 Python 运行时 | 独立可执行文件 | +| **界面风格** | 原生 Windows 风格 | 自定义风格 | + ## 整体部署步骤(细化版) ### 步骤1:MediaMTX服务器端 @@ -48,13 +61,24 @@ ### 主播端:推送本机屏幕 -**方案A:使用push\_screen.py脚本** +**方案A:使用 Rust 客户端(推荐)** + +1. **下载预编译版本** + - 从 Releases 下载 `push_screen.exe` + - 或使用源码自行编译(见下方编译说明) + +2. **运行程序** + - 双击运行 `push_screen.exe` + - 点击「设置」按钮配置服务器IP和FFmpeg路径 + - 点击「开始全屏投屏」按钮开始推流 + +**方案B:使用 Python 客户端** - 双击运行 `push_screen.py` - 点击「一键全屏投屏」按钮 - 脚本会自动启动MediaMTX并开始推流 -**方案B:使用mss抓屏+FFmpeg推流** +**方案C:使用mss抓屏+FFmpeg推流** ```python import subprocess @@ -217,6 +241,166 @@ MediaMTX 会返回内置的 WebRTC 播放页面,浏览器会自动播放HDMI 所有32台终端均可通过浏览器访问上述地址观看视频会议内容。 +## Rust 客户端编译指南 + +### 环境准备 + +1. **安装 Rust** + - 下载地址:`https://rustup.rs/` + - 安装时选择 `x86_64-pc-windows-gnu` 目标 + +2. **安装 MinGW-w64**(GNU 工具链) + - 推荐通过 MSYS2 安装:`pacman -S mingw-w64-x86_64-toolchain` + - 或下载 winlibs MinGW-w64 + +3. **添加 Rust 目标** + ```bash + rustup target add x86_64-pc-windows-gnu + ``` + +### 项目结构 + +``` +push_screen_rust/ +├── Cargo.toml # 项目配置 +├── build.rs # 构建脚本(用于嵌入图标) +├── app.rc # Windows 资源文件 +├── vi.ico # 应用程序图标 +└── src/ + └── main.rs # 主程序 +``` + +### 依赖库对照(PySide6 vs Rust) + +| Python/PySide6 | Rust 等效库 | 用途 | +|----------------|-------------|------| +| PySide6 (Qt) | `eframe` + `egui` | GUI 框架 | +| `QThread` | `std::thread` + `mpsc` | 多线程 | +| `QTimer` | `std::time::Duration` + 线程休眠 | 定时器 | +| `socket` | `std::net::TcpStream` | 网络检测 | +| `subprocess` | `std::process::Command` | 进程管理 | +| `json` | `serde` + `serde_json` | JSON 序列化 | +| `logging` | `tracing` + `tracing-subscriber` | 日志记录 | +| `requests` | `reqwest` | HTTP 客户端 | + +### 编译参数对照(PyInstaller vs Cargo) + +| PyInstaller 参数 | Cargo/Rust 等效配置 | 说明 | +|------------------|---------------------|------| +| `--onefile` | `lto = true` + `strip = true` | 优化体积 | +| `--windowed` | `#![windows_subsystem = "windows"]` | 隐藏控制台 | +| `--icon=vi.ico` | `windres app.rc -O coff -o app.res` + 链接 | 嵌入图标 | +| `--noconsole` | `windows_subsystem` 属性 | 无控制台窗口 | + +### 编译步骤 + +1. **进入项目目录** + ```bash + cd push_screen_rust + ``` + +2. **编译资源文件(图标)** + ```bash + windres app.rc -O coff -o app.res + ``` + +3. **配置构建脚本**(`build.rs`) + ```rust + use std::env; + + fn main() { + let target = env::var("TARGET").unwrap(); + if target.contains("windows") { + println!("cargo:rustc-link-arg=app.res"); + } + println!("cargo:rerun-if-changed=app.rc"); + println!("cargo:rerun-if-changed=vi.ico"); + } + ``` + +4. **配置 Cargo.toml** + ```toml + [package] + name = "push_screen_rust" + version = "0.1.0" + edition = "2021" + build = "build.rs" + + [dependencies] + eframe = { version = "0.24", features = ["default"] } + egui = "0.24" + tokio = { version = "1", features = ["full"] } + serde = { version = "1.0", features = ["derive"] } + serde_json = "1.0" + reqwest = { version = "0.11", features = ["json"] } + tracing = "0.1" + tracing-subscriber = "0.3" + winapi = { version = "0.3", features = ["winuser", "windef", "wingdi", ...] } + + [profile.release] + opt-level = 3 + lto = true + # strip = true # 取消注释以进一步减小体积 + + [[bin]] + name = "push_screen" + path = "src/main.rs" + ``` + +5. **编译发布版本** + ```bash + cargo build --release --target x86_64-pc-windows-gnu + ``` + +6. **输出文件** + - 位置:`target/x86_64-pc-windows-gnu/release/push_screen.exe` + - 大小:约 4-5 MB + +### 关键代码说明 + +**隐藏控制台窗口** +```rust +#![windows_subsystem = "windows"] +``` + +**设置 UTF-8 编码(解决中文乱码)** +```rust +#[cfg(windows)] +extern "system" { + fn SetConsoleOutputCP(wCodePageID: u32) -> i32; + fn SetConsoleCP(wCodePageID: u32) -> i32; +} + +fn set_utf8_encoding() { + #[cfg(windows)] + unsafe { + SetConsoleOutputCP(65001); // UTF-8 + SetConsoleCP(65001); + } +} +``` + +**加载中文字体** +```rust +fn configure_fonts(ctx: &egui::Context) { + let mut fonts = egui::FontDefinitions::default(); + + // 从系统加载中文字体 + let font_paths = [ + r"C:\Windows\Fonts\msyh.ttc", // 微软雅黑 + r"C:\Windows\Fonts\simsun.ttc", // 宋体 + ]; + + for font_path in &font_paths { + if let Ok(font_data) = std::fs::read(font_path) { + // 加载字体... + } + } + + ctx.set_fonts(fonts); +} +``` + ## 测试方案 使用1台台式机模拟MediaMTX服务器,2台笔记本分别模拟信号源和观众,测试两种场景。 @@ -249,7 +433,7 @@ MediaMTX 会返回内置的 WebRTC 播放页面,浏览器会自动播放HDMI 确认控制台显示端口监听正常 2. **笔记本A启动推流** - - 运行 `push_screen.py` + - 运行 `push_screen.exe` (Rust) 或 `push_screen.py` (Python) - 或使用命令行推流: ```bat ffmpeg -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://192.168.1.100:8554/screen @@ -319,21 +503,57 @@ D:\ScreenCast │ └── mediamtx.exe ├── ffmpeg/ # FFmpeg解压目录 │ └── bin/ffmpeg.exe -├── push_screen.py # 投屏源推流脚本(一键采集) +├── push_screen_rust/ # Rust 客户端源码 +│ ├── Cargo.toml +│ ├── build.rs +│ ├── app.rc +│ ├── vi.ico +│ └── src/main.rs +├── push_screen.exe # Rust 编译后的可执行文件(推荐) +├── push_screen.py # Python 投屏源推流脚本 ├── auto_receive.py # 终端自动打开浏览器脚本 -└── manage_server.py # 运维总控脚本(启动/切换模式/停止) +└── manage_server.py # 运维总控脚本 ``` -## 核心Python脚本 +## 核心脚本说明 -### 脚本1:投屏源推流脚本(push\_screen.py) +### Rust 客户端(push_screen_rust) -功能:双击即可采集Win10屏幕,自动推流到MediaMTX,无需敲命令;支持「全屏/指定窗口」投屏,带可视化提示。 +**功能**:轻量级投屏控制客户端,单文件可执行,无需运行时依赖。 -### 脚本2:终端自动打开浏览器脚本(auto\_receive.py) +**特性**: +- 实时状态检测(FFmpeg、服务器、端口) +- 配置持久化(config.json) +- 一键开始/停止推流 +- 中文字体支持 +- 自定义应用程序图标 -功能:双击脚本自动打开Chrome浏览器(全屏),直接跳转到投屏/会议流页面;支持批量部署到32台终端,无需手动输入地址。 +**编译命令**: +```bash +cd push_screen_rust +windres app.rc -O coff -o app.res +cargo build --release --target x86_64-pc-windows-gnu +``` -### 脚本3:运维总控脚本(manage\_server.py) +### Python 客户端(push_screen.py) -功能:一站式运维(启动MediaMTX、切换两种模式、批量控制32台终端、停止所有服务),适合管理员操作。 +**功能**:基于 PySide6 的投屏控制界面,功能完善。 + +**特性**: +- 可视化配置界面 +- 实时状态指示器 +- 日志显示 +- 设置对话框 + +**运行命令**: +```bash +python push_screen.py +``` + +### 终端自动打开浏览器脚本(auto_receive.py) + +**功能**:双击脚本自动打开Chrome浏览器(全屏),直接跳转到投屏/会议流页面;支持批量部署到32台终端,无需手动输入地址。 + +### 运维总控脚本(manage_server.py) + +**功能**:一站式运维(启动MediaMTX、切换两种模式、批量控制32台终端、停止所有服务),适合管理员操作。