把手机浏览器变成电脑的远程输入终端,语音、触控板、常用按键都行
| 🗣️ 语音输入 豆包输入法 → 电脑 |
🖱️ 触控板 手机当鼠标用 |
📋 历史记录 点击回填,自动滚回顶部 |
![]() |
![]() |
![]() |
电脑上写长文,打字慢;手机上豆包输入法的语音识别很准,但识别出来的字还在手机上。躺在床上 AI Coding 切候选项,还得爬起来摸键盘。
Remote Input Board 把这件事倒过来:电脑上跑一个小服务,手机浏览器打开网页,手机就变成电脑的远程输入终端。语音输入直接打到光标位置,触控板当鼠标用,ESC、发送、清空这些常用按键也能在手机上操作。
项目地址:https://github.com/createskyblue/remote-input-board
能做什么
文本输入
- 🗣️ 手机用豆包输入法语音识别,电脑光标处直接出字
- ⚡ 停止输入后自动发送,延时可调
- ↩️ 有内容按回车立即发送,空内容按回车 = 电脑回车键
- ⌫ 输入框为空时按退格 = 电脑退格键
- 📝 最近 30 条发送历史,点一下回填到输入框,覆盖前会确认
- 🔢 累计发送字数统计,浏览器 localStorage 持久化
触控板
- 🖱️ 单指滑动 = 移动鼠标,单指单击 = 左键,双指单击 = 右键
- 📜 双指滑动 = 滚动(横放上下滚,竖放左右滚)
- ✊ 双击按住 = 拖拽,松开结束
- 🌐 鼠标移动和滚动走 WebSocket,比 HTTP 轮询延迟低得多
常用按键
- ⎋ ESC、清空、发送按钮放在输入框下方,AI Coding 退出状态、重发文本和清理输入都很顺手
关键行为
- 🧹 所有文字通过 Win32
SendInputUnicode 键盘事件逐字输入,不碰系统剪贴板,不会覆盖你复制的重要内容
怎么用
电脑端一行启动:
uv run python -m py_remote_input终端打印局域网地址,手机连同一个 Wi-Fi 打开即可。发送前在电脑上点一下目标输入位置,把光标放好。
改端口:
$env:PORT='3219'; uv run python -m py_remote_input打包成单个 exe(不需要 Python 环境):
.\.venv\Scripts\python.exe scripts\build_exe.py输出 dist\RemoteInputBoard.exe,双击即用。
发送过的文本都写进 logs/input-history.log,一行一条 JSON,崩溃也不丢。
架构
整个项目只有两个运行时通道:
| 通道 | 用途 | 协议 |
|---|---|---|
| HTTP API | 文本发送、按键、鼠标点击等离散操作 | HTTP POST JSON |
| WebSocket | 鼠标移动、滚动等高频连续操作 | WebSocket 文本帧 JSON |
鼠标移动如果走 HTTP,每次 pointermove 发一个 POST 请求,延迟和开销都很大。走 WebSocket 后,前端用 requestAnimationFrame 攒帧合并增量,后端收到直接调 SendInput,体感跟手。
核心模块:
py_remote_input/
__main__.py # 入口
server.py # HTTP + WebSocket 服务,ThreadingHTTPServer
web.py # HTTP 路由和请求分发
websocket.py # WebSocket 帧编码/解码(无第三方依赖)
typer.py # Win32 SendInput 封装:文本、按键、鼠标移动/点击/滚动
logger.py # 结构化日志(同时输出 stdout 和文件)
templates/
index.html # 单页前端(原生 JS,无框架)typer.py 是整个电脑端的核心。文字输入走 KEYEVENTF_UNICODE,每个 UTF-16 码元生成一对 keydown/keyup 事件;回车和退格映射到虚拟键码;鼠标移动、点击、滚动各自拼装 MOUSEINPUT 结构体,统一通过 SendInput 批量注入。
server.py 用标准库 ThreadingHTTPServer,不依赖 Flask 或任何 Web 框架。WebSocket 升级握手、帧解析、掩码处理全在 websocket.py 里手写实现,代码不到 80 行。
前端是单个 HTML 文件,所有状态(自动发送开关、延时、历史记录、累计字数)存在 localStorage,不依赖服务端 session。
触控板手势状态机
触控板的 tap / double-tap / drag 判定不依赖浏览器 click 事件,完全在 pointerdown/move/up 里处理:
- 单指按下:记录起始时间戳和位置,启动 tap 监测
- 移动超过阈值(8px):判定为滑动,取消 tap,开始移动鼠标
- 抬起且无移动且间隔 < 220ms:判定为 tap,区分单指(左键)和双指(右键)
- 快速双击(间隔 < 180ms):进入拖拽候选 — 第二次按下后如有移动则锁定拖拽(持续按下左键),无移动则触发双击
- 双指滑动:根据两指初始横纵关系判定滚动轴向,累积增量走
requestAnimationFrame批量发送
所有定时和状态管理都在前端完成,服务端只接收 mouseMove、mouseScroll、mouseClick、mouseButton 四种标准化消息。
小结
这个工具的出发点一直没变:把手机上更好的输入能力借给电脑用。语音输入是起点,触控板和常用按键是后来发现同样顺手加上的。代码量不大,但恰好覆盖了"不想碰键盘"的几个高频场景。
本文由 AI 辅助生成,可能存在错误或遗漏,请以实际资料和官方文档为准。


