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

连续语音对话 ggfgfgf-on/dsh-voice-dialog

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

DeepSeek Harness 的连续语音对话:一个麦克风,自动朗读回复,轻声插话即可打断

31.3/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ggfgfgf-on/dsh-voice-dialog
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · chat
装得上吗
实装验证未通过(runtime_add_failed),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

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

验证判据与等级说明 →
⚠︎ 实装验证未通过(runtime_add_failed · 2026/10/30) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 116 处,展示前 63 条)
  • 发起网络请求
    lib/index.js:10265
    request = https.request(options);
  • 发起网络请求
    lib/index.js:10267
    request = http.request(options);
  • 发起网络请求
    lib/index.js:11691
    var request = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse);
  • 发起网络请求
    lib/index.js:11824
    var wrappedRequest = wrappedProtocol.request(input, options, callback);
  • 发起网络请求
    lib/index.js:15205
    const req = session.request(http2Headers);
  • 发起网络请求
    lib/index.js:15580
    req = transport.request(options, function handleResponse(res) {
  • 读取本地文件
    lib/index.js:25965
    size = statSync(PLAN_LOG_PATH).size;
  • 写入本地文件
    lib/index.js:25969
    if (size > MAX_BYTES) writeFileSync(PLAN_LOG_PATH, "");
  • 写入本地文件
    lib/index.js:25970
    appendFileSync(PLAN_LOG_PATH, JSON.stringify(item) + "\n");
  • 读取本地文件
    lib/index.js:26094
    size = statSync2(RECORD_LOG_PATH).size;
  • 写入本地文件
    lib/index.js:26098
    if (size > MAX_BYTES2) writeFileSync2(RECORD_LOG_PATH, "");
  • 写入本地文件
    lib/index.js:26099
    appendFileSync2(RECORD_LOG_PATH, JSON.stringify(item) + "\n");
  • 读取本地文件
    lib/index.js:26467
    if (statSync3(DECISION_LOG).size > DECISION_LOG_LIMIT) return;
  • 写入本地文件
    lib/index.js:26470
    appendFileSync3(DECISION_LOG, JSON.stringify(entry) + "\n", "utf8");
  • 写入本地文件
    lib/index.js:26555
    const out = createWriteStream(dest);
  • 读取本地文件
    lib/index.js:26588
    const raw = JSON.parse(readFileSync(this.storePath, "utf8"));
  • 读取本地文件
    lib/index.js:26635
    modelBytes = statSync3(this.modelPath).size;
  • 读取本地文件
    lib/index.js:26669
    if (!existsSync(this.modelPath) || statSync3(this.modelPath).size < 1e6) {
  • 删除本地文件
    lib/index.js:26754
    unlinkSync(part);
  • 删除本地文件
    lib/index.js:26923
    unlinkSync(this.storePath);
  • 删除本地文件
    lib/index.js:27359
    unlinkSync2(part);
  • 执行外部命令来自配置/变量
    lib/index.js:27393
    worker = fork(workerPath, [], {
  • 发起网络请求
    lib/client.js:18533
    void fetch(apiUrl("/record-log"), {
  • 发起网络请求
    lib/client.js:18559
    void fetch(apiUrl("/plan-log"), {
  • 发起网络请求
    lib/client.js:18572
    void fetch(apiUrl("/volume-log"), {
  • 发起网络请求
    lib/client.js:18635
    void fetch(apiUrl("/voice-state"), {
  • 发起网络请求
    lib/client.js:18643
    void fetch(apiUrl("/voice-state"), {
  • 发起网络请求
    lib/client.js:18654
    void fetch(apiUrl("/voice-state"), {
  • 读取本地文件
    lib/plan-log.js:37
    size = statSync(PLAN_LOG_PATH).size;
  • 写入本地文件
    lib/plan-log.js:41
    if (size > MAX_BYTES) writeFileSync(PLAN_LOG_PATH, "");
  • 写入本地文件
    lib/plan-log.js:42
    appendFileSync(PLAN_LOG_PATH, JSON.stringify(item) + "\n");
  • 读取本地文件
    lib/record-log.js:78
    size = statSync(RECORD_LOG_PATH).size;
  • 写入本地文件
    lib/record-log.js:82
    if (size > MAX_BYTES) writeFileSync(RECORD_LOG_PATH, "");
  • 写入本地文件
    lib/record-log.js:83
    appendFileSync(RECORD_LOG_PATH, JSON.stringify(item) + "\n");
  • 发起网络请求
    lib/rewriter.js:145
    this.request();
  • 发起网络请求
    lib/rewriter.js:190
    this.request();
  • 写入本地文件
    lib/separation.js:63
    const out = createWriteStream(dest);
  • 读取本地文件
    lib/separation.js:205
    modelBytes = statSync(this.modelPath).size;
  • 读取本地文件
    lib/separation.js:227
    const current = statSync(this.modelPath, { throwIfNoEntry: false })?.size ?? 0;
  • 写入本地文件
    lib/separation.js:229
    mkdirSync(dirname(this.modelPath), { recursive: true });
  • 读取本地文件
    lib/separation.js:233
    const size = statSync(part).size;
  • 写入本地文件
    lib/separation.js:235
    renameSync(part, this.modelPath);
  • 删除本地文件
    lib/separation.js:239
    unlinkSync(part);
  • 读取本地文件
    lib/separation.js:255
    if (!statSync(this.modelPath, { throwIfNoEntry: false })?.size) {
  • 执行外部命令来自配置/变量
    lib/separation.js:273
    worker = fork(workerPath, [], {
  • 发起网络请求
    lib/separation.js:389
    const result = await this.request(samples);
  • 读取本地文件
    lib/voiceprint.js:55
    if (statSync(DECISION_LOG).size > DECISION_LOG_LIMIT) return;
  • 写入本地文件
    lib/voiceprint.js:58
    appendFileSync(DECISION_LOG, JSON.stringify(entry) + "\n", "utf8");
  • 写入本地文件
    lib/voiceprint.js:143
    const out = createWriteStream(dest);
  • 读取本地文件
    lib/voiceprint.js:176
    const raw = JSON.parse(readFileSync(this.storePath, "utf8"));
  • 写入本地文件
    lib/voiceprint.js:183
    mkdirSync(this.dataDir, { recursive: true });
  • 写入本地文件
    lib/voiceprint.js:184
    writeFileSync(this.storePath, JSON.stringify(store), "utf8");
  • 读取本地文件
    lib/voiceprint.js:223
    modelBytes = statSync(this.modelPath).size;
  • 读取本地文件
    lib/voiceprint.js:257
    if (!existsSync(this.modelPath) || statSync(this.modelPath).size < 1e6) {
  • 读取本地文件
    lib/voiceprint.js:257
    if (!existsSync(this.modelPath) || statSync(this.modelPath).size < 1e6) {
  • 读取本地文件
    lib/voiceprint.js:328
    if (existsSync(this.modelPath) && statSync(this.modelPath).size > 1e6) return this.status();
  • 写入本地文件
    lib/voiceprint.js:329
    mkdirSync(dirname(this.modelPath), { recursive: true });
  • 写入本地文件
    lib/voiceprint.js:336
    renameSync(part, this.modelPath);
  • 删除本地文件
    lib/voiceprint.js:342
    unlinkSync(part);
  • 删除本地文件
    lib/voiceprint.js:511
    unlinkSync(this.storePath);
  • 读取本地文件
    lib/volume-log.js:34
    size = statSync(VOLUME_LOG_PATH).size;
  • 写入本地文件
    lib/volume-log.js:38
    if (size > MAX_BYTES) writeFileSync(VOLUME_LOG_PATH, "");
  • 写入本地文件
    lib/volume-log.js:39
    appendFileSync(VOLUME_LOG_PATH, JSON.stringify(sample) + "\n");
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-web@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
dsh-voice-dialog 给 DeepSeek Harness 的连续语音对话插件:输入框旁只有一个麦克风,语音输入期间朗读助手回复,支持模型响应“轻一点/重复/闭嘴”等语音意图;插话会以“软打断”的方式交给正在运行的模型,而不是硬切断回答。 功能 - 只有一个麦克风。 不再有“电话模式”按钮、悬浮面板或第二套工具栏控件;点麦克风开始/结束连续收音;激活后展开行左边是叉,只关收音、让当前朗读继续;右边方块是挂断,会同时打断朗读并取消后台还没合成的句子。 - 连续听写。 静音约 1.4 秒后自动结束一句,调用 DSH 语音识别转写。登记过的本人默认用 session.prompt(..., "queue") 排在当前回答之后;可以在设置里改成 steer 立即插话。其他人默认也走排队。最多三句同时识别;识别是并行的,投递严格按说话先后排一条队列,后来的话不会抢到前面。麦克风触发门槛可以调:小声说话容易漏就调低,环境太吵容易误触发就调高。 - 只在语音输入时朗读。 Host 监听 llm/stream,把助手文本按句切分后用 Edge TTS 合成,通过 SSE 推给浏览器排队播放。第一句比较长时,会在第一个自然逗号处先开始合成,不必等整句句号。麦克风启动才接收新句子;关闭麦克风后不再读新内容,但会把已经排队的剩余音频读完。
展开完整文档(README 剩余 1 节)
dsh-voice-dialog

给 DeepSeek Harness 的连续语音对话插件:输入框旁只有一个麦克风,语音输入期间朗读助手回复,支持模型响应“轻一点/重复/闭嘴”等语音意图;插话会以“软打断”的方式交给正在运行的模型,而不是硬切断回答。

功能

- 只有一个麦克风。 不再有“电话模式”按钮、悬浮面板或第二套工具栏控件;点麦克风开始/结束连续收音;激活后展开行左边是叉,只关收音、让当前朗读继续;右边方块是挂断,会同时打断朗读并取消后台还没合成的句子。
- 连续听写。 静音约 1.4 秒后自动结束一句,调用 DSH 语音识别转写。登记过的本人默认用 session.prompt(..., "queue") 排在当前回答之后;可以在设置里改成 steer 立即插话。其他人默认也走排队。最多三句同时识别;识别是并行的,投递严格按说话先后排一条队列,后来的话不会抢到前面。麦克风触发门槛可以调:小声说话容易漏就调低,环境太吵容易误触发就调高。
- 只在语音输入时朗读。 Host 监听 llm/stream,把助手文本按句切分后用 Edge TTS 合成,通过 SSE 推给浏览器排队播放。第一句比较长时,会在第一个自然逗号处先开始合成,不必等整句句号。麦克风启动才接收新句子;关闭麦克风后不再读新内容,但会把已经排队的剩余音频读完。Edge 端点不可达时,这一句会退到系统语音朗读,不会静默消失。
- 按优先级插话。 你开口时只把朗读音量压低,不停止播放。本人的话默认等当前回答说完,再用 session.prompt(..., "queue") 交给模型,不会把你正在听的回答截断;设置里可以改成 steer 立即插话。旁边其他人的话也按说话顺序排队,不抢当前回答;也可以改成直接插话或忽略。
- 并行语音组织层。 助手还在朗读时,主人的新话会立刻入队,但停在队头等一个独立的、带版本号的模型判断:打断、排队还是忽略。打断会先用 250 毫秒淡出当前句、清掉没读的旧句子,再把这句按 steer 送进去;排队保持原策略;忽略只丢这一条。判断过期、超时、输出不合法或找不到模型时一律按排队处理。明确说“打断”会取消正在进行的组织判断,仍然优先。组织调用使用 voice-organizer 这个 purpose,不会被朗读。
- 队列里的最新意图。 最新一句说“打断 / 停一下”会立刻停朗读、清掉还没送出的队列,并把后面的请求用插话送进去;说“忽略客人1 / 别理老婆”会当场改声纹策略,把那个人还在排队的句子删掉;说“恢复”重新排队。普通句子仍然严格按先后顺序走,不会因为识别快就超车。
- 不整段读思维链。 通过 GenerateOptions.purpose 过滤 compaction / 会话标题 / voice-organizer 等内部调用;reasoning 只扫描显式的 [[voice: ...]] 指令,不会把整段思维链读出来。工具参数永远不会进入 TTS。
- 模型决定说什么、说多快。 模型可以在 reasoning 里写 [[voice: 要说的内容]] 指定朗读文本,或用 [[voice: volume +0.15]]、[[voice: rate +10]]、[[voice: repeat]]、[[voice: stop]] 控制。说“慢一点/快一点/语速调到…”时,模型通过 voice_dialog 的 rate 动作调整后续句子;say 指令只增加朗读前缀,不替代可见回复。
- 模型语音控制。 新增 voice_dialog 工具:轻一点/响一点(volume)、听不清/什么/重复一遍(repeat)、别说了/闭嘴/停(stop)。Host 通过同一条 SSE 把动作广播给浏览器;stop 会静音后续句子,直到用户再次开口。同样的动作和指定朗读文本也可以直接用 reasoning 标记表达,模型不必每次走工具调用。
- 后台子代理直接播报。 开麦时客户端把当前会话标记为语音活跃;子代理结束时 host 读取它的最终文本,压成一句摘要直接排进父会话的 TTS,不需要主模型再开一轮。客户端用心跳续期,标签页消失后状态自动过期。
- 声纹前缀与优先级。 本地 CAM++ 声纹模型(由 sherpa-onnx-node 运行,不调用云端)识别登记过的本人,并把其他声音聚类;每段转写前加 [声纹:我] 或 [声纹:客人1],模型能看出是谁在说。本人是高优先级,其他人是低优先级。设置页可以录制本人声纹,也可以给其他常说话的人录入声纹并起名;录入后名字会代替“客人1”持久保存,转写里直接显示名字。对话中判定为本人时会用该段特征慢慢强化模板,可选的“只回应我的声音”会丢弃不匹配的语音。模型也可以按声纹决定:调用 voice_dialog 的 speaker 动作,把 客人1 设为 ignore 就不再收这个人的后续语音,设为 queue 恢复排队,speaker: "*" 作用于所有其他人;带 name 可以给声纹改名(例如 "老婆"),之后用原名或新名字都能设置策略,转写也会显示新名字。主人 我 不能被改名或忽略。两个人同时开口时,可选的本地 MossFormer2 ONNX 模型会把这一段麦克风音频拆成两路,再分别识别、分别标声纹、分别排队;只有一个人说话时自动回退到原始音频,不会重复识别。模型对两个人的重叠说话效果最好,三个人以上仍可能混在一起。
- 插件设置页。 自动朗读、音量、压低比例、朗读音色与语速、试听、识别服务/语言、模型准备、我说话时/其他人插话策略、并行组织层、并行识别、输入麦克风都在 插件 → dsh-voice-dialog 页面里。麦克风激活后,输入框会展开成内置语音输入插件风格的整行:波形、关闭和挂断按钮,并显示后台还有几句没合成完。

要求

- DSH 0.2.1-rc.2 或兼容版本。
- Node.js 22+。
- DSH 语音识别服务。本插件的 bundle 自己组合了三条 host 行:speech-to-text、speech-to-text-sensevoice、api-speech-to-text。
- 朗读需要能访问 Microsoft Edge TTS(用于所选音色);访问不了会自动退到浏览器系统语音。首次使用 SenseVoice 可能需要下载模型。
- 需要代理才能访问 Edge 时,插件自动读取 HTTPS_PROXY / HTTP_PROXY,WebSocket 通过 CONNECT 隧道;可用 DSH_VOICE_TTS_PROXY 覆盖,NO_PROXY 可让 Edge 直连。
- 麦克风需要安全上下文:https:// 或 http://localhost / http://127.0.0.1。
- 声纹前缀可选:sherpa-onnx-node(可选依赖,自带当前平台的原生模块)和一次约 27 MB 的 CAM++ 模型下载。没有它们时语音输入仍可用,只是不带说话人前缀。
- 同时说话分离可选:onnxruntime-node 和一次约 234 MB 的 MossFormer2 模型下载(阿里 MossFormer2_SS_16K 的 ONNX 导出,Apache-2.0)。优先用 DirectML(有可用显卡时每 4 秒窗口约 0.4 秒),失败自动回退到处理器。没有它时普通听写不受影响。

安装

从 GitHub 安装(仓库内已提交构建后的 lib/):

dsh plugin --profile web add github:ggfgfgf-on/dsh-voice-dialog

或从本地目录安装:

dsh plugin --profile web add file:D:/path/to/dsh-voice-dialog

确认 profile 的 bundle 列表包含:

"dsh": { "profile": { "bundles": [ "...", "dsh-voice-dialog" ] } }

重要:不要同时启用内置语音输入 bundle

本插件和 @deepseek-ai/dsh-experimental-voice-input-bundle 需要同样的三条语音 host 行。
同一个 profile 里同时启用会重复注册服务。请在 dsh.profile.bundles 里移除内置语音输入 bundle(或在插件页停用它),只保留 dsh-voice-dialog。麦克风界面由本插件接管,功能不会少。

使用

1. 打开会话,点输入框右侧的麦克风。
2. 正常说话;停顿会自动结束一句并插入当前轮次。开启同时说话分离时,停顿按每一路声源单独计算:你停 1.6 秒就切你这句,旁边的人继续说他那一路。
3. 语音输入期间助手回复会自动朗读;关闭麦克风后不再读新内容,已经排队的剩余音频会读完。
4. 再点一下红色麦克风结束收音,已排队的音频会读完。展开行左边的叉关闭收音,但已排队朗读继续;右边方块挂断并打断朗读。说“轻一点/响一点/重复一遍/别说了”时,模型会调用 voice_dialog 调整朗读。

语音模型没准备好时,点麦克风会自动打开本插件设置页,可在那里下载/准备模型;页面也会显示实时状态和下载进度。

设置

全部在 插件 → dsh-voice-dialog:

| 设置 | 存储位置 | 说明 |
| 自动朗读、音量、压低比例、输入设备 | 浏览器 localStorage | 每个浏览器/设备独立 |
| Edge 朗读音色、语速 | Host ~/.dsh/voice-dialog/settings.json | 立即生效,重启后保留 |
| 识别服务、语言 | DSH speech selection | 与其他语音客户端共享 |
| 模型准备 | DSH speech host | 下载 / 取消 / 重试 |
| 语速 | Host ~/.dsh/voice-dialog/settings.json | -50% 到 +50%;模型也能改 |
| 声纹前缀、只回应我的声音、阈值 | 浏览器 localStorage | 控制加不加前缀、是否过滤 |
| 我说话时、其他人插话策略、并行组织层、并行识别 | 浏览器 localStorage | 我默认排队(也可立即插话);其他人排队(默认)/ 直接插话 / 忽略;最多三路识别,投递严格按说话顺序;组织层只能改当前这一条投递方式 |
| 本人和其他人的声纹、名字 | Host ~/.dsh/voice-dialog/voiceprint.json | 只保存特征向量,不保存原始录音;其他人最多 12 个 |
| 声纹模型 | Host ~/.dsh/voice-dialog/models/ | 从设置页下载 |
| 同时说话分离 | 浏览器 localStorage + Host 模型 | 可选;把两个重叠说话的人拆成两路分别识别;每一路按自己的 1.6 秒静音切句,旁边一直说也不会拖住你这句 |
| 分离模型 | Host ~/.dsh/voice-dialog/models/mossformer2_ss_16k.onnx | 约 234 MB;从设置页下载 |

手机上左侧栏是整列滑出屏幕的,「插件」入口点不到;因此输入框麦克风旁边还有一个齿轮(语音设置),点开就是同一份设置表单(≤420px 单列、全宽控件、40px 触控目标、内部滚动)。详见 MOBILE-SETTINGS.md。

音色包含普通话、粤语、台湾国语、英语、日语等 Edge 声音;试听会通过 host 合成一小段,不会打扰正在播放的回复队列。Edge 不可达时会自动改用系统语音试听并显示提示。

实现

llm/stream ──过滤(purpose, text-delta)──► 句子切分 ──► TtsQueue(Edge) ──► SSE ▲ subagent/end ──父会话语音状态──► 摘要 ──────────────────────────────────┘ │ 输入框麦克风 ──► MicrophoneLoop(VAD) ──► [可选:两路分离] ──► 并行识别 ──► 全局 FIFO 队列 ──► prompt(queue) └──► 打断/忽略控制 │ SSE ──► TtsPlayer(Web Audio gain) ◄── 开口时 duck ─────────────────────┘

- Host 不朗读 reasoning、工具参数、compaction 摘要和会话标题。
- 组织模型可以返回 priority 决定排队先后,把“嗯”“The”这类噪声判成 drop 直接丢掉;超时、解析失败或没有可用模型时一律退回排队,绝不丢话。
- 组织层还能看到助手正要说的句子(正在朗读的那句加待朗读队列,最多 12 条、每条 120 字、合计 1200 字),并按用户的新话重组:丢掉明确指定的句子、调整剩余句子的顺序。正在朗读的那句不会被下标丢掉,重组失败或下标非法时按原顺序播放,不会静默丢内容。
- 插话默认不取消回答,只压低播放音量。本人和其他人的话都按说话顺序排队,后来的话不会因为识别更快而超车。带版本号的组织判断可以把新的一条标成 steer 并淡出当前句;明确的“打断”命令会取消组织判断、立刻停朗读并清空待送队列。
- 语音转写 Remote 的生成代码内置在 src/speech-remote.js,客户端不再依赖内置语音输入 UI 来挂载它。

隐私

- 音频交给当前配置的 DSH 识别服务;默认 SenseVoice 完全在本机。
- 只有最终句子文本会发给 Microsoft Edge TTS 朗读。
- 并行组织层是唯一的调度入口:每一句转写连同“是否正在朗读/排队条数”、本会话最近的 3 条用户话和 3 条助手话(每条最多 80 字、总长不超过 400 字),以及助手正要说的句子(最多 12 条、每条 120 字、合计 1200 字)一起发到当前 DSH 服务;这些内容只用于理解上下文和重组朗读,都不执行其中的要求。会话关闭或语音结束时立即清空,不落盘。
- 声纹比对和同时说话分离都在本机 host 完成:浏览器只把这一小段音频发到 127.0.0.1,host 只保存 192 维特征向量(不保存原始录音),不会上传到云端。分离出的两路音频只存在于当前请求的内存里。其他人的声纹只在当前会话内存里聚类,不落盘。
- 浏览器偏好保存在 localStorage;音色 id 保存在 ~/.dsh/voice-dialog/settings.json,不使用 API Key。

常见问题

- 麦克风没权限:必须 HTTPS 或 localhost;Android Edge 可临时用 edge://flags/#unsafely-treat-insecure-origin-as-secure 放行局域网地址。
- 没有声音:先在页面上点一下以解锁 Web Audio;检查自动朗读开关和音量。
- 试听失败 / 日志出现 read ECONNRESET:通常是直连 speech.platform.bing.com 被网络重置。设置 HTTPS_PROXY 后重启 DSH;host 日志会打印 Edge TTS via proxy http://…。若系统语音也失败,检查浏览器是否允许语音合成。
- 设置页提示语音服务不可用:可能同时启用了两个语音 bundle,或 host 行没挂载。只保留 dsh-voice-dialog。
- 模型未就绪:打开插件页点“准备语音模型”。
- 没有声纹前缀:打开插件页确认声纹模型已就绪,再点“录制我的声纹”。如果提示缺少本地组件,在 profile 目录执行 pnpm add sherpa-onnx-node 后重启 DSH。
- 本人被标成客人:把声纹阈值稍微调低(建议从 0.52 开始),或在安静环境重新录一遍。

开发

npm install
npm run build
npm test

npm run build 生成 host ESM、客户端 __ModuleLoader__ 闭包和测试用的纯 Node 模块;npm test 覆盖优先级车道、句子切分、Markdown 过滤、不读思维链、WAV 编码、音色切换、声纹 WAV 解码/余弦相似度,以及分离窗口/重叠对齐、连续分离的每路 1.6 秒端点与按开口顺序的 FIFO(用注入的 runner)。原生声纹和分离模型在开发时单独验证,npm test 不会下载模型。

许可

MIT,见 LICENSE 与 NOTICE。
预览分享卡片长什么样 ↓ggfgfgf-on/dsh-voice-dialog
分享 · DeepSeek Harness Hub
ggfgfgf-on/dsh-voice-dialog

DeepSeek Harness 的连续语音对话:一个麦克风,自动朗读回复,轻声插话即可打断

这是你的仓库?认领条目

回到顶部