🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

Oopz 语音分身 Kingyibin/dsh-oopz-voice

DeepSeek Harness
Kingyibin4 天前有提交已提供中文文档扫描:含敏感能力

让智能体进入 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 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 4 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 11 处,展示前 11 条)
  • 执行外部命令来自配置/变量
    lib/index.js:66
    const p = spawn(nodeRt.file, [script, ...args], {
  • 发起网络请求
    lib/client.js:26
    fetch(B + p, { cache: 'no-store' })
  • 发起网络请求
    lib/client.js:30
    fetch(B + p, {
  • 读取密钥环境变量
    lib/secret.js:39
    return (process.env.DEEPSEEK_API_KEY || '').trim() || readSecret().deepseekApiKey
  • 执行外部命令来自配置/变量
    lib/detect.js:18
    execFile(cmd, args, { timeout, windowsHide: true }, (err, stdout, stderr) => {
  • 执行外部命令来自配置/变量
    lib/node-runtime.js:19
    const r = spawnSync(file, ['-e', 'require("fs").writeFileSync(process.argv[1],process.versions.node)', proof], {
  • 执行外部命令来自配置/变量
    lib/runtime.js:110
    this.proc = spawn(nodeRt.file, args, {
  • 读取密钥环境变量
    runtime/brain.mjs:28
    const API_KEY = process.env.DEEPSEEK_API_KEY || ENV.DEEPSEEK_API_KEY || ''
  • 发起网络请求
    runtime/brain.mjs:171
    const res = await fetch(`${this.base}/chat/completions`, {
  • 执行外部命令来自配置/变量
    runtime/bridge.mjs:82
    this.proc = spawn(PY, [path.join(HERE, script)], {
  • 发起网络请求
    runtime/bridge.mjs:243
    await this.bot.rest.transport.request(
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

让 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
预览分享卡片长什么样 ↓Kingyibin/dsh-oopz-voice
分享 · DeepSeek Harness Hub
Kingyibin/dsh-oopz-voice

让智能体进入 Oopz 语音房,像真人一样听你说并开口回应

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部