让智能体进入 Oopz 语音房,像真人一样听你说并开口回应
29.8/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Kingyibin/dsh-oopz-voice该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
让 DSH 里的 agent 真的进 Oopz 语音房开口说话:本地 ASR + 大模型 + 本地 TTS + Agora 推流,感知延迟约 1.6 秒。别人听到的是一个真人,不是机器人。
README
由 DeepSeek 最新模型翻译生成dsh-oopz-voice
让 DSH 里的智能体真的进 Oopz 语音房开口说话。
这不是「语音助手」。它有耳朵(本地 ASR)、有嘴(本地 TTS)、有脑子(大模型),在语音房里别人听到的是一个说话带停顿、会插话、该沉默时会沉默的人 —— 不是一段播报。
别人的声音 ──▶ 能量 VAD ──▶ SenseVoice ASR ──▶ 大模型 ──▶ VITS TTS ──▶ Agora 推流
(Agora) (~50ms) (86–137ms) (~500ms) (55ms/字) (48kHz)
感知延迟大约 1.6 秒(说完话到听见回应)。这个数字是物理下限堆出来的,不是没优化。
它做什么
- 进房:进任意有权限的 Oopz 语音频道,长时间挂着不掉(心跳续命,实测 7 分 41 秒零掉线)
- 听:只处理「有人在说话」的那段,按静音断句;太短的一声「哦」直接丢
- 想:把听到的话交给它自己的大模型,配一份你自己写的人格
- 说:本地合成人声,推到语音房里
- 让位:别人在说话时它会停——不是一有声音就闭嘴,而是对方持续说够了才让(否则永远被打断)
- 被打断后补听:让位期间听到的内容不会丢,说完这句再接回来
它不做什么
- 不做回声消除。
展开完整文档(README 剩余 1 节)
dsh-oopz-voice
让 DSH 里的智能体真的进 Oopz 语音房开口说话。
这不是「语音助手」。它有耳朵(本地 ASR)、有嘴(本地 TTS)、有脑子(大模型),在语音房里别人听到的是一个说话带停顿、会插话、该沉默时会沉默的人 —— 不是一段播报。
别人的声音 ──▶ 能量 VAD ──▶ SenseVoice ASR ──▶ 大模型 ──▶ VITS TTS ──▶ Agora 推流
(Agora) (~50ms) (86–137ms) (~500ms) (55ms/字) (48kHz)
感知延迟大约 1.6 秒(说完话到听见回应)。这个数字是物理下限堆出来的,不是没优化。
它做什么
- 进房:进任意有权限的 Oopz 语音频道,长时间挂着不掉(心跳续命,实测 7 分 41 秒零掉线)
- 听:只处理「有人在说话」的那段,按静音断句;太短的一声「哦」直接丢
- 想:把听到的话交给它自己的大模型,配一份你自己写的人格
- 说:本地合成人声,推到语音房里
- 让位:别人在说话时它会停——不是一有声音就闭嘴,而是对方持续说够了才让(否则永远被打断)
- 被打断后补听:让位期间听到的内容不会丢,说完这句再接回来
它不做什么
- 不做回声消除。它靠让位避让,不靠 AEC
- 不处理英文(见「已知限制」)
- 不是官方 API 集成 —— 走的是 Oopz 私有协议,见「合规」
前置条件
| 需要 | 说明 |
| DSH | dsh --profile web 能跑起来 |
| Node 20+ | 运行时靠 puppeteer-core 起 Chrome |
| Python 3.10+ | 装 numpy 和 sherpa-onnx:python -m pip install numpy sherpa-onnx |
| 真 Chrome / Edge | ⚠️ 不能是 headless shell。我们要 WebAudio + Agora Web SDK,headless shell 里没有这套 |
| DeepSeek API Key | 或任何 OpenAI 兼容接口 |
| Oopz 账号 | 手机号 + 密码,且有权限进目标语音频道 |
模型不用自己找,设置页点「下载模型」会从 HuggingFace 镜像拉(约 300MB)。
安装
dsh plugin --profile desktop add dsh-oopz-voice
从源码 / 本地开发:
git clone https://github.com/Kingyibin/dsh-oopz-voice.git
cd dsh-oopz-voice
npm install
dsh plugin --profile desktop add "link:$(pwd)"
装完重启 DSH,设置里会多一项 语音房。
五步跑起来
1. 登录 → 填 Oopz 手机号密码。密码只在这一次请求里用,不落盘、不回显。
凭据存 <DSH_HOME>/oopz-voice/cred.json,只在本机。
2. 填 API Key → 保存。
3. 下载模型 → 约 300MB,看进度条。
4. 读我的域 → 会自动列出你能看到的域和语音频道,并标出每个频道里有几个人(选个有人的)。
5. 回到顶部点 进房。第一次要起两个本地模型,10–25 秒。状态变「在房里」就成了。
顶部那七行「差什么」是体检,全绿再进房。哪行红着,它下面会直接写该装什么 / 该点哪里。
设置页每一项
展开
落点
- 域 / 语音频道:进哪个房间。「读我的域」列出的频道会带人数和昵称——有人才有的聊。
音频
- Python / 浏览器:留空自动找。找不到就填绝对路径。
- ASR 模型目录 / TTS 模型目录:留空用数据目录下的默认位置。
- 语速:0.95 偏慢、更像人;1.0 是模型原速。
- 线程数:TTS 是逐字线性合成的,加线程只能压一点点。
大脑
- 接口地址 + 模型:任何 OpenAI 兼容服务都行。
- 温度:0.95 适合闲聊。太高会开始胡说。
- 记住几句:默认 6。语音里历史别拉长——越长首字越慢,还会绕回去讲旧事。
- 软切句门槛:默认 7 字。越小开口越快,太大像念稿。
人格 留空就用 runtime/persona.example.md。写了以你的为准。
建议只写「它是谁、怎么说话、什么不干」,别写任务清单 —— 那是派活。
怎么说话
- 开口概率:被叫到时真的开口的概率。留一点「懒得理」的余地,1.0 反而假。
- 说完到下一句的间隔:默认 300ms。原来设 1200ms,结果说两句就硬等 1.2 秒,一顿一顿的。
- 只听不说:调 ASR 用,能听见不开口。
- 只连不进房:自检用,验证登录和协议,不真的占频道。
- VAD 参数:判断「在说话」的能量门槛。房里底噪大就往上调。
它是怎么做到的
展开(这部分是踩出来的,不是读文档读来的)
1. 登录:纯 HTTP,不用客户端
POST /client/v1/login/v2/login:
- 密码用 RSA-OAEP(SHA256) 加密
- 签名是 RSA-SHA256(MD5(path + body) + oopzTime)
- 两把内置密钥藏在客户端里:反转 → base64url → XOR → zlib
2. Agora appId 藏在 token 里
enter 接口返回的 data.appId 恒为 0,不能用。
真值在 supplierSign 字段里 —— token 是 "007" + base64(zlib(payload)), zlib.inflateSync 之后按小端读出 appId / roomId / uid。
代码里 rtc.appId 留空就会自动解,不用手填。
3. 进房之后成员会「过期」
POST /area/v2/channel/enter 是幂等的,可以反复发。
成员寿命只有 60–80 秒——不发续期心跳就会从频道里消失。
官方 oopz-sdk 的 services/voice.js 是个空壳:startIdentityHeartbeat() 没有实现,
join() 返回假 token。所以这部分是自研的:每 20 秒重发一次 enter,实测 7 分 41 秒零掉线。
4. 音频:headless Chrome + Agora Web SDK
Node 里没有 WebRTC,所以起一个 headless Chrome 跑 Agora Web SDK:
- createClient({ mode: 'live', codec: 'vp8' }) + setClientRole('host')
- 用 createCustomAudioTrack 推自己合成的 PCM —— 这会绕过 Agora 的 3A (降噪 / 回声消除 / 自动增益)。好处是不被处理坏,代价是底噪得自己管。
- ⚠️ connection-state-changed 事件在 live + host 下不触发。
必须直接读 client.connectionState 属性,否则看门狗会误判断线、把自己踢出房间。
5. 多人同时说话:按 uid 分桶,不用声纹
Agora 给每个远端用户一路独立的音频轨,回调里本来就带着 uid。
所以「谁在说话」不需要声纹——分桶就够了。语音房默认一个账号一个人,uid 就是身份。
⚠️ 但第一版把这事写错了:全场只有一个 VAD 实例,所有 uid 的 PCM 都倒进同一个桶。
后果是两个人同时说话会被拼成一句,ASR 出来是乱码,说话人还会记成最后一块的 uid。
sim/repro-mix.mjs 可以复现:
A 说 0–700ms,B 说 300–900ms 【坏】出一句 1500ms,里面是 AAA+BBB+AAA+BBB 交替拼接,归属记成 null 【好】A 一句(有声 700ms)、B 一句(有声 600ms),各自归属
现在 VadBank 每人一个 Vad,另外补了两件事:
- 重叠判定:一句出来时若别人还在说,会明确告诉她「XX 也在说 —— 你只可能听清刚才那句」。
不告诉她,她会把两个人的意思缝成一个人的。
- 短句判定改用「有声时长」。原来用的是「开口到收句」,里面含 650ms 静音尾巴,所以 minMs 从来没生效过(任何句子都超过 450ms)。同理,可信度守卫的「字/秒」也一直算错,会把听清的句子误判成没听清。
什么时候才真的需要声纹:一个账号两个人轮流说话(实测遇到过,对方还拿这个考它)。
这种情况要上 CAM++(3D-Speaker,28MB ONNX,CPU 上一次提取 30–50ms,同一人相似度 0.85–0.96、不同人 0.35–0.65,阈值取 0.77)。本版没做——加它要改记忆的主键(从 uid 变成声纹簇),代价不小,等真有需求再说。
6. 记忆:本地三层,说话路径零 IO
语音场景最怕记忆把延迟拖垮。但完全不记又不行——进程一重启就失忆,人会立刻觉得「这玩意儿不认识我」。折中是读内存、写攒批:
| 层 | 文件 | 内容 |
| 人物档案 | memory/people.json | 每个账号:名字、第一次见、聊过多少句、最近说过的原话 |
| 事实库 | memory/facts.json | 会淡忘的事实。半衰期 30 天,每次最多注入 6 条 / 800 字 |
| 流水 | memory/turns/<日期>.jsonl | 当天所有听见和说出的句子 |
- 启动时 load() 一次,之后每轮只读内存,不碰磁盘
- 改动标脏,15 秒落盘,退出时强制 flush()
- 事实抽取走规则(不做额外模型调用,省 300ms 和一分钱),存成第三人称
- 事实打分:重要度 × 0.5^(天数/30) × 相关性 × 命中加成,跟当前说话人相关的加权 1.35
拼进 prompt 的样子:
你现在在跟谁说话他叫「阿青」,你们 3 天前第一次说话,到现在聊过 42 句。
关于他你知道这些(别当成新信息再问一遍,就当本来就知道):
- 他叫阿青,他在武汉上班(2026-10-28)
- 他养了只猫,叫豆豆,特别胖(2026-10-30)他最近说过的:
- 「昨天加班到两点,困死了。」
实测:加记忆之后首字中位数 581ms,跟加之前(525–731ms)没差别。
「进程重启」后仍能答出「阿青嘛,武汉」。
如果配置里填了 memory.diary,还会读那段日记——她就能顺口提「我今天看了个修糖果机的视频」,而不是每句话都只对眼前这句做反应。
7. 延迟预算
| 环节 | 耗时 |
| 静音判定 | 650ms(等对方说完,省不掉) |
| ASR | 86–137ms |
| 大模型首字 | ~500ms(物理下限,砍人格只省 90ms,不划算) |
| TTS | 55ms/字,线性 |
| 推流 + 对方听到 | ~100ms |
| 合计 | ~1.6s |
TTS 没有并行空间 —— 它是逐字合成的,13 个字就是 629ms。所以句子越短开口越快,这也是 软切句门槛 存在的理由。
踩过的坑
这一节可能是整个仓库最值钱的部分。
展开
音量对了,但对方说「声音嘈杂」 不是音量问题,是底噪。TTS 原始输出有 −40dBFS 的底噪、峰值只留 −0.9dBFS。
加了 20ms 分帧的噪声门(−38dB 门限、80ms 平滑)+ 峰值压到 −3.0dBFS + 48kHz 链路之后,底噪降到 −57~−61dBFS。感知上的「吵」是底噪,不是响度。
她把旁白念出来了 模型输出了「(没说话,尾巴在水里轻轻摆了一下)」,TTS 老老实实念了。
正则切掉所有括号内容,整句纯旁白当沉默处理。
「滚」被听成「我」,她回「哦,你俩认识啊」 ASR 会编。加了可信度守卫:音频超过 0.8 秒、但字数/秒 < 2.2 → 判定「没听清」,只许问「啊?」「没听清」。宁可显得耳背,也不要答非所问。
「哈」被听成「烟」,她回「烟啊,我闻着呛」 极短句的 ASR 天生不可靠。策略是把 history 里的原文换成占位符——让她看不见听错的字,只知道自己「应了一声」。
说两句就一顿一顿 minReplyGapMs = 1200 被写在每句之前。改成回合开始计一次、降到 300ms,句间只留 70–190ms 随机气口。
每句都是同一个调 speed 固定、音量固定 → 听着像机器。
现在每句 speed 在 0.93–1.00 之间随机、音量 ±3.5% 浮动。
TTS 遇到中文引号就跳过 “ ” 在模型词表里是 OOV,合成时会静默跳过。clean() 里直接剔除。
⚠️ 已知限制(诚实的部分)
这些是实测结论,不是没调好:
| 限制 | 原因 |
| 声音有点闷 | TTS 模型只有 16kHz。电话带宽本身就容不下通透感,换模型才能解决 |
| 听写的句子读起来像机器翻的 | 不是模型旧 —— SenseVoice 中文 CER 7.81%,比 Whisper-large-v3 的 20% 好得多。真相是它非自回归,解码时没有语言模型参与,不会用「这句话怎么说才通顺」的先验纠错。「武汉」永远听成「五汉」,「护肤」永远听成「户完」。要根治只能换 LLM-ASR(Fun-ASR-Nano:SenseVoice 编码器 + Qwen3-0.6B 解码),代价 +950MB 模型、每句多约 200ms |
| 英文词全丢 | SenseVoice 中文版的 token 表里没有英文词。混说「GPU」这种会念成中文或跳过 |
| 极短句经常听错 | 一两字音频信息量太少,ASR 只能返回空。现在当「应了一声」当语气信号,不再静默吞掉 |
| 首字最快 ~500ms | 完整人格 prompt 是 525–731ms,砍成极短 prompt 只到 480–573ms。差 90ms,不值得 |
| 一个账号两个人说话分不清 | 认的是 uid,不是声音。要区分得加声纹(CAM++),当前没做 |
| 音乐/纯噪声会被当成说话 | 能量 VAD 只认「有声音」。真人说话能被分到各自的桶,但音乐会被一起收进来 |
| 协议可能随时失效 | 走的是 Oopz 私有协议,客户端升级可能改签名或加密方式 |
隐私
- DeepSeek Key:单独存 <DSH_HOME>/oopz-voice/secret.json,API 永不回显
- Oopz 凭据:存 cred.json,只在本机,不进配置文件、不进 git(.gitignore 已挡)
- 音频:ASR / TTS 全在本地跑。只有识别出来的文字会发到大模型接口
- 所有 HTTP 路由都过 DSH 的 requestRejection 信任栅栏 —— 端口在回环地址上,但浏览器里任何一个网页都能往回环发请求,不设栅栏等于把「启动进程」这个能力开放给任意页面
合规
本项目通过逆向分析 Oopz 客户端实现语音房接入,不是 Oopz 官方提供的能力。
- 仅用于你自己有权限的账号和频道
- 不要在别人的房间里用、不要用来刷屏或骚扰
- 语音房里的其他人不知道说话的是程序 —— 请自行判断这在你的场景里是否合适
- 因使用本插件导致的账号封禁、协议失效,作者不负责
目录
lib/
index.js 宿主半边:路由、起停、体检、oopz_voice 工具 client.js 设置页(DSH 设置 → 语音房) config.js 配置单一真相源 runtime.js 子进程生命周期 + @@VOICE 事件解析 detect.js Python / Chrome / 模型 探测 secret.js 密钥单存 node-runtime.js 找可用的 node(躲开桌面端 process.execPath 是 Harness.exe 的坑) agora.js 从 token 里解 appId runtime/ bridge.mjs 主循环:Oopz 协议 + 编排 + 排队 vad.mjs 多路 VAD:每人一个桶,重叠判定(v1.1.0) memory.mjs 记忆三层:人物档案 / 淡忘事实 / 流水(v1.1.0) brain.mjs 大脑:切句、防重复、可信度守卫 asr.py SenseVoice(sherpa-onnx int8) tts.py VITS 中文(sherpa-onnx)+ 噪声门 agora-agent.html headless Chrome 里的音频桥 persona.example.md 示例人格 tools/ login.mjs 登录并写凭据 rooms.mjs 列出域 / 频道 / 人数 get-models.mjs 下模型(走 HF 镜像)
<DSH_HOME>/oopz-voice/memory/ 下会生成:
people.json 每个账号的档案 facts.json 会淡忘的事实 turns/日.jsonl 当天流水
License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Kingyibin/dsh-oopz-voice
让智能体进入 Oopz 语音房,像真人一样听你说并开口回应
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,270已汉化DSH
70.8
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。