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

本地语音合成 abbccdd/dsh-localtts

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

为 DeepSeek Harness 增加按协议配置的本地 HTTP API / JSONL worker…

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

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

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add abbccdd/dsh-localtts
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

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

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

验证判据与等级说明 →

可信度证据

安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包@dsh-external/dsh-plugin-local-ai-tts(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/4 16:14:44

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 68 处,展示前 47 条)
  • 执行外部命令来自配置/变量
    lib/index.mjs:183
    const child = spawn(process.execPath, argv, {
  • 发起网络请求
    lib/index.mjs:341
    res = await fetch(baseUrl + route, {
  • 读取本地文件
    lib/index.mjs:398
    audioBytes = readFileSync(mp3Path);
  • 写入本地文件
    lib/index.mjs:411
    writeFileSync(wavPath, wavBytes);
  • 执行外部命令来自配置/变量
    lib/index.mjs:458
    const p = spawn(cfg.binary, ['--model', cfg.model, '--output_file', wavPath], {
  • 读取本地文件
    lib/index.mjs:630
    if (existsSync(CAL_FILE)) calFileData = JSON.parse(readFileSync(CAL_FILE, 'utf8'));
  • 读取本地文件
    lib/index.mjs:630
    if (existsSync(CAL_FILE)) calFileData = JSON.parse(readFileSync(CAL_FILE, 'utf8'));
  • 写入本地文件
    lib/index.mjs:641
    mkdirSync(CAL_DIR, { recursive: true });
  • 写入本地文件
    lib/index.mjs:642
    writeFileSync(CAL_FILE, JSON.stringify(calFileData, null, 2));
  • 发起网络请求
    lib/index.mjs:653
    const r = await fetch(cfg.baseUrl + '/health', { signal: AbortSignal.timeout(8000) });
  • 读取本地文件
    lib/index.mjs:695
    const audioBytes = readFileSync(mp3Path);
  • 读取本地文件
    lib/index.mjs:742
    data = JSON.parse(readFileSync(path.join(packsDir(), PACK_FILE), 'utf8'));
  • 读取本地文件
    lib/index.mjs:749
    if (!e || !e.modelPath || !existsSync(e.modelPath)) {
  • 写入本地文件
    lib/index.mjs:760
    mkdirSync(packsDir(), { recursive: true });
  • 写入本地文件
    lib/index.mjs:761
    writeFileSync(path.join(packsDir(), PACK_FILE), JSON.stringify(data, null, 2));
  • 发起网络请求
    lib/index.mjs:838
    const r = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
  • 发起网络请求
    lib/index.mjs:899
    const r = await fetch(url, { signal: AbortSignal.timeout(1200000) });
  • 写入本地文件
    lib/index.mjs:956
    mkdirSync(dir, { recursive: true });
  • 删除本地文件
    lib/index.mjs:980
    rmSync(modelPath, { force: true });
  • 删除本地文件
    lib/index.mjs:981
    rmSync(indexPath, { force: true });
  • 发起网络请求
    lib/index.mjs:1322
    const r = await fetch(baseUrl + '/files?kind=' + kind, {
  • 删除本地文件递归
    lib/index.mjs:1481
    rmSync(dir, { recursive: true, force: true });
  • 发起网络请求
    lib/index.mjs:1532
    const r = await fetch(baseUrl + '/health', { signal: AbortSignal.timeout(6000) });
  • 发起网络请求
    lib/client.js:1120
    const response = await fetch('/dsh-local-ai-tts-api/local-runtime', {
  • 发起网络请求
    lib/client.js:1961
    fetch(
  • 发起网络请求
    lib/client.js:2062
    const response = await fetch("/dsh-local-ai-tts-api/speak", {
  • 发起网络请求
    lib/client.js:2074
    const r = await fetch(
  • 发起网络请求
    lib/client.js:2147
    const r = await fetch(url);
  • 发起网络请求
    lib/client.js:2985
    const r = await fetch(
  • 执行外部命令来自配置/变量
    lib/local-runtime/provider.mjs:147
    try { child = spawn(this.config.command, this.config.args, { cwd: this.config.cwd || undefined, shell: false, windowsHide: true, stdio: ['pipe', 'pipe
  • 发起网络请求
    lib/local-runtime/provider.mjs:160
    const health = await this.request('health', {}, this.config.startupTimeoutMs);
  • 发起网络请求
    lib/local-runtime/provider.mjs:201
    async healthCheck() { await this.start(); const msg = await this.request('health', {}, this.config.startupTimeoutMs); return { ready: msg.ready !== fa
  • 发起网络请求
    lib/local-runtime/provider.mjs:202
    async listVoices() { await this.start(); const msg = await this.request('voices', {}, this.config.timeoutMs); const list = Array.isArray(msg.voices) ?
  • 发起网络请求
    lib/local-runtime/provider.mjs:208
    try { if (this.config.autoStart) await this.start(); else if (!this.child) throw processError('OFFLINE', 'Worker is not running and automatic start is
  • 执行外部命令固定命令
    lib/local-runtime/provider.mjs:224
    const killer = spawn('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore', shell: false });
  • 读取本地文件
    lib/local-runtime/discovery.mjs:23
    try { base = await realpath(input); if (!(await stat(base)).isDirectory()) throw new Error(); }
  • 读取本地文件
    lib/local-runtime/discovery.mjs:23
    try { base = await realpath(input); if (!(await stat(base)).isDirectory()) throw new Error(); }
  • 读取本地文件
    lib/local-runtime/discovery.mjs:31
    const resolved = await realpath(file);
  • 读取本地文件
    lib/local-runtime/discovery.mjs:33
    const info = await stat(resolved);
  • 读取本地文件
    lib/local-runtime/discovery.mjs:113
    return found && inside(parent, await realpath(found)) ? found : null;
  • 读取本地文件
    lib/local-runtime/discovery.mjs:116
    const stream = await opendir(dir);
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:6
    async function exists(file) { try { return (await stat(file)).isFile(); } catch (e) { if (['ENOENT', 'ENOTDIR'].includes(e.code)) return false; throw
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:23
    try { folder = await realpath(value); }
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:25
    if (!(await stat(folder)).isDirectory()) fail('请选择文件夹。');
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:34
    const available = await Promise.all(roots.map(async value => { try { await stat(value); return { name: value, path: value }; } catch (e) { if (['ENOEN
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:37
    const base = await directory(folder), entries = await readdir(base, { withFileTypes: true });
  • 读取本地文件
    lib/local-runtime/model-discovery.mjs:46
    for (const entry of (await readdir(base, { withFileTypes: true })).slice(0, 200)) {
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-host-webserver
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

1 张 · 点击查看大图

功能亮点

  • 语音播放

本地 IndexTTS 2.5 和 GPT-SoVITS 语音合成与播放,接入 DeepSeek Harness。

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness Local AI TTS Plugin 为 DeepSeek Harness 增加按协议配置的本地 HTTP API / JSONL worker 入口,并保留 IndexTTS 2.5 和 GPT-SoVITS 内置启动器。用户提供兼容的本地服务或已有 Python/项目/模型配置,插件逐句发送文本并在浏览器播放音频。合成、播放与 Harness 消息生成独立进行。 本地 AI TTS 中文设置界面 基于 1624318455/dsh-plugin-tts,上游提交 ec0cf87ef52abb81ae91681a966aa3096365e631。复用消息朗读按钮、Auto Read、Edge/RVC Provider、停止/暂停、设置面板、持久化与 Harness 插件 API。保留上游 MIT 版权和 LICENSE,详见 NOTICE。 插件不包含模型。 不安装、裁剪、训练或修改模型;使用已有环境运行内置加载配方或用户配置的 worker 命令。不打包权重、参考音频、用户音色缓存、Python 环境或生成音频。
展开完整文档(README 剩余 1 节)
DeepSeek Harness Local AI TTS Plugin

为 DeepSeek Harness 增加按协议配置的本地 HTTP API / JSONL worker 入口,并保留 IndexTTS 2.5 和 GPT-SoVITS 内置启动器。用户提供兼容的本地服务或已有 Python/项目/模型配置,插件逐句发送文本并在浏览器播放音频。合成、播放与 Harness 消息生成独立进行。

本地 AI TTS 中文设置界面

基于 1624318455/dsh-plugin-tts,上游提交 ec0cf87ef52abb81ae91681a966aa3096365e631。复用消息朗读按钮、Auto Read、Edge/RVC Provider、停止/暂停、设置面板、持久化与 Harness 插件 API。保留上游 MIT 版权和 LICENSE,详见 NOTICE。

插件不包含模型。 不安装、裁剪、训练或修改模型;使用已有环境运行内置加载配方或用户配置的 worker 命令。不打包权重、参考音频、用户音色缓存、Python 环境或生成音频。

Harness assistant 回复 → SentenceBuffer → Local Process Provider ↓ JSONL stdin/stdout IndexTTS / GPT-SoVITS Adapter ↓ PCM / Audio 浏览器 Web Audio

模型文件夹与中文设置

选择“本地模型文件夹(自动识别)” → 选择文件夹 → 识别 → 选择音色 → 加载模型 → 试听。支持 Kokoro 82M、Qwen3 CustomVoice、F5 v1 Base、VoxCPM、CosyVoice 3 的已知布局,直接调用已有 SDK,无需配置网关。克隆模型需要参考音频与原文,可保存为可复用音色预设;环境路径等低频设置默认折叠。点击“卸载模型”释放本插件持有的模型进程。详见文件夹使用指南。

通用协议入口和 IndexTTS / GPT-SoVITS 原有入口继续保留。文件夹识别不会安装依赖,也不能推断未知权重的架构;运行环境需已准备好。

以上五个文件夹模型已在本机完成直接 SDK 合成,以及正式 DSH 设置页加载、试听、暂停、继续、停止和卸载;此次不需要 HTTP 网关。实测范围见文件夹指南末尾。

通用本地 TTS(发布候选版)

新增 通用本地 TTS(HTTP / worker):同一个 Provider 支持 OpenAI speech、自定义 JSON、URL 编码表单、multipart 音频上传及 JSONL worker。模型名独立于协议,参数预设共用同一连接器。OpenAI speech 指本地接口格式,不要求 OpenAI 账号或云服务。

Piper、GPT-SoVITS 已完成原生 HTTP 合成验证;Kokoro、F5-TTS、VoxCPM1.5、Qwen3-TTS 0.6B、CosyVoice3 通过开发者本机 SDK 网关及正式 DSH 设置/播放器完成验证。这不代表各引擎所有原生 API/WebUI 都已验证。测试网关、模型环境和录音不随插件分发。配置方法和准确边界见通用接入指南与模型实测记录。

支持范围与要求

同一个插件包适配 Harness 0.1(从 0.1.0-rc.6 起,包括 0.1.1-rc.2)和 0.2(从 0.2.0-rc.2 起)。通过公共服务和消息选择器连接宿主,旧版 Session 文本事件和新版 Agent 流式帧共用逐句播放器。兼容声明保留下一次 minor 版本变更的上限;未来接口若有破坏性变化,需要验证后再扩展。具体测试边界见验证记录。

- DeepSeek Harness web profile,提供 webServer、session/event 和客户端 UI slots;Node.js 22+,浏览器支持 Web Audio。
- 兼容的本地 HTTP 服务,或已有模型安装及实现 JSONL worker 协议 的命令。
- 使用内置 IndexTTS / GPT-SoVITS 启动器时,需要对应 Python 环境、项目和模型文件。adapters/ 中的连接示例不包含权重。

并非任意原版 WebUI 或 /tts API 都能直接连接,协议必须匹配。旧接口说明与通用接入指南包含请求/响应格式;历史宿主检查见验证记录,新增 GPT-SoVITS 实测见GPU 记录。

安装

可以与原版同时安装和启用,不需要卸载原版。 本插件使用独立的包名、路由、设置和界面标识;检测到原版后自动进入本地补充模式,详见下文。

从 GitHub 安装当前源码(已装旧版时也用此命令替换,并启用市场更新检测):

dsh plugin --profile web add github:abbccdd/dsh-localtts

源码已包含编译后的客户端文件,无需运行构建脚本。也可从 v0.1.12-rc.5 候选版下载对应安装包和 SHA256 校验文件。上一版 v0.1.11 不包含新增通用接口及文件夹入口;0.1.8 不兼容 Harness 0.2。安装后重启 Harness 并刷新浏览器。

本地开发时,也可以安装工作区目录:

dsh plugin --profile web add "file:/path/to/dsh-plugin-local-ai-tts"
dsh web

重启 dsh web 并刷新浏览器。在 Windows 上,file: 安装可能复制文件;修改源码后需要重新安装该本地包。不要修改 Harness 核心。

社区 DSH 插件市场目录由其他仓库维护;若仍提供 0.1.8,请使用上面的命令。

更新机制与兼容性

打开设置时,插件每天最多自动检查一次本仓库已发布完整安装包的 GitHub 版本,并标明候选版;也可手动点击 检查更新,或关闭自动检查。检查不向 GitHub 发送登录凭据或对话内容。离线或 API 限流会显示原因,可手动重试。

点击 更新安装 并确认后,由已安装的 DSH 插件市场执行更新,保留市场的运行中 Agent 检查、宿主兼容检查和回滚。安装后需要重启 Harness 并刷新页面,正在运行的旧模块不会假装已切换版本。市场收录后,本地 file: 安装可恢复到线上来源。没有市场、使用固定 Release 地址或目录尚未收录时,请执行面板中的 GitHub 安装命令;自定义 profile 请替换 web。插件不会独立覆盖自身文件,也不会自动绕过兼容限制。

如果宿主在加载前拒绝插件,插件自己的更新面板也无法运行,此时需要独立市场或 CLI 更新。消息接口按实际提供的 Chat/Session 能力选择,不支持的结构会明确提示;缺少流式帧时仍可通过最终消息朗读,但开始时间会延后到回复完成。每次推送的 CI 会检查官方 0.1.1-rc.2、0.2.0-rc.2 和持续变化的 alpha 通道宿主包。检查能发现接口变化,无法自动适配任意未来 API,也不替代真实模型与浏览器验收;0.3 的兼容上限仍保留。

配置本地进程(IndexTTS 2.5 / GPT-SoVITS)

打开 设置 → 插件 → 语音 · 本地 AI 语音,正常安装只需处理三项:

1. 引擎:选择 IndexTTS 2.5 或 GPT-SoVITS。
2. 项目文件夹:粘贴已有安装的完整目录,离开输入框时自动查找,也可点击 自动查找文件。支持项目根目录,以及常见的外层整合包目录。IndexTTS 与 GPT-SoVITS 分别保存自己的项目、模型和角色配置;切换回来会恢复之前填写的路径,不会把另一引擎的路径带过来。
3. 参考音频:只有一个候选时自动填入;多个候选时从列表选择;不在列表中的音频可手动填写完整路径。

主界面还提供「合成语言」和当前模型原版的「语速/时长系数」。首次测试连接需要加载官方模型,可能会等待一段时间;请保持设置页面打开,不要重复点击。

不需要逐个填写 Python、启动脚本、模型权重或配置文件,也不用手写启动参数和 JSON。设置自动保存;保存设置可再次确认保存。

高级设置默认折叠。 自动发现不完整、有多个 Python/模型候选,或你使用外部 Conda 环境、自定义模型目录时,才需展开调整。GPT-SoVITS 的参考音频原文和语言也在这里:部分模型要求原文,插件不能从文件名可靠推断。不会替用户随机选取 .pth / .ckpt。

路径指的是 运行 Harness 的电脑。发现操作只读检查指定目录,不启动引擎、不安装依赖、不下载模型。Test Connection 会实际启动 worker;worker 响应并不保证合成成功,还需要试听一小段。

再次扫描同一项目会保留手动覆盖的路径;更换项目或引擎会清除上一套启动路径、参考音频和提示文本。缺文件会明确提示,不会改用云端。

自动发现范围、必要文件与官方启动依据见 目录识别说明;自定义 worker 的底层协议见 PROCESS-WORKER-PROTOCOL.md。

与原版共存

| 环境 | 本插件行为 |
| 没有启用原版 | 独立提供 Edge TTS、RVC、Local Runtime。 |
| 检测到原版 | 只提供 Local Runtime;Edge/RVC、选中文本朗读、通用快捷键、审批播报交给原版。 |
| 自动检测不适用的旧版 Harness/其他 fork | 在共存检测中选择 始终仅提供本地功能。无法确认原版 Auto Read 状态时,仅支持手动本地朗读。 |

消息旁保留原版按钮,并增加标有 Local 的本地按钮;设置和自动朗读入口分别标为 本地语音、本地 Auto Read。原版没有公开的第三方 Provider 注册接口,因此这里不会把 Local Runtime 注入原版下拉框,也不会修改原版代码。

使用本地自动朗读前,请先关闭原版 Auto Read,再开启本地 Auto Read。原版开启或状态未知时,本地自动朗读暂停;检测到状态变化会取消本地自动队列,但不打断手动本地朗读。此检查按浏览器轮询进行,不是两个播放器的原子互斥;请勿同时点击两个手动朗读按钮,原版已经开始的音频也不会被本插件强行停止。

设置、语言和音色包状态独立保存;首次启动只读复制旧 TTS 主设置,并将导入的 Auto Read 和审批播报设为 OFF。保存、恢复默认和卸载本插件均不改写原版设置。浏览器清理整个站点数据仍会清除其他插件数据,不建议用它做单插件卸载。切换启用状态后建议重启 Harness 并刷新页面;旧 Harness 无插件清单时,禁用原版后必须刷新才能排除残留设置 getter。

Host 有公开插件清单时,会省略本插件自己的 Edge/RVC 路由;没有清单时保留独立命名的路由,因此加载顺序仍不会撞路由。更详细的边界与测试见 共存说明。

Auto Read、手动朗读与播放控制

1. 测试连接后,可使用原有预览和 assistant 消息朗读按钮。先点击一次页面,允许浏览器播放音频。
2. 在输入区开启 Auto Read;共存时先关闭原版,再开启 本地 Auto Read。只朗读当前会话后续生成的 assistant 文本,不因刷新重播历史消息。
3. 每个完整句子立即入队,支持“Harness 生成第 3 句、Runtime 合成第 2 句、浏览器播放第 1 句”。
4. 回复尚未完成时也有本地播放控制条。暂停/继续控制音频,停止丢弃待播队列,当前自动回复余下内容不再朗读;进程 worker 内正在执行的推理不保证被立即终止。
5. 关闭 Auto Read 不打断手动朗读;切换 engine、voice、endpoint 会停止旧任务。重复 React 渲染、完成消息和重复序号事件不重新合成。

中文 。!? 和英文 .!? 切句,小数点有例外。长句约 55 字后优先按软标点切分,70 个 Unicode 字符硬上限;短句绝不合并,三句严格三次请求。最多预取三段。Runtime 慢于实际语速时仍可能出现间隙。

设置中的「合成语言」和「语速/时长系数」直接传给官方模型:IndexTTS 使用原版 duration_factor(0.50 更快,2.00 更慢),GPT-SoVITS 使用对应 WebUI 的 speed/speed_factor(范围 0.60–1.65)。播放控制条的倍速仍只改变浏览器播放速度,不改变模型合成。Local Runtime 暂不提供音频下载;原有其他 Provider 的功能保留。完整边界及取消语义见 协议文档。

常见错误

| 状态/错误 | 处理方式 |
| 插件市场里点开关后变灰、几十秒按不了 | 保持 DSH 和页面打开,等这次请求结束,不要反复刷新或重启。原因在插件市场一侧(dshmarket 1.31.1 已复现):它启用任何插件前都要联网拉一次目录来判断该包是不是主题,网络慢时这一个请求会阻塞整个开关,实测约 70 秒;插件自身的激活只需约 1 秒。 |
| 开关点完、重启后 DSH 直接打不开 | 手工改过 profile 的 cordis.patch.yml,同一个 id 出现两条记录时会导致启动失败。若报 duplicate loader entry id: local-ai-tts,把补丁层里 local-ai-tts 的所有行删掉(回到 []),只让 bundle 层挂载一次。自查:dsh --profile <profile> --dump-config,id: local-ai-tts 必须只出现 1 次。 |
| 文件未找到 / worker 启动失败 | 先重新自动查找;高级设置中检查现有 Python、模型目录或 API/YAML 路径,再测试连接。 |
| loading / unloaded / busy | 等待或用 Runtime 自己的管理方式处理;插件不主动加载模型。 |
| Worker 返回异常/非 JSON | 检查 worker 是否遵守 JSONL 协议;WebUI 页面不是 worker。 |
| HTTP 401/403 | Runtime 需要鉴权或拒绝访问;本版不读取/导入任何登录凭据。 |
| HTTP 429/503 | Runtime 繁忙或不可用,停止其他推理后重试。 |
| 请求超时 | 检查 Runtime 日志,按需增大高级设置中的启动/请求超时;进程模式最多 600000 毫秒。 |
| 参考音频无效/未找到 | 从候选列表选择,或填写已有参考音频的完整路径;插件不附带音色。 |
| 没有声音/自动播放受限 | 点击页面,检查浏览器静音与系统输出;停止后重试。 |
| 合成失败 | 当前朗读停止,但插件仍可使用;修复 Runtime 后再次朗读,不会自动发到云端。 |
| 远程浏览器连接失败 | localhost 指的是运行 dsh web 的主机,不是远程浏览器所在机器。 |
| 局域网地址被拒绝 | 默认仅允许 loopback;RFC1918 私有 IPv4 必须明确勾选局域网许可,公网地址/域名仍禁止。 |

旧版 HTTP Runtime 兼容附录

已有 HTTP 设置仍可迁移,但不再是主流程;local-runtime 仅保留内部兼容。插件不会替这类旧设置启动外部 HTTP 服务,也不会把模型目录当作 Endpoint。具体设置结构见 旧 HTTP 协议。更换项目目录后使用内置进程启动方式。

如果只有模型文件或可导入的 Python 对象,请使用上面的内置 Local Engine Launcher。随插件提供的 adapters/python_http.py 只是在已有 Runtime 对象外接兼容 HTTP 薄适配的可选工具,不创建、安装或修改模型。

隐私与安全

Local Runtime 模式只从 Harness Host 向配置的 Runtime 发送待朗读文本,不读取 Harness 登录凭据,不自动回退云端。默认只允许 127.0.0.1、localhost,后者固定解析为 IPv4 loopback。局域网许可会提示文本离开本机。Local Runtime 模式禁用本插件继承的云端审批提醒;共存时原版自身的云端功能不受本插件控制,如需完全本地处理,请自行关闭原版相关功能。

普通日志不记录完整回复;只有显式 Debug 模式允许记录句子文本,处理隐私内容时请关闭。音频和文本在内存中排队,播放确认、停止或过期后释放。IndexTTS worker 会在合成时使用临时 WAV 并在返回后删除;异常终止可能留下临时文件。Harness 和 Runtime 自己的日志、缓存及下载策略需另行检查。

Edge TTS 会向微软发送文本;RVC 可能先用 Edge 生成基底语音再本地转换,因此不等于完全本地。上游 RVC 文件/音色包工具保持原样,适用于可信的本地 Harness;请勿把 Harness 或插件暴露给不可信用户/公网。

Edge TTS 的费用和自定义音色

本插件继承的 Edge TTS 路径不要求 Azure Speech 订阅、Azure API Key 或在插件内配置付款账户,因此插件本身不会产生一项 Azure 账单。它实际调用的是 Microsoft Edge 的在线 Read Aloud 服务;微软可以调整服务条款、可用性、速率限制或访问策略,不能把它承诺为永久免费、无限量服务。微软官方将 Read Aloud 描述为 Edge 浏览器功能,使用时应遵守 Microsoft Services Agreement。

不要把 Edge Read Aloud 的免费可用性等同于 Azure Speech 的商业授权。Azure Speech 标准语音按字符计费;如果需要稳定的商业服务,应查看 Azure Speech 定价 和适用条款,或使用本地 Runtime。项目发布者不能替用户判断具体地区、账户或内容的授权。

Edge TTS 不能训练自己的声音。微软的 Custom Neural Voice / Personal Voice 属于 Azure Speech 的独立功能,需要申请 Limited Access;官方要求取得音色本人明确书面许可和录音确认,并按批准用途使用。Custom Neural Voice 的训练和托管也会计费,不能通过本插件完成。若 IndexTTS 或 GPT-SoVITS Runtime 支持本地音色训练/克隆,应遵守对应模型和录音许可;本插件只传递 Runtime 的 Voice ID,不保存或上传参考音频。

卸载

先停止朗读,然后运行:

dsh plugin --profile web remove @dsh-external/dsh-plugin-local-ai-tts

重启 Harness 并刷新页面。不会卸载或修改原版插件或任何 Runtime/模型。如需清理本插件主设置,卸载前点击 恢复默认设置;不会清除原版设置。

开发、测试与发布

npm run build
npm test
npm run test:adapter
npm pack --dry-run

测试只用 Node 内置模块、Python 标准库和 mock,无需安装新依赖、GPU、真实模型或云端 TTS。src/local-client.js 会嵌入 Harness 模块格式的 lib/client.js,两者都应提交。上游真实在线测试保留为手动选项,不进入 CI。

需要验证已有 HTTP Runtime 时,可运行 npm run smoke:runtime -- --engine indextts --endpoint http://127.0.0.1:8765 --voice default,自行替换参数;这只是旧版兼容路径。内置 Local Engine Launcher 的真实 worker 验证请按 验证记录与人工清单 配置现有 Python/模型环境执行;两者都不等于 Harness 页面实际播放验收。

发布前查看 CHANGELOG、验证记录与人工清单、LICENSE。npm 包使用文件白名单;.gitignore 和发布扫描排除模型、用户音色、参考录音、环境、凭据、音频产物。仍需人工审查最终 Git diff 与打包清单。GitHub 源码仓库已经可用;目前尚未声明 npm 包或稳定版 tag。

许可证

MIT,保留原作者版权及完整 LICENSE。没有新增生产依赖。NOTICE列出上游归属;Runtime、权重和音色的授权由各自项目/用户单独负责,插件 MIT 不代表获得这些内容的授权。

官方 WebUI 后端(无需打开网页)

默认的本地模式会按官方入口在后台加载模型,不需要手动打开模型网页:IndexTTS 2.5 使用项目中的 webui.py,GPT-SoVITS 使用官方 GPT_SoVITS/inference_webui.py(或明确选择的 fast 分支)。插件只负责启动参数、连接和逐句播放,模型加载与推理仍由官方代码完成。

如果探测到端口已有服务,插件不会猜测那是不是同一个项目或权重,而会提示先在高级设置选择“仅连接”。该模式不会启动、切换权重或停止用户自己的服务。目录发现不会执行 BAT,不会安装依赖,也不会下载模型;真正启动官方入口时,官方代码可能按自己的规则下载缺失资源、写缓存和输出文件。

IndexTTS 需要确认 2.5 模型目录和参考音频。GPT-SoVITS 需要参考音频、参考原文/语言,并在存在多个已保存模型组合时确认 weight.json 中的版本或权重。Gradio 接口会从实际服务的 /config 和 API 信息读取,插件不固定事件编号。
预览分享卡片长什么样 ↓abbccdd/dsh-localtts
分享 · DeepSeek Harness Hub
abbccdd/dsh-localtts

为 DeepSeek Harness 增加按协议配置的本地 HTTP API / JSONL worker…

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