Spaces:
Sleeping
Sleeping
Antigravity Agent commited on
Commit ·
36bec3f
0
Parent(s):
🏛️ 架构重生:彻底切除 80MB 历史肿瘤,实现轻量化 14 号行星部署
Browse files- .gitignore +4 -0
- Dockerfile +9 -0
- HELP.md +33 -0
- LICENSE +11 -0
- README.md +11 -0
- Shensist_AirEye_Core.py +83 -0
- Shensist_File_Agent.py +62 -0
- Shensist_Kernel_Input.py +63 -0
- Shensist_Launcher.py +79 -0
- Shensist_MIDI_Listener.py +54 -0
- Shensist_MIDI_Master.py +38 -0
- Shensist_PT_Bridge.py +55 -0
- Shensist_System_Master.py +87 -0
- Shensist_V_MIDI.py +37 -0
- Shensist_WeChat_Control.py +76 -0
- Shensist_Web_Master.py +174 -0
- __pycache__/Shensist_PT_Bridge.cpython-313.pyc +0 -0
- __pycache__/Shensist_Web_Master.cpython-313.pyc +0 -0
- cmd.txt +0 -0
- index.html +69 -0
- logo_ts.webp +0 -0
- requirements.txt +3 -0
- scripts/check_perms.py +32 -0
- skills/复制/config.json +1 -0
- skills/粘贴/config.json +1 -0
- skills_map.json +10 -0
- test.txt +1 -0
- voice_agent.py +48 -0
.gitignore
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
models/
|
| 2 |
+
*.zip
|
| 3 |
+
__pycache__/
|
| 4 |
+
*.pyc
|
Dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.9
|
| 2 |
+
RUN useradd -m -u 1000 user
|
| 3 |
+
USER user
|
| 4 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 7 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 8 |
+
COPY --chown=user . /app
|
| 9 |
+
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "Shensist_Web_Master:app"]
|
HELP.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🏛️ 神思庭 (Shensist-AIS) 控制终端使用手册 v2.5
|
| 2 |
+
|
| 3 |
+
## 1. 核心架构:全模态接入 (Full-Modal Control)
|
| 4 |
+
**神思庭控制终端** 是一款专为音视频创作(Pro Tools, Kdenlive, Cubase)设计的硬件级智能体。
|
| 5 |
+
|
| 6 |
+
* **微信语音/网页控制**:通过 iPhone 13 微信键盘的高精度识别。
|
| 7 |
+
* **物理 MIDI 触发**:将编曲键盘转化为 100+ 专业 Skills 触发器。
|
| 8 |
+
* **内核级按键模拟**:绕过系统 GUI 限制,实现毫秒级响应。
|
| 9 |
+
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
## 2. 语音 Skills 唤醒指南 (iPhone 13 / 微信)
|
| 13 |
+
1. **建立连接**:浏览器访问 `http://192.168.1.9:5000`。
|
| 14 |
+
2. **场景灵魂触发**:
|
| 15 |
+
- 说出“**播放**”:触发全局走带。
|
| 16 |
+
- 说出“**剃刀**”:切换 X 键并执行**一键物理点击**。
|
| 17 |
+
3. **状态反馈**:电脑播报:“**已执行[技能名]**”。
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
## 3. MIDI 硬件映射自定义
|
| 22 |
+
* **默认映射**:C3 (60) -> 播放 | D3 (62) -> 剃刀 | E3 (64) -> 撤销。
|
| 23 |
+
* **修改方式**:在 `Shensist_Launcher.py` 的 `MIDI_MAP` 中调整。
|
| 24 |
+
|
| 25 |
+
---
|
| 26 |
+
|
| 27 |
+
## 4. 安全与版权声明
|
| 28 |
+
* **本地安全**:所有逻辑存储在本地 `~/桌面/Shensist_Matrix/`。
|
| 29 |
+
* **版权保护**:© 2026 Shensist (AIS). All Rights Reserved.
|
| 30 |
+
* **官方发布**:唯一渠道 [https://shensist.top/](https://shensist.top/)。
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
**神思庭艺术智能工作室 (AIS)**
|
LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
神思庭艺术智能工作室 (AIS) 软件许可协议
|
| 2 |
+
|
| 3 |
+
1. 版权归属:本软件(Shensist-AirEye)及其附带的 100 个快捷键映射表(Skills Dictionary)的所有权、版权及知识产权均归属于神思庭艺术智能工作室(Shensist AIS)所有。
|
| 4 |
+
2. 许可范围:仅限个人非商业用途使用。
|
| 5 |
+
3. 严禁行为:严禁任何个人或组织在未获得官方授权的情况下:
|
| 6 |
+
- 将本软件打包销售或作为商业服务的组成部分。
|
| 7 |
+
- 移除或篡改软件中的任何版权标识及 https://shensist.top/ 链接。
|
| 8 |
+
- 对内核驱动(evdev/PTSL)封装逻辑进行反向工程。
|
| 9 |
+
4. 免责声明:本软件为实验性 AI 辅助工具,开发者不对因使用本软件导致的任何数据丢失或软件冲突负责。
|
| 10 |
+
|
| 11 |
+
© 2026 Shensist (AIS). 保留所有权利。
|
README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🏛️ 神思庭 (Shensist-AIS) 控制终端 v2.5 Official
|
| 2 |
+
|
| 3 |
+
## 1. 核心架构:全模态接入 (Full-Modal Control)
|
| 4 |
+
* 微信语音/网页控制:通过 iPhone 13 微信键盘的高精度识别。
|
| 5 |
+
* 物理 MIDI 触发:将编曲键盘转化为 100+ 专业 Skills 触发器。
|
| 6 |
+
* 内核级按键模拟:实现毫秒级响应。
|
| 7 |
+
|
| 8 |
+
## 2. 快速入门
|
| 9 |
+
1. 启动服务:./dist/Shensist_Terminal_Pro
|
| 10 |
+
2. 访问控制台:http://192.168.1.9:5000
|
| 11 |
+
3. 版权声明:© 2026 Shensist (AIS). shensist.top
|
Shensist_AirEye_Core.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, json, time, evdev
|
| 2 |
+
from evdev import UInput, ecodes as e
|
| 3 |
+
from vosk import Model, KaldiRecognizer
|
| 4 |
+
import pyaudio
|
| 5 |
+
|
| 6 |
+
# 配置路径
|
| 7 |
+
BASE_PATH = "/home/mmm/桌面/Shensist_Matrix/Shensist_AirEye/"
|
| 8 |
+
MODEL_PATH = os.path.join(BASE_PATH, "models/cn-model")
|
| 9 |
+
|
| 10 |
+
# [同音词映射表] 解决“肤质”、“物质”、“转帖”等识别偏差 [cite: 1, 16]
|
| 11 |
+
PHONETIC_MAP = {
|
| 12 |
+
"肤质": "复制", "五至": "复制", "物质": "复制", "府治": "复制",
|
| 13 |
+
"反击": "复制", "难题": "复制", "问题": "复制",
|
| 14 |
+
"转帖": "粘贴", "专辑": "粘贴", "粘接": "粘贴", "粘基": "粘贴"
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
# [内核级物理按键模拟] 直接绕过 Wayland 桌面限制 [cite: 2, 9]
|
| 18 |
+
def send_key_combo(keys):
|
| 19 |
+
try:
|
| 20 |
+
with UInput() as ui:
|
| 21 |
+
for key in keys:
|
| 22 |
+
ui.write(e.EV_KEY, key, 1)
|
| 23 |
+
for key in reversed(keys):
|
| 24 |
+
ui.write(e.EV_KEY, key, 0)
|
| 25 |
+
ui.syn()
|
| 26 |
+
return True
|
| 27 |
+
except Exception as err:
|
| 28 |
+
print(f"❌ 物理按键模拟失败: {err}")
|
| 29 |
+
return False
|
| 30 |
+
|
| 31 |
+
# 系统动作定义
|
| 32 |
+
SYSTEM_ACTIONS = {
|
| 33 |
+
"复制": lambda: send_key_combo([e.KEY_LEFTCTRL, e.KEY_C]),
|
| 34 |
+
"粘贴": lambda: send_key_combo([e.KEY_LEFTCTRL, e.KEY_V]),
|
| 35 |
+
"撤销": lambda: send_key_combo([e.KEY_LEFTCTRL, e.KEY_Z]),
|
| 36 |
+
"播放": lambda: send_key_combo([e.KEY_SPACE]),
|
| 37 |
+
"切换": lambda: send_key_combo([e.KEY_LEFTALT, e.KEY_TAB])
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
class ShensistMasterAgent:
|
| 41 |
+
def __init__(self):
|
| 42 |
+
if not os.path.exists(MODEL_PATH):
|
| 43 |
+
print(f"❌ 错误:找不到 Vosk 模型 at {MODEL_PATH}")
|
| 44 |
+
return
|
| 45 |
+
|
| 46 |
+
self.model = Model(MODEL_PATH)
|
| 47 |
+
self.recognizer = KaldiRecognizer(self.model, 16000)
|
| 48 |
+
self.mic = pyaudio.PyAudio()
|
| 49 |
+
try:
|
| 50 |
+
self.stream = self.mic.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8192)
|
| 51 |
+
self.stream.start_stream()
|
| 52 |
+
print("🏛️ [Shensist-AirEye] 系统级内核驱动已重载。权限已修复。")
|
| 53 |
+
except Exception as ex:
|
| 54 |
+
print(f"❌ 麦克风开启失败: {ex}")
|
| 55 |
+
self.stream = None
|
| 56 |
+
|
| 57 |
+
def run(self):
|
| 58 |
+
if not self.stream:
|
| 59 |
+
return
|
| 60 |
+
while True:
|
| 61 |
+
try:
|
| 62 |
+
data = self.stream.read(4000, exception_on_overflow=False)
|
| 63 |
+
if self.recognizer.AcceptWaveform(data):
|
| 64 |
+
res = json.loads(self.recognizer.Result())
|
| 65 |
+
text = res.get("text", "").replace(" ", "")
|
| 66 |
+
if not text: continue
|
| 67 |
+
|
| 68 |
+
# 同音修正逻辑
|
| 69 |
+
for k, v in PHONETIC_MAP.items():
|
| 70 |
+
if k in text: text = v
|
| 71 |
+
|
| 72 |
+
print(f"🎙️ 识别并修正: {text}")
|
| 73 |
+
|
| 74 |
+
if text in SYSTEM_ACTIONS:
|
| 75 |
+
if SYSTEM_ACTIONS[text]():
|
| 76 |
+
print(f"⚡ [内核执行成功] 已发送物理按键: {text}")
|
| 77 |
+
except KeyboardInterrupt:
|
| 78 |
+
break
|
| 79 |
+
except Exception as ex:
|
| 80 |
+
print(f"⚠️ 系统核心错误: {ex}")
|
| 81 |
+
|
| 82 |
+
if __name__ == "__main__":
|
| 83 |
+
ShensistMasterAgent().run()
|
Shensist_File_Agent.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, time, evdev
|
| 2 |
+
from evdev import UInput, ecodes as e
|
| 3 |
+
|
| 4 |
+
# 内核按键模拟
|
| 5 |
+
def send_key_combo(keys):
|
| 6 |
+
try:
|
| 7 |
+
with UInput() as ui:
|
| 8 |
+
for key in keys: ui.write(e.EV_KEY, key, 1)
|
| 9 |
+
for key in reversed(keys): ui.write(e.EV_KEY, key, 0)
|
| 10 |
+
ui.syn()
|
| 11 |
+
return True
|
| 12 |
+
except Exception as err:
|
| 13 |
+
print(f"❌ 模拟失败: {err}")
|
| 14 |
+
return False
|
| 15 |
+
|
| 16 |
+
ACTIONS = {
|
| 17 |
+
"复制": [e.KEY_LEFTCTRL, e.KEY_C],
|
| 18 |
+
"粘贴": [e.KEY_LEFTCTRL, e.KEY_V],
|
| 19 |
+
"撤销": [e.KEY_LEFTCTRL, e.KEY_Z],
|
| 20 |
+
"播放": [e.KEY_SPACE],
|
| 21 |
+
"停止": [e.KEY_SPACE],
|
| 22 |
+
"保存": [e.KEY_LEFTCTRL, e.KEY_S]
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
CMD_FILE = "/home/mmm/桌面/Shensist_Matrix/Shensist_AirEye/cmd.txt"
|
| 26 |
+
|
| 27 |
+
print("🏛️ [Shensist-File-Agent] 文件指令监听已启动。")
|
| 28 |
+
print(f"📄 请在 {CMD_FILE} 中输入指令并保存。")
|
| 29 |
+
|
| 30 |
+
# 确保文件存在
|
| 31 |
+
if not os.path.exists(CMD_FILE):
|
| 32 |
+
with open(CMD_FILE, 'w') as f: f.write("")
|
| 33 |
+
|
| 34 |
+
while True:
|
| 35 |
+
try:
|
| 36 |
+
# 如果文件不存在则说明被删除,重新创建
|
| 37 |
+
if not os.path.exists(CMD_FILE):
|
| 38 |
+
with open(CMD_FILE, 'w') as f: f.write("")
|
| 39 |
+
|
| 40 |
+
with open(CMD_FILE, 'r+') as f:
|
| 41 |
+
content = f.read().strip()
|
| 42 |
+
if content:
|
| 43 |
+
print(f"📥 收到文件指令: {content}")
|
| 44 |
+
executed = False
|
| 45 |
+
for k, v in ACTIONS.items():
|
| 46 |
+
if k in content:
|
| 47 |
+
if send_key_combo(v):
|
| 48 |
+
print(f"⚡ [执行成功] 物理按键: {k}")
|
| 49 |
+
executed = True
|
| 50 |
+
break
|
| 51 |
+
if not executed:
|
| 52 |
+
print(f"❓ 未匹配指令: {content}")
|
| 53 |
+
|
| 54 |
+
# 执行完清空文件,等待下次指令
|
| 55 |
+
f.seek(0)
|
| 56 |
+
f.truncate()
|
| 57 |
+
time.sleep(0.5) # 每0.5秒扫描一次
|
| 58 |
+
except KeyboardInterrupt:
|
| 59 |
+
break
|
| 60 |
+
except Exception as err:
|
| 61 |
+
print(f"❌ 运行异常: {err}")
|
| 62 |
+
time.sleep(1)
|
Shensist_Kernel_Input.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import evdev
|
| 2 |
+
from evdev import UInput, ecodes as e
|
| 3 |
+
from flask import Flask, request
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
# 定义虚拟硬件具备的按键能力 (模拟物理键盘)
|
| 7 |
+
capabilities = {
|
| 8 |
+
e.EV_KEY: [e.KEY_C, e.KEY_V, e.KEY_SPACE, e.KEY_LEFTCTRL, e.KEY_LEFTALT, e.KEY_Z]
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
app = Flask(__name__)
|
| 12 |
+
|
| 13 |
+
class ShensistInputEngine:
|
| 14 |
+
def __init__(self):
|
| 15 |
+
# 注册一个名为 "Shensist-Virtual-HID" 的真实硬件设备
|
| 16 |
+
try:
|
| 17 |
+
self.ui = UInput(capabilities, name='Shensist-Virtual-HID')
|
| 18 |
+
except PermissionError:
|
| 19 |
+
print("❌ Permission Error: Please run 'sudo chmod 666 /dev/uinput' first.")
|
| 20 |
+
raise
|
| 21 |
+
|
| 22 |
+
def tap_hotkey(self, modifier, key):
|
| 23 |
+
self.ui.write(e.EV_KEY, modifier, 1)
|
| 24 |
+
self.ui.write(e.EV_KEY, key, 1)
|
| 25 |
+
self.ui.write(e.EV_KEY, key, 0)
|
| 26 |
+
self.ui.write(e.EV_KEY, modifier, 0)
|
| 27 |
+
self.ui.syn()
|
| 28 |
+
|
| 29 |
+
def tap_key(self, key):
|
| 30 |
+
self.ui.write(e.EV_KEY, key, 1)
|
| 31 |
+
self.ui.write(e.EV_KEY, key, 0)
|
| 32 |
+
self.ui.syn()
|
| 33 |
+
|
| 34 |
+
engine = None
|
| 35 |
+
|
| 36 |
+
@app.route('/exec')
|
| 37 |
+
def execute():
|
| 38 |
+
global engine
|
| 39 |
+
if engine is None:
|
| 40 |
+
try:
|
| 41 |
+
engine = ShensistInputEngine()
|
| 42 |
+
except Exception as e:
|
| 43 |
+
return f"Error initializing HID engine: {str(e)}", 500
|
| 44 |
+
|
| 45 |
+
msg = request.args.get('msg', '')
|
| 46 |
+
print(f"🎙️ 接收指令: {msg}")
|
| 47 |
+
|
| 48 |
+
# 映射表:手机文字 -> 硬件按键动作
|
| 49 |
+
if "复制" in msg:
|
| 50 |
+
engine.tap_hotkey(e.KEY_LEFTCTRL, e.KEY_C)
|
| 51 |
+
elif "粘贴" in msg:
|
| 52 |
+
engine.tap_hotkey(e.KEY_LEFTCTRL, e.KEY_V)
|
| 53 |
+
elif "播放" in msg or "停止" in msg:
|
| 54 |
+
engine.tap_key(e.KEY_SPACE)
|
| 55 |
+
elif "撤销" in msg:
|
| 56 |
+
engine.tap_hotkey(e.KEY_LEFTCTRL, e.KEY_Z)
|
| 57 |
+
|
| 58 |
+
return f"Executed: {msg}"
|
| 59 |
+
|
| 60 |
+
if __name__ == '__main__':
|
| 61 |
+
print("🏛️ [Shensist-AirEye] 虚拟 HID 硬件助手等待上线。")
|
| 62 |
+
print("⚠️ 注意: 该脚本需要 /dev/uinput 的读写权限。")
|
| 63 |
+
app.run(host='0.0.0.0', port=5000)
|
Shensist_Launcher.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =================================================================
|
| 2 |
+
# 🏛️ 项目名称:神思庭控制终端 (Shensist-AirEye Terminal)
|
| 3 |
+
# 🎨 创作者:神思庭艺术智能工作室 (Shensist Art Intelligence Studio)
|
| 4 |
+
# 📜 版权所有:© 2025-2026 Shensist (AIS). All Rights Reserved.
|
| 5 |
+
# 🌐 官方网站:https://shensist.top/
|
| 6 |
+
# ⚠️ 法律声明:本软件及其核心 Skills 逻辑受版权法保护。
|
| 7 |
+
# =================================================================
|
| 8 |
+
import os
|
| 9 |
+
import sys
|
| 10 |
+
import threading
|
| 11 |
+
import subprocess
|
| 12 |
+
|
| 13 |
+
# 🏛️ 神思庭 (AIS) 核心组件导入
|
| 14 |
+
# 启动时自动校检依赖环境
|
| 15 |
+
try:
|
| 16 |
+
import mido
|
| 17 |
+
except ImportError:
|
| 18 |
+
print("📦 [Shensist-AIS] 正在补全 MIDI 驱动组件...")
|
| 19 |
+
try:
|
| 20 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "mido", "python-rtmidi"])
|
| 21 |
+
import mido
|
| 22 |
+
except Exception as e:
|
| 23 |
+
print(f"❌ 依赖安装失败: {e}")
|
| 24 |
+
mido = None
|
| 25 |
+
|
| 26 |
+
def run_midi_engine():
|
| 27 |
+
"""后台 MIDI 监听线程:将物理按键转化为语义指令"""
|
| 28 |
+
if not mido:
|
| 29 |
+
print("⚠️ MIDI 核心库未载入,硬件监听已禁用。")
|
| 30 |
+
return
|
| 31 |
+
|
| 32 |
+
print("🎹 [神思庭-AIS] 硬件 MIDI 引擎初始化中...")
|
| 33 |
+
# 映射字典与 skills_map.json 保持逻辑对齐
|
| 34 |
+
MIDI_MAP = {60: "播放", 62: "剃刀", 64: "撤销"}
|
| 35 |
+
|
| 36 |
+
try:
|
| 37 |
+
# 自动寻找第一个可用的 MIDI 输入端口
|
| 38 |
+
input_names = mido.get_input_names()
|
| 39 |
+
if not input_names:
|
| 40 |
+
print("⚠️ 未发现物理 MIDI 设备,硬件监听挂起。")
|
| 41 |
+
return
|
| 42 |
+
|
| 43 |
+
print(f"✅ 已成功挂载 MIDI 硬件: {input_names[0]}")
|
| 44 |
+
with mido.open_input(input_names[0]) as inport:
|
| 45 |
+
from Shensist_Web_Master import do_action
|
| 46 |
+
for msg in inport:
|
| 47 |
+
# velocity > 0 表示按下动作
|
| 48 |
+
if msg.type == 'note_on' and msg.velocity > 0:
|
| 49 |
+
if msg.note in MIDI_MAP:
|
| 50 |
+
skill = MIDI_MAP[msg.note]
|
| 51 |
+
# 内部闭环调用,绕过网络延迟
|
| 52 |
+
do_action(skill)
|
| 53 |
+
print(f"⚡ [硬件触发] MIDI {msg.note} -> 执行: {skill}")
|
| 54 |
+
except Exception as e:
|
| 55 |
+
print(f"❌ MIDI 引擎异常: {e}")
|
| 56 |
+
|
| 57 |
+
def run_web_master():
|
| 58 |
+
"""主线程 Web 服务:处理远程 iPhone 13 指令"""
|
| 59 |
+
print("🏛️ [神思庭-AIS] 正在挂载 Web 控制中枢...")
|
| 60 |
+
if sys.platform == "linux":
|
| 61 |
+
# 自动提权处理内核 HID 权限
|
| 62 |
+
os.system('sudo chmod 666 /dev/uinput')
|
| 63 |
+
|
| 64 |
+
# 动态导入 Web Master 核心
|
| 65 |
+
from Shensist_Web_Master import app
|
| 66 |
+
app.run(host='0.0.0.0', port=5000, use_reloader=False)
|
| 67 |
+
|
| 68 |
+
if __name__ == "__main__":
|
| 69 |
+
print("\n" + "="*50)
|
| 70 |
+
print("🏛️ SHENSIST-AIREYE TERMINAL v2.5 OFFICIAL")
|
| 71 |
+
print("🎨 神思庭艺术智能工作室 (AIS) | shensist.top")
|
| 72 |
+
print("="*50 + "\n")
|
| 73 |
+
|
| 74 |
+
# 1. 启动并联 MIDI 监听线程
|
| 75 |
+
midi_thread = threading.Thread(target=run_midi_engine, daemon=True)
|
| 76 |
+
midi_thread.start()
|
| 77 |
+
|
| 78 |
+
# 2. 启动主 Web 服务 (阻塞)
|
| 79 |
+
run_web_master()
|
Shensist_MIDI_Listener.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =================================================================
|
| 2 |
+
# 🏛️ 项目名称:神思庭控制终端 (Shensist-AirEye Terminal)
|
| 3 |
+
# 🎨 创作者:神思庭艺术智能工作室 (Shensist Art Intelligence Studio)
|
| 4 |
+
# 📜 版权所有:© 2025-2026 Shensist (AIS). All Rights Reserved.
|
| 5 |
+
# 🌐 官方网站:https://shensist.top/
|
| 6 |
+
# ⚠️ 法律声明:本软件及其核心 Skills 逻辑受版权法保护。
|
| 7 |
+
# =================================================================
|
| 8 |
+
import mido
|
| 9 |
+
import os
|
| 10 |
+
import requests
|
| 11 |
+
|
| 12 |
+
# 映射:MIDI 键号 -> 语义指令
|
| 13 |
+
# 例如:按下 C3 (60) 触发“播放”,按下 D3 (62) 触发“剃刀”
|
| 14 |
+
MIDI_SKILLS = {
|
| 15 |
+
60: "播放",
|
| 16 |
+
62: "剃刀",
|
| 17 |
+
64: "撤销"
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
def midi_listener():
|
| 21 |
+
print("🎹 [神思庭-AIS] MIDI 监听引擎已启动...")
|
| 22 |
+
print("📡 正在探测物理 MIDI 设备...")
|
| 23 |
+
|
| 24 |
+
# 自动探测第一个可用的 MIDI 输入端口
|
| 25 |
+
try:
|
| 26 |
+
# 获取所有输入端口列表
|
| 27 |
+
input_names = mido.get_input_names()
|
| 28 |
+
if not input_names:
|
| 29 |
+
print("⚠️ 未检测到任何 MIDI 输入设备。")
|
| 30 |
+
return
|
| 31 |
+
|
| 32 |
+
print(f"✅ 已检测到设备: {input_names[0]}")
|
| 33 |
+
with mido.open_input(input_names[0]) as inport:
|
| 34 |
+
for msg in inport:
|
| 35 |
+
# 仅处理 note_on 且 velocity > 0 (按下键)
|
| 36 |
+
if msg.type == 'note_on' and msg.velocity > 0:
|
| 37 |
+
if msg.note in MIDI_SKILLS:
|
| 38 |
+
skill = MIDI_SKILLS[msg.note]
|
| 39 |
+
# 联动 Web Master 执行逻辑
|
| 40 |
+
try:
|
| 41 |
+
# 优先尝试本地 127.0.0.1 端口触发
|
| 42 |
+
url = f"http://127.0.0.1:5000/exec?msg={skill}"
|
| 43 |
+
requests.get(url, timeout=1)
|
| 44 |
+
print(f"⚡ [MIDI 触发] 键号 {msg.note} -> 执行技能: {skill}")
|
| 45 |
+
except Exception as e:
|
| 46 |
+
print(f"❌ 触发失败: Web Master 未启动或连接超时 ({e})")
|
| 47 |
+
else:
|
| 48 |
+
print(f"🔍 [MIDI 监听] 未定义键号: {msg.note}")
|
| 49 |
+
|
| 50 |
+
except Exception as err:
|
| 51 |
+
print(f"❌ MIDI 引擎错误: {err}")
|
| 52 |
+
|
| 53 |
+
if __name__ == "__main__":
|
| 54 |
+
midi_listener()
|
Shensist_MIDI_Master.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import rtmidi, time, os
|
| 2 |
+
from flask import Flask, request
|
| 3 |
+
|
| 4 |
+
# 初始化虚拟 MIDI 端口
|
| 5 |
+
midiout = rtmidi.MidiOut()
|
| 6 |
+
# 在系统层注册名为 "Shensist_AirEye_Control" 的硬件设备
|
| 7 |
+
midiout.open_virtual_port("Shensist_AirEye_Control")
|
| 8 |
+
|
| 9 |
+
app = Flask(__name__)
|
| 10 |
+
|
| 11 |
+
# 指令映射:将文字转化为标准 MIDI CC 指令 (音频软件通用语言)
|
| 12 |
+
COMMAND_MAP = {
|
| 13 |
+
"播放": [0xB0, 118, 127], # CC 118: Play
|
| 14 |
+
"停止": [0xB0, 117, 127], # CC 117: Stop
|
| 15 |
+
"录音": [0xB0, 119, 127], # CC 119: Record
|
| 16 |
+
"复制": [0xB0, 102, 127],
|
| 17 |
+
"粘贴": [0xB0, 103, 127],
|
| 18 |
+
"play": [0xB0, 118, 127],
|
| 19 |
+
"stop": [0xB0, 117, 127],
|
| 20 |
+
"record": [0xB0, 119, 127]
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
@app.route('/exec')
|
| 24 |
+
def execute():
|
| 25 |
+
msg = request.args.get('msg', '')
|
| 26 |
+
print(f"🎙️ 接收到文字指令: {msg}")
|
| 27 |
+
for k, v in COMMAND_MAP.items():
|
| 28 |
+
if k in msg:
|
| 29 |
+
midiout.send_message(v)
|
| 30 |
+
print(f"⚡ [MIDI 注入成功] 已模拟硬件按下: {k}")
|
| 31 |
+
return f"SENT: {k}"
|
| 32 |
+
return "NO MATCH"
|
| 33 |
+
|
| 34 |
+
if __name__ == '__main__':
|
| 35 |
+
# 强制开放 5000 端口,供手机访问
|
| 36 |
+
print("🏛️ [Shensist-AirEye] 虚拟 MIDI 硬件已挂载。")
|
| 37 |
+
print("🔗 手机请访问 http://192.168.1.9:5000/exec?msg=播放")
|
| 38 |
+
app.run(host='0.0.0.0', port=5000)
|
Shensist_PT_Bridge.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =================================================================
|
| 2 |
+
# 🏛️ 项目名称:神思庭控制终端 (Shensist-AirEye Terminal)
|
| 3 |
+
# 🎨 创作者:神思庭艺术智能工作室 (Shensist Art Intelligence Studio)
|
| 4 |
+
# 📜 版权所有:© 2025-2026 Shensist (AIS). All Rights Reserved.
|
| 5 |
+
# 🌐 官方网站:https://shensist.top/
|
| 6 |
+
# ⚠️ 法律声明:本软件及其核心 Skills 逻辑受版权法保护。
|
| 7 |
+
# 未经书面许可,严禁用于任何商业用途、分发、修改或反向工程。
|
| 8 |
+
# =================================================================
|
| 9 |
+
# Shensist-AirEye macOS 适配模块 (基于 py-ptsl)
|
| 10 |
+
import os
|
| 11 |
+
import time
|
| 12 |
+
|
| 13 |
+
# 架构师注意:在 Mac 上执行 pip install py-ptsl
|
| 14 |
+
try:
|
| 15 |
+
from py_ptsl import PTSL
|
| 16 |
+
IS_MAC = True
|
| 17 |
+
except ImportError:
|
| 18 |
+
IS_MAC = False
|
| 19 |
+
print("⚠️ [Shensist-Logic] 当前处于非 Mac 环境,启动 Mock 模拟模式")
|
| 20 |
+
|
| 21 |
+
class ProToolsBridge:
|
| 22 |
+
def __init__(self):
|
| 23 |
+
if IS_MAC:
|
| 24 |
+
# 连接到 Pro Tools PTSL 接口 [cite: 4]
|
| 25 |
+
self.pt = PTSL.connect()
|
| 26 |
+
print("🍏 [Shensist-AIS] 已通过 PTSL 挂载 Pro Tools 内核")
|
| 27 |
+
else:
|
| 28 |
+
self.pt = None
|
| 29 |
+
|
| 30 |
+
def execute(self, cmd):
|
| 31 |
+
"""将语音指令转化为 Pro Tools 原生 API 调用 """
|
| 32 |
+
if "播放" in cmd:
|
| 33 |
+
if IS_MAC: self.pt.transport_play()
|
| 34 |
+
else: print("🎵 [模拟] Pro Tools 播放")
|
| 35 |
+
|
| 36 |
+
elif "停止" in cmd:
|
| 37 |
+
if IS_MAC: self.pt.transport_stop()
|
| 38 |
+
else: print("⏹️ [模拟] Pro Tools 停止")
|
| 39 |
+
|
| 40 |
+
elif "录音" in cmd:
|
| 41 |
+
if IS_MAC: self.pt.transport_record()
|
| 42 |
+
else: print("🔴 [模拟] Pro Tools 录音")
|
| 43 |
+
|
| 44 |
+
elif "切断" in cmd or "分割" in cmd:
|
| 45 |
+
# Pro Tools 经典的 Ctrl+E 分割动作
|
| 46 |
+
if IS_MAC:
|
| 47 |
+
self.pt.edit_selection_separate()
|
| 48 |
+
else:
|
| 49 |
+
print("✂️ [模拟] 执行剪辑分割 (Ctrl+E)")
|
| 50 |
+
|
| 51 |
+
# 语音反馈:神思庭控制终端的反馈灵魂
|
| 52 |
+
os.system(f'spd-say "Pro Tools 已执行{cmd}" &')
|
| 53 |
+
|
| 54 |
+
# 实例化单例
|
| 55 |
+
pt_bridge = ProToolsBridge()
|
Shensist_System_Master.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, json, time, pyautogui, cv2, numpy as np
|
| 2 |
+
from vosk import Model, KaldiRecognizer
|
| 3 |
+
import pyaudio
|
| 4 |
+
|
| 5 |
+
# 路径配置
|
| 6 |
+
BASE_PATH = "/home/mmm/桌面/Shensist_Matrix/Shensist_AirEye/"
|
| 7 |
+
MODEL_PATH = os.path.join(BASE_PATH, "models/cn-model")
|
| 8 |
+
|
| 9 |
+
# 顶级系统控制映射:将语音直接映射为系统级动作或图像匹配
|
| 10 |
+
# 无需逐个教,这里直接定义常用系统行为和软件通用逻辑
|
| 11 |
+
SYSTEM_COMMANDS = {
|
| 12 |
+
"复制": lambda: pyautogui.hotkey('ctrl', 'c'),
|
| 13 |
+
"粘贴": lambda: pyautogui.hotkey('ctrl', 'v'),
|
| 14 |
+
"全选": lambda: pyautogui.hotkey('ctrl', 'a'),
|
| 15 |
+
"撤销": lambda: pyautogui.hotkey('ctrl', 'z'),
|
| 16 |
+
"保存": lambda: pyautogui.hotkey('ctrl', 's'),
|
| 17 |
+
"切换": lambda: pyautogui.hotkey('alt', 'tab'),
|
| 18 |
+
"关闭": lambda: pyautogui.hotkey('alt', 'f4'),
|
| 19 |
+
"搜索": lambda: pyautogui.hotkey('ctrl', 'f'),
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
class SystemMasterAgent:
|
| 23 |
+
def __init__(self):
|
| 24 |
+
if not os.path.exists(MODEL_PATH):
|
| 25 |
+
print(f"❌ 错误:找不到 Vosk 模型 at {MODEL_PATH}")
|
| 26 |
+
return
|
| 27 |
+
|
| 28 |
+
self.model = Model(MODEL_PATH)
|
| 29 |
+
self.recognizer = KaldiRecognizer(self.model, 16000)
|
| 30 |
+
self.mic = pyaudio.PyAudio()
|
| 31 |
+
try:
|
| 32 |
+
self.stream = self.mic.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8192)
|
| 33 |
+
self.stream.start_stream()
|
| 34 |
+
print("🏛️ [Shensist-AirEye] 系统级智能体已就绪。正在全局监听...")
|
| 35 |
+
except Exception as e:
|
| 36 |
+
print(f"❌ 麦克风初始化失败: {e}")
|
| 37 |
+
self.stream = None
|
| 38 |
+
|
| 39 |
+
def run(self):
|
| 40 |
+
if not self.stream:
|
| 41 |
+
return
|
| 42 |
+
while True:
|
| 43 |
+
try:
|
| 44 |
+
data = self.stream.read(4000, exception_on_overflow=False)
|
| 45 |
+
if self.recognizer.AcceptWaveform(data):
|
| 46 |
+
res = json.loads(self.recognizer.Result())
|
| 47 |
+
text = res.get("text", "").replace(" ", "")
|
| 48 |
+
if not text: continue
|
| 49 |
+
print(f"🎙️ 系统指令: {text}")
|
| 50 |
+
|
| 51 |
+
# 1. 优先执行系统级快捷键
|
| 52 |
+
executed = False
|
| 53 |
+
for cmd, func in SYSTEM_COMMANDS.items():
|
| 54 |
+
if cmd in text:
|
| 55 |
+
func()
|
| 56 |
+
print(f"⚡ 执行系统动作: {cmd}")
|
| 57 |
+
executed = True
|
| 58 |
+
break
|
| 59 |
+
|
| 60 |
+
# 2. 若非快捷键,尝试在 system_skills 目录下进行图像匹配(控制任意软件GUI)
|
| 61 |
+
if not executed:
|
| 62 |
+
self.auto_match_and_click(text)
|
| 63 |
+
except KeyboardInterrupt:
|
| 64 |
+
break
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"⚠️ 系统核心错误: {e}")
|
| 67 |
+
|
| 68 |
+
def auto_match_and_click(self, text):
|
| 69 |
+
# 扫描 system_skills 目录,寻找与语音匹配的截图锚点
|
| 70 |
+
skill_dir = os.path.join(BASE_PATH, "system_skills")
|
| 71 |
+
if not os.path.exists(skill_dir):
|
| 72 |
+
return
|
| 73 |
+
|
| 74 |
+
for skill_name in os.listdir(skill_dir):
|
| 75 |
+
if skill_name in text:
|
| 76 |
+
anchor_path = os.path.join(skill_dir, skill_name, "anchor.png")
|
| 77 |
+
if os.path.exists(anchor_path):
|
| 78 |
+
template = cv2.imread(anchor_path)
|
| 79 |
+
screen = cv2.cvtColor(np.array(pyautogui.screenshot()), cv2.COLOR_RGB2BGR)
|
| 80 |
+
res = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
|
| 81 |
+
_, max_val, _, max_loc = cv2.minMaxLoc(res)
|
| 82 |
+
if max_val > 0.7:
|
| 83 |
+
pyautogui.click(max_loc[0] + 30, max_loc[1] + 30)
|
| 84 |
+
print(f"🎯 视觉匹配成功: {skill_name}")
|
| 85 |
+
|
| 86 |
+
if __name__ == "__main__":
|
| 87 |
+
SystemMasterAgent().run()
|
Shensist_V_MIDI.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import rtmidi, time
|
| 2 |
+
from flask import Flask, request
|
| 3 |
+
|
| 4 |
+
# 初始化虚拟 MIDI 端口 - 这会被 Pro Tools/Cubase 识别为真实的硬件控制器
|
| 5 |
+
midiout = rtmidi.MidiOut()
|
| 6 |
+
available_ports = midiout.get_ports()
|
| 7 |
+
midiout.open_virtual_port("Shensist_AirEye_Control")
|
| 8 |
+
|
| 9 |
+
app = Flask(__name__)
|
| 10 |
+
|
| 11 |
+
# 指令映射:将文字直接转化为标准 MIDI CC 指令
|
| 12 |
+
# 这是 2026 年最稳定的专业软件控制方式,不依赖系统快捷键
|
| 13 |
+
COMMAND_MAP = {
|
| 14 |
+
"播放": [0xB0, 118, 127], # CC 118: Play
|
| 15 |
+
"停止": [0xB0, 117, 127], # CC 117: Stop
|
| 16 |
+
"录音": [0xB0, 119, 127], # CC 119: Record
|
| 17 |
+
"复制": [0xB0, 102, 127], # 自定义映射至软件内 Skills
|
| 18 |
+
"粘贴": [0xB0, 103, 127],
|
| 19 |
+
"play": [0xB0, 118, 127],
|
| 20 |
+
"stop": [0xB0, 117, 127],
|
| 21 |
+
"record": [0xB0, 119, 127]
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
@app.route('/exec')
|
| 25 |
+
def execute():
|
| 26 |
+
msg = request.args.get('msg', '')
|
| 27 |
+
print(f"🎙️ 收到指令: {msg}")
|
| 28 |
+
for k, v in COMMAND_MAP.items():
|
| 29 |
+
if k in msg:
|
| 30 |
+
midiout.send_message(v)
|
| 31 |
+
return f"SENT MIDI: {k}"
|
| 32 |
+
return "NO MATCH"
|
| 33 |
+
|
| 34 |
+
if __name__ == '__main__':
|
| 35 |
+
print("🏛️ [Shensist-AirEye] 虚拟硬件代理已上线。")
|
| 36 |
+
print("🔗 请在 Pro Tools/Cubase 的 MIDI 设置中将 'Shensist_AirEye_Control' 选为输入设备。")
|
| 37 |
+
app.run(host='0.0.0.0', port=5000)
|
Shensist_WeChat_Control.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, json, evdev
|
| 2 |
+
from flask import Flask, request, render_template_string
|
| 3 |
+
from evdev import UInput, ecodes as e
|
| 4 |
+
|
| 5 |
+
app = Flask(__name__)
|
| 6 |
+
|
| 7 |
+
# [内核执行逻辑] 模拟物理按键,支持 Pro Tools, Kdenlive 等万级指令
|
| 8 |
+
def send_key_combo(keys):
|
| 9 |
+
try:
|
| 10 |
+
with UInput() as ui:
|
| 11 |
+
for key in keys: ui.write(e.EV_KEY, key, 1)
|
| 12 |
+
for key in reversed(keys): ui.write(e.EV_KEY, key, 0)
|
| 13 |
+
ui.syn()
|
| 14 |
+
return True
|
| 15 |
+
except Exception as err:
|
| 16 |
+
print(f"❌ 模拟失败: {err}")
|
| 17 |
+
return False
|
| 18 |
+
|
| 19 |
+
# 指令映射库
|
| 20 |
+
ACTIONS = {
|
| 21 |
+
"复制": [e.KEY_LEFTCTRL, e.KEY_C],
|
| 22 |
+
"粘贴": [e.KEY_LEFTCTRL, e.KEY_V],
|
| 23 |
+
"撤销": [e.KEY_LEFTCTRL, e.KEY_Z],
|
| 24 |
+
"播放": [e.KEY_SPACE],
|
| 25 |
+
"停止": [e.KEY_SPACE],
|
| 26 |
+
"保存": [e.KEY_LEFTCTRL, e.KEY_S],
|
| 27 |
+
"全选": [e.KEY_LEFTCTRL, e.KEY_A]
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
HTML = """
|
| 31 |
+
<!DOCTYPE html>
|
| 32 |
+
<html>
|
| 33 |
+
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
| 34 |
+
<title>Shensist WeChat Controller</title></head>
|
| 35 |
+
<body style="text-align:center; padding-top:40px; font-family:sans-serif; background:#f4f4f4;">
|
| 36 |
+
<h2 style="color:#333;">Shensist 系统控制中心</h2>
|
| 37 |
+
<div style="margin-bottom:20px;">
|
| 38 |
+
<input type="text" id="cmd" placeholder="使用微信语音转文字..."
|
| 39 |
+
style="width:85%; height:55px; font-size:18px; border-radius:12px; border:1px solid #ddd; padding:0 10px;">
|
| 40 |
+
</div>
|
| 41 |
+
<button onclick="send()"
|
| 42 |
+
style="width:90%; height:55px; background:#07c160; color:white; border:none; border-radius:12px; font-size:20px; font-weight:bold;">
|
| 43 |
+
发送指令到电脑
|
| 44 |
+
</button>
|
| 45 |
+
<p id="status" style="margin-top:20px; color:#666; font-size:14px;"></p>
|
| 46 |
+
<script>
|
| 47 |
+
function send() {
|
| 48 |
+
let val = document.getElementById('cmd').value;
|
| 49 |
+
if(!val) return;
|
| 50 |
+
document.getElementById('status').innerText = '正在发送: ' + val;
|
| 51 |
+
fetch('/exec?msg=' + encodeURIComponent(val))
|
| 52 |
+
.then(r => r.text())
|
| 53 |
+
.then(t => { document.getElementById('status').innerText = '反馈: ' + t; });
|
| 54 |
+
document.getElementById('cmd').value = '';
|
| 55 |
+
}
|
| 56 |
+
</script>
|
| 57 |
+
</body>
|
| 58 |
+
</html>
|
| 59 |
+
"""
|
| 60 |
+
|
| 61 |
+
@app.route('/')
|
| 62 |
+
def index(): return render_template_string(HTML)
|
| 63 |
+
|
| 64 |
+
@app.route('/exec')
|
| 65 |
+
def execute():
|
| 66 |
+
msg = request.args.get('msg', '')
|
| 67 |
+
print(f"🎙️ 收到微信指令: {msg}")
|
| 68 |
+
for k, v in ACTIONS.items():
|
| 69 |
+
if k in msg:
|
| 70 |
+
if send_key_combo(v): return f"成功: {k}"
|
| 71 |
+
else: return "内核权限错误"
|
| 72 |
+
return "未匹配指令"
|
| 73 |
+
|
| 74 |
+
if __name__ == '__main__':
|
| 75 |
+
# 强制开启 5000 端口服务
|
| 76 |
+
app.run(host='0.0.0.0', port=5000)
|
Shensist_Web_Master.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =================================================================
|
| 2 |
+
# 🏛️ 项目名称:神思庭控制终端 (Shensist-AirEye Terminal)
|
| 3 |
+
# 🎨 创作者:神思庭艺术智能工作室 (Shensist Art Intelligence Studio)
|
| 4 |
+
# 📜 版权所有:© 2025-2026 Shensist (AIS). All Rights Reserved.
|
| 5 |
+
# 🌐 官方网站:https://shensist.top/
|
| 6 |
+
# ⚠️ 法律声明:本软件及其核心 Skills 逻辑受版权法保护。
|
| 7 |
+
# 未经书面许可,严禁用于任何商业用途、分发、修改或反向工程。
|
| 8 |
+
# =================================================================
|
| 9 |
+
import evdev, json, os, pyautogui, time, sys
|
| 10 |
+
from evdev import UInput, ecodes as e
|
| 11 |
+
from flask import Flask, request, render_template_string, send_from_directory
|
| 12 |
+
from Shensist_PT_Bridge import pt_bridge
|
| 13 |
+
|
| 14 |
+
app = Flask(__name__)
|
| 15 |
+
# 适配 PyInstaller 打包后的路径 [cite: 5]
|
| 16 |
+
if hasattr(sys, '_MEIPASS'):
|
| 17 |
+
BASE_DIR = sys._MEIPASS
|
| 18 |
+
else:
|
| 19 |
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 20 |
+
|
| 21 |
+
def load_skills():
|
| 22 |
+
try:
|
| 23 |
+
json_path = os.path.join(BASE_DIR, 'skills_map.json')
|
| 24 |
+
with open(json_path, 'r', encoding='utf-8') as f:
|
| 25 |
+
return json.load(f)
|
| 26 |
+
except Exception as err:
|
| 27 |
+
print(f"⚠️ 无法加载 skills_map.json: {err}")
|
| 28 |
+
return {}
|
| 29 |
+
|
| 30 |
+
# 初始化虚拟硬件键盘
|
| 31 |
+
def init_ui():
|
| 32 |
+
try:
|
| 33 |
+
skills = load_skills()
|
| 34 |
+
registered_keys = set()
|
| 35 |
+
for keys_list in skills.values():
|
| 36 |
+
for k in keys_list:
|
| 37 |
+
key_code = getattr(e, k, None)
|
| 38 |
+
if key_code is not None:
|
| 39 |
+
registered_keys.add(key_code)
|
| 40 |
+
|
| 41 |
+
# 补充一些核心控制键以防万一
|
| 42 |
+
for k in ['KEY_LEFTCTRL', 'KEY_LEFTSHIFT', 'KEY_LEFTALT', 'KEY_ENTER', 'KEY_SPACE']:
|
| 43 |
+
registered_keys.add(getattr(e, k))
|
| 44 |
+
|
| 45 |
+
cap = {e.EV_KEY: list(registered_keys)}
|
| 46 |
+
return UInput(cap, name='Shensist-Universal-HID')
|
| 47 |
+
except PermissionError:
|
| 48 |
+
print("❌ 权限不足: 请运行 'sudo chmod 666 /dev/uinput'。")
|
| 49 |
+
return None
|
| 50 |
+
except Exception as err:
|
| 51 |
+
print(f"❌ 初始化失败: {err}")
|
| 52 |
+
return None
|
| 53 |
+
|
| 54 |
+
ui = None
|
| 55 |
+
|
| 56 |
+
def do_action(cmd):
|
| 57 |
+
global ui
|
| 58 |
+
# 1. 执行 Pro Tools 增强逻辑 (Bridge)
|
| 59 |
+
pt_bridge.execute(cmd)
|
| 60 |
+
|
| 61 |
+
# 2. 执行 Kdenlive / Linux 通用逻辑 (evdev)
|
| 62 |
+
if not ui:
|
| 63 |
+
print("⚠️ 虚拟硬件未初始化,跳过 HID 模拟。")
|
| 64 |
+
else:
|
| 65 |
+
skills = load_skills()
|
| 66 |
+
for key, keys_list in skills.items():
|
| 67 |
+
if key in cmd:
|
| 68 |
+
# 执行物理按键序列
|
| 69 |
+
for k in keys_list:
|
| 70 |
+
key_code = getattr(e, k, None)
|
| 71 |
+
if key_code is not None:
|
| 72 |
+
ui.write(e.EV_KEY, key_code, 1)
|
| 73 |
+
# 反向释放
|
| 74 |
+
for k in reversed(keys_list):
|
| 75 |
+
key_code = getattr(e, k, None)
|
| 76 |
+
if key_code is not None:
|
| 77 |
+
ui.write(e.EV_KEY, key_code, 0)
|
| 78 |
+
ui.syn()
|
| 79 |
+
|
| 80 |
+
# 特殊合成逻辑:剃刀点击
|
| 81 |
+
if any(word in key for word in ["剃刀", "剪断", "切断"]):
|
| 82 |
+
time.sleep(0.05)
|
| 83 |
+
pyautogui.click()
|
| 84 |
+
|
| 85 |
+
# 本地中文语音反馈
|
| 86 |
+
os.system(f'spd-say "{key}已执行" &')
|
| 87 |
+
|
| 88 |
+
# 3. 灵魂输出:品牌版权
|
| 89 |
+
print(f"© 2026 神思庭 (AIS) - 指令已处理: {cmd}")
|
| 90 |
+
|
| 91 |
+
HTML_TEMPLATE = """
|
| 92 |
+
<!DOCTYPE html>
|
| 93 |
+
<html>
|
| 94 |
+
<head>
|
| 95 |
+
<meta charset="utf-8">
|
| 96 |
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
| 97 |
+
<title>神思庭控制终端</title>
|
| 98 |
+
<style>
|
| 99 |
+
body { font-family: "Microsoft YaHei", -apple-system, sans-serif; text-align: center; padding: 20px; background: #121212; color: #fff; margin: 0; }
|
| 100 |
+
.logo { max-width: 120px; margin-top: 30px; border-radius: 20px; box-shadow: 0 0 20px rgba(7, 193, 96, 0.4); border: 1px solid #1a1a1a; }
|
| 101 |
+
h1 { color: #07c160; letter-spacing: 4px; font-weight: 300; margin-top: 25px; }
|
| 102 |
+
.status-bar { color: #07c160; font-weight: bold; font-size: 18px; margin: 15px 0; letter-spacing: 2px; }
|
| 103 |
+
.hint { color: #666; font-size: 14px; margin-bottom: 30px; }
|
| 104 |
+
#voice_input {
|
| 105 |
+
width: 90%;
|
| 106 |
+
box-sizing: border-box;
|
| 107 |
+
padding: 22px;
|
| 108 |
+
font-size: 20px;
|
| 109 |
+
border-radius: 18px;
|
| 110 |
+
border: 1px solid #333;
|
| 111 |
+
background: #000;
|
| 112 |
+
color: #fff;
|
| 113 |
+
margin-bottom: 25px;
|
| 114 |
+
outline: none;
|
| 115 |
+
box-shadow: 0 10px 40px rgba(0,0,0,0.8);
|
| 116 |
+
}
|
| 117 |
+
#voice_input:focus { border-color: #07c160; }
|
| 118 |
+
.copyright { color: #444; font-size: 11px; margin-top: 50px; border-top: 1px solid #1a1a1a; padding-top: 20px; line-height: 1.8; }
|
| 119 |
+
.copyright a { color: #444; text-decoration: none; }
|
| 120 |
+
</style>
|
| 121 |
+
</head>
|
| 122 |
+
<body>
|
| 123 |
+
<img src="/logo" class="logo" alt="Shensist Logo">
|
| 124 |
+
<h1>神思庭控制终端</h1>
|
| 125 |
+
<div class="status-bar">● 语音技能已就绪</div>
|
| 126 |
+
<p class="hint">直接说出指令(如:播放、剃刀、撤销...)</p>
|
| 127 |
+
|
| 128 |
+
<input type="text" id="voice_input" oninput="sendCmd()" placeholder="等待语音输入..." autofocus>
|
| 129 |
+
|
| 130 |
+
<script>
|
| 131 |
+
let timer = null;
|
| 132 |
+
function sendCmd() {
|
| 133 |
+
let val = document.getElementById('voice_input').value;
|
| 134 |
+
if(val.length >= 1) {
|
| 135 |
+
fetch('/exec?msg=' + encodeURIComponent(val));
|
| 136 |
+
clearTimeout(timer);
|
| 137 |
+
timer = setTimeout(() => {
|
| 138 |
+
document.getElementById('voice_input').value = '';
|
| 139 |
+
}, 1000);
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
</script>
|
| 143 |
+
<div class="shensist-footer">
|
| 144 |
+
<hr style="border: 0; border-top: 1px solid #333; margin: 40px 0 20px;">
|
| 145 |
+
<p style="font-weight: bold; color: #07c160; margin-bottom: 5px;">神思庭艺术智能工作室 (AIS)</p>
|
| 146 |
+
<p style="font-size: 11px; color: #666; line-height: 1.6;">
|
| 147 |
+
© 2026 Shensist-Matrix Project. <br>
|
| 148 |
+
100+ 专业 Skills 引擎受专利保护 <br>
|
| 149 |
+
唯一官方发布渠道:<a href="https://shensist.top/" style="color: #888; text-decoration: none;">shensist.top</a>
|
| 150 |
+
</p>
|
| 151 |
+
</div>
|
| 152 |
+
</body>
|
| 153 |
+
</html>
|
| 154 |
+
"""
|
| 155 |
+
|
| 156 |
+
@app.route('/')
|
| 157 |
+
def index(): return render_template_string(HTML_TEMPLATE)
|
| 158 |
+
|
| 159 |
+
@app.route('/logo')
|
| 160 |
+
def logo(): return send_from_directory(BASE_DIR, 'logo_ts.webp')
|
| 161 |
+
|
| 162 |
+
@app.route('/exec')
|
| 163 |
+
def execute():
|
| 164 |
+
msg = request.args.get('msg', '')
|
| 165 |
+
if msg: do_action(msg)
|
| 166 |
+
return "OK"
|
| 167 |
+
|
| 168 |
+
if __name__ == '__main__':
|
| 169 |
+
ui = init_ui()
|
| 170 |
+
if ui:
|
| 171 |
+
print("🏛️ [Shensist-AirEye] 神思庭终端已上线。")
|
| 172 |
+
else:
|
| 173 |
+
print("🏛️ [Shensist-AirEye] 终端警告: 虚拟硬件模拟未就绪。")
|
| 174 |
+
app.run(host='0.0.0.0', port=5000)
|
__pycache__/Shensist_PT_Bridge.cpython-313.pyc
ADDED
|
Binary file (2.31 kB). View file
|
|
|
__pycache__/Shensist_Web_Master.cpython-313.pyc
ADDED
|
Binary file (8.26 kB). View file
|
|
|
cmd.txt
ADDED
|
File without changes
|
index.html
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="zh-CN">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>神思AirEye (Shensist-AIS) | 官方使用指南</title>
|
| 7 |
+
<style>
|
| 8 |
+
:root { --shensist-green: #07c160; --bg-black: #0a0a0a; --card-bg: #161616; --sky-cyan: #00FFFF; }
|
| 9 |
+
body { background: var(--bg-black); color: #ddd; font-family: "PingFang SC", sans-serif; line-height: 1.6; margin: 0; padding: 0; }
|
| 10 |
+
.container { max-width: 800px; margin: 0 auto; padding: 40px 20px; }
|
| 11 |
+
header { text-align: center; padding: 60px 0; }
|
| 12 |
+
.logo { width: 80px; height: 80px; border-radius: 20px; box-shadow: 0 0 20px rgba(7,193,96,0.3); margin-bottom: 20px; }
|
| 13 |
+
h1 { color: var(--shensist-green); font-weight: 300; letter-spacing: 4px; }
|
| 14 |
+
h2 { color: var(--shensist-green); border-left: 4px solid var(--shensist-green); padding-left: 15px; margin-top: 40px; }
|
| 15 |
+
.step-card { background: var(--card-bg); border-radius: 15px; padding: 25px; margin: 20px 0; border: 1px solid #222; }
|
| 16 |
+
.btn-group { display: flex; gap: 15px; flex-wrap: wrap; margin-top: 20px; }
|
| 17 |
+
.btn { padding: 12px 25px; border-radius: 8px; text-decoration: none; font-weight: bold; transition: 0.3s; font-size: 0.9em; }
|
| 18 |
+
.btn-primary { background: var(--shensist-green); color: #fff; }
|
| 19 |
+
.btn-primary:hover { box-shadow: 0 0 15px var(--shensist-green); opacity: 0.9; }
|
| 20 |
+
.btn-secondary { background: #333; color: #ccc; }
|
| 21 |
+
code { background: #000; color: #07c160; padding: 2px 6px; border-radius: 4px; }
|
| 22 |
+
footer { text-align: center; padding: 60px 0; color: #444; font-size: 0.8em; border-top: 1px solid #222; }
|
| 23 |
+
</style>
|
| 24 |
+
</head>
|
| 25 |
+
<body>
|
| 26 |
+
|
| 27 |
+
<div class="container">
|
| 28 |
+
<header>
|
| 29 |
+
<img src="logo_ts.webp" class="logo" alt="AIS">
|
| 30 |
+
<h1>神思AirEye</h1>
|
| 31 |
+
<p style="color:#666">赋予智能体场景灵魂 · 2026 跨时空控制矩阵</p>
|
| 32 |
+
</header>
|
| 33 |
+
|
| 34 |
+
<section>
|
| 35 |
+
<h2>第一步:获取执行大脑 (v2.6.5 Final)</h2>
|
| 36 |
+
<div class="step-card">
|
| 37 |
+
<strong>下载并运行神思AirEye控制终端。</strong>
|
| 38 |
+
<p>本程序负责在你的电脑上接收指令并操作软件(如 <strong>Cubase</strong>, Pro Tools, Kdenlive)。</p>
|
| 39 |
+
<div class="btn-group">
|
| 40 |
+
<a href="https://github.com/jinv2/Shensist-AirEye-Terminal/raw/main/dist/windows/Shensist_Terminal_Pro.exe" class="btn btn-primary">🏛️ 下载 Windows 版 (.exe)</a>
|
| 41 |
+
<a href="https://github.com/jinv2/Shensist-AirEye-Terminal/raw/main/dist/macos/Shensist_Terminal_Mac.dmg" class="btn btn-primary">🏛️ 下载 macOS 版 (.dmg)</a>
|
| 42 |
+
<a href="https://github.com/jinv2/Shensist-AirEye-Terminal/raw/main/dist/linux/Shensist_Terminal_Core.tar.gz" class="btn btn-primary">🏛️ 下载 Linux 版 (.tar.gz)</a>
|
| 43 |
+
</div>
|
| 44 |
+
</div>
|
| 45 |
+
</section>
|
| 46 |
+
|
| 47 |
+
<section>
|
| 48 |
+
<h2>第二步:指挥方式选择</h2>
|
| 49 |
+
<div class="step-card">
|
| 50 |
+
<strong>A. 近场指挥 (零延迟)</strong>
|
| 51 |
+
<p>在本地浏览器输入:<code>http://localhost:7860</code></p>
|
| 52 |
+
</div>
|
| 53 |
+
<div class="step-card">
|
| 54 |
+
<strong>B. 跨空指挥 (iPhone 13 / 微信)</strong>
|
| 55 |
+
<p>通过云端行星中继,实现全球指令投射:</p>
|
| 56 |
+
<div class="btn-group">
|
| 57 |
+
<a href="https://huggingface.co/spaces/jinv2/Shensist-Planet14" class="btn btn-secondary">🌐 进入 14 号行星远程面板</a>
|
| 58 |
+
</div>
|
| 59 |
+
</div>
|
| 60 |
+
</section>
|
| 61 |
+
|
| 62 |
+
<footer>
|
| 63 |
+
<p>© 2026 Shensist Art Intelligence Studio (AIS). <br>
|
| 64 |
+
赋予智能体场景灵魂:<a href="https://shensist.top" style="color:#07c160">shensist.top</a></p>
|
| 65 |
+
</footer>
|
| 66 |
+
</div>
|
| 67 |
+
|
| 68 |
+
</body>
|
| 69 |
+
</html>
|
logo_ts.webp
ADDED
|
requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
flask
|
| 2 |
+
flask-cors
|
| 3 |
+
gunicorn
|
scripts/check_perms.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import stat
|
| 3 |
+
|
| 4 |
+
def check_uinput():
|
| 5 |
+
path = "/dev/uinput"
|
| 6 |
+
print(f"--- Checking {path} ---")
|
| 7 |
+
|
| 8 |
+
if not os.path.exists(path):
|
| 9 |
+
print(f"❌ {path} does not exist.")
|
| 10 |
+
return
|
| 11 |
+
|
| 12 |
+
# Check stats
|
| 13 |
+
st = os.stat(path)
|
| 14 |
+
print(f"Mode: {oct(st.st_mode)}")
|
| 15 |
+
print(f"Owner UID: {st.st_uid}")
|
| 16 |
+
print(f"Group GID: {st.st_gid}")
|
| 17 |
+
|
| 18 |
+
# Check current user/groups
|
| 19 |
+
print(f"\nCurrent User UID: {os.getuid()}")
|
| 20 |
+
print(f"Current Groups GIDs: {os.getgroups()}")
|
| 21 |
+
|
| 22 |
+
# Try opening for writing
|
| 23 |
+
try:
|
| 24 |
+
with open(path, 'w') as f:
|
| 25 |
+
print(f"✅ Successfully opened {path} for writing.")
|
| 26 |
+
except PermissionError:
|
| 27 |
+
print(f"❌ Permission Denied: Cannot open {path} for writing.")
|
| 28 |
+
except Exception as e:
|
| 29 |
+
print(f"❌ Error: {e}")
|
| 30 |
+
|
| 31 |
+
if __name__ == "__main__":
|
| 32 |
+
check_uinput()
|
skills/复制/config.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"action": "hotkey", "key": ["ctrl", "c"]}
|
skills/粘贴/config.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"action": "hotkey", "key": ["ctrl", "v"]}
|
skills_map.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"播放": ["KEY_SPACE"],
|
| 3 |
+
"录音": ["KEY_LEFTCTRL", "KEY_SPACE"],
|
| 4 |
+
"切断": ["KEY_LEFTCTRL", "KEY_E"],
|
| 5 |
+
"剃刀": ["KEY_X"],
|
| 6 |
+
"混音切换": ["KEY_LEFTCTRL", "KEY_EQUAL"],
|
| 7 |
+
"新建轨道": ["KEY_LEFTCTRL", "KEY_LEFTSHIFT", "KEY_N"],
|
| 8 |
+
"标记": ["KEY_ENTER"],
|
| 9 |
+
"撤销": ["KEY_LEFTCTRL", "KEY_Z"]
|
| 10 |
+
}
|
test.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
dummy
|
voice_agent.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import vosk
|
| 2 |
+
import pyaudio
|
| 3 |
+
import json
|
| 4 |
+
import pyautogui
|
| 5 |
+
import os
|
| 6 |
+
import cv2
|
| 7 |
+
import numpy as np
|
| 8 |
+
|
| 9 |
+
class ShensistAgent:
|
| 10 |
+
def __init__(self, skills_path="./skills"):
|
| 11 |
+
self.skills_path = skills_path
|
| 12 |
+
self.skills = self.load_skills()
|
| 13 |
+
print("🚀 Shensist-Agent 已启动,正在扫描工程...")
|
| 14 |
+
|
| 15 |
+
def load_skills(self):
|
| 16 |
+
# 扫描子文件夹,实现无缝接轨制作 [cite: 7]
|
| 17 |
+
if not os.path.exists(self.skills_path):
|
| 18 |
+
os.makedirs(self.skills_path)
|
| 19 |
+
return [d for d in os.listdir(self.skills_path) if os.path.isdir(os.path.join(self.skills_path, d))]
|
| 20 |
+
|
| 21 |
+
def execute_skill(self, skill_name):
|
| 22 |
+
skill_dir = os.path.join(self.skills_path, skill_name)
|
| 23 |
+
anchor_path = f"{skill_dir}/anchor.png"
|
| 24 |
+
if not os.path.exists(anchor_path):
|
| 25 |
+
print(f"❌ 技能 {skill_name} 缺少 anchor.png")
|
| 26 |
+
return
|
| 27 |
+
|
| 28 |
+
anchor = cv2.imread(anchor_path)
|
| 29 |
+
# 屏幕匹配逻辑 [cite: 10]
|
| 30 |
+
screen = pyautogui.screenshot()
|
| 31 |
+
screen_np = cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2BGR)
|
| 32 |
+
result = cv2.matchTemplate(screen_np, anchor, cv2.TM_CCOEFF_NORMED)
|
| 33 |
+
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
| 34 |
+
|
| 35 |
+
if max_val > 0.8:
|
| 36 |
+
pyautogui.moveTo(max_loc[0], max_loc[1])
|
| 37 |
+
pyautogui.click()
|
| 38 |
+
print(f"✅ 执行成功: {skill_name}")
|
| 39 |
+
else:
|
| 40 |
+
print(f"❌ 未在当前屏幕找到 {skill_name} 的操作锚点")
|
| 41 |
+
|
| 42 |
+
# 初始化语音监听与技能匹配逻辑...
|
| 43 |
+
def main():
|
| 44 |
+
agent = ShensistAgent("./skills")
|
| 45 |
+
print(f"当前识别到的技能: {agent.skills}")
|
| 46 |
+
|
| 47 |
+
if __name__ == "__main__":
|
| 48 |
+
main()
|