dsh-typewriter-blip

DSH PLUGIN模型与账号接入

仓库 nsswkj/dsh-typewriter-blip

模型与账号接入 未标注验证等级 安全审查:未标注 可信度:未标注 可安装插件

为 DeepSeek Harness 助手回答加上逐字打字机音效,音色可换可自定义,窗口最小化或切到后台时照常发声。

一句话选型结论

按资料字段整理

dsh-typewriter-blip 是模型与账号接入类的 DSH 可安装插件,未做沙盒验证,暂无安全审查结论,列出 5 项功能,没有现成安装命令,需要按仓库 README 接入。验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么;涉及密钥或系统权限的,建议先在隔离环境试装。

分类模型与账号接入 收录类型可安装插件 验证等级未标注验证等级 安全审查未标注
验证等级 UNKNOWN 未标注验证等级
GitHub 星标 0 复刻 0 · 未关闭 issue 0
最近更新 2026-10-09 创建于 2026-10-09
README 12.8 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
  1. 1
    确认版本与运行环境

    仓库没有标注兼容版本与 Node.js 要求,先确认你的 DSH 版本能装,再继续。

  2. 2
    执行安装命令

    在 DSH 里执行上面的命令;多包仓库要注意区分具体子包名,别装错包。

  3. 3
    确认已挂载

    用 dsh plugin list 查看列表里是否出现这个插件,出现即挂载成功。

  4. 4
    试跑并检查权限

    加载后跑一个最小用例,确认它能正常工作;同时看它申请了哪些文件、命令或网络权限。

兼容 DSH 版本未标注版本不匹配时安装会报错
Node.js 要求未标注来自仓库 package.json 的 engines 字段
前置依赖无需要同时安装的同级依赖
npm 包名未发布到 npm可用 npm view 查看包信息

能做什么

5 项功能
字段来自项目仓库与公开索引,中文说明由本站标注

dsh-typewriter-blip:为 DeepSeek Harness 加上逐字发声的语音反馈

  • 回答流式逐字发声
  • 柔和/打字机/自定义音色
  • 音高音量与间隔可调
  • 后台最小化照常发声
  • 只对助手回答发声

上游标签

audiodeepseek-harnessdshdsh-pluginweb-audio

验证等级与安全审查

未标注验证等级
自动化流程结论,不是人工审核
验证等级未标注验证等级上游未给出验证结论,安装前请自行确认
安全审查未标注静态分析结论,未标注不代表已通过审查
仓库健康度未标注按仓库活跃度与最近更新时间给出
可信度未标注综合仓库活跃度与验证结果

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 列出了 5 项功能,能直接看出它解决什么问题。

先想清楚的地方

  • 安全审查还没结论,装之前先看仓库改了什么、要什么权限。
  • 没有现成安装命令,要按仓库 README 手动接入。
  • 验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么。

更适合

  • 需要在模型与账号接入场景里给 DSH 补能力的人。
  • 能接受在本地装依赖、愿意自己确认权限的人。

不太适合

  • 只使用 DSH 官方内置能力、不接受第三方插件的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
插件验证等级安全审查星标兼容版本安装命令
dsh-typewriter-blip当前 未做沙盒验证 未标注 0 未标注 无
archify L4 · 沙盒安装通过 低风险 8.0 万 未标注 有
DeepSeek-Reasonix L4 · 沙盒安装通过 低风险 3.6 万 未标注 有
nocobase L3 · 安装规范通过 低风险 2.5 万 0.1.1-rc.2 无
learn-harness-engineering L4 · 沙盒安装通过 低风险 2.0 万 未标注 有
dsh-our-free-model 未做沙盒验证 未标注 8,064 未标注 无

仓库档案

模型与账号接入
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方nsswkj仓库 dsh-typewriter-blip · 默认分支 main
分类模型与账号接入model-inference
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言JavaScript仓库主语言
许可证MIT商用或二次分发前请确认条款原文
星标 / 复刻 / issue0 / 0 / 0收录时的数值,非实时
创建 / 更新2026-10-09 · 2026-10-09最后推送 2026-10-11
本站收录2026-10-09首次进入本站目录的时间

README 全文

12.8 KB
作者原文,中文版优先;只做安全转义,不改内容

说话音效 / Speech Blip

模型回答时逐字发出音效,音色可换,也可以自己调。
进入对话时不发声,模型说完立刻停;窗口最小化、被挡住、或者切到别的标签页时照常发声。

安装

插件市场(dshmarket)里搜说话音效,点一下安装;或者直接装 npm 包:

dsh plugin --profile desktop add dsh-typewriter-blip

也可以从仓库装源码(内容和 npm 包一致):

dsh plugin --profile desktop add github:nsswkj/dsh-typewriter-blip

装完刷新一次 Harness 页面即可,无需重启。

用法

  1. 插件安装后(profile:desktop),刷新一次 Harness 页面。
  2. 输入框上方会出现一个 ♪ 说话音效 按钮。
  3. 点它打开面板:
控件 作用
启用 总开关(关闭后不再发声,也不排队)
音色 柔和(三角波,默认)/ 打字机(锯齿 + 噪声瞬态)/ 自定义
自定义音色 两种来源:合成音色(波形 方波/三角/锯齿/正弦 + 基频 + 音长 + 亮度)或音频文件(本地 audio/*,可调播放速度,每个字最多播 0.6 秒)。动这里的任何一项会自动切到「自定义」
音高 / 音量 ±12 半音升降调;0–100% 音量
最小间隔 两个音之间的最小毫秒数;流式输出很快时用它控制密度
说完即停 最后一个字之后多久掐掉还响着的音(默认 140 ms,且不会短于一次唤醒的间隔)。还没播的队列不会整段丢掉:前台最多 6 个字、不到三分之一秒就播完;后台按下面「后台也要发声」的规则只留最后 0.3 秒
跳过空格 空格、换行不发声
只对回答发声 只对助手回答的文字发声;工具调用、思考过程(reasoning)和你的消息都不响。默认开
随机音高 每个音随机偏移的半音数,让声音更自然。滑条到 2,右边的输入框可以直接填到 24;自定义音频也生效——音频文件没法改音高,插件用同一份半音偏移换算成播放速度(重采样),所以调高时那个音也会短一点
随机音量 每个音随机改变多少音量,滑条到 ±50%,输入框可以直接填到 ±100%。随机量加在每个音自己的增益上,不动总音量开关
试听 连播几个字试听当前音色。一次只能听一遍:按下后按钮变灰显示「试听中…」,最后一个字播完才解锁,中途再点无效
恢复默认 回到出厂设置

设置即时生效并自动保存(localStorage,键 dsh:typewriter-blip:v1)。
按钮上只有 ♪ 说话音效 两个元素,不再显示发声计数。
「随机音高」和「随机音量」右边的数值框可以直接输入,超过滑条上限也照收(上限是
settings.js 里的 JITTER_MAX / VOLUME_JITTER_MAX);输入即生效,还解析不出数字的
半截文本(空框、只有一个 -)不会被写进设置。

面板开在按钮上方(输入框贴着窗口底边,下方没有地方放),并且高度只取按钮上方
到窗口顶边之间的空间,内容多就在面板里滚动;只有按钮靠近窗口顶部、上方确实放不下时
才会翻到下方。出现时用 ease-out 缓动淡入(180 ms,从按钮那一侧滑进来),关闭时先播
完 140 ms 的淡出再从 DOM 里移除,prefers-reduced-motion 下两个动画都会关掉。

什么时候响,什么时候不响

用户要的是"说话"的感觉,而浏览器里只有一个越来越长的 DOM,所以下面三件事必须分开:

  • 进入对话 / 历史消息整段挂载:一律不响。第一次看到的容器只建立基线。
  • 宿主复用了行元素(换会话、虚拟滚动、Markdown 重新渲染):新文本不再以旧文本开头、
    或者变短了,就当成换了一行内容,重新建立基线,不发声。
  • 一次刷新里整块出现:那是挂载,不是打字(首次增长 > 24 字、之后单帧 > 160 字都按挂载处理)。

反向的两个规则让声音跟得上说话:

  • 回答停止:最后一个字之后超过「说完即停」的窗口没有任何新字符,就 cut() 掉所有
    已排程的音——否则队列里剩下的字会继续说,用户听到的就是"说完了还在响"。队列本身
    不丢
    ,只裁到还剩最后 0.3 秒(PLAYOUT_MS):前台队列最多 6 个字(MAX_PENDING),
    按「最小间隔」算不到三分之一秒就播完,所以一个字都不会少;以前一次性丢掉整个队列,
    才是"换完音效第一句断断续续、只响了一半"的根因。
  • 跟得上说话:音效速率上限就是「最小间隔」(默认 45 ms ≈ 每秒 22 个音),而模型一次
    chunk 能吐几十个字,所以队列只存得下最新几个字(溢出丢最旧的,前台 6 个、后台按
    lead 放宽)。队列长了不会让声音更丰富,只会让声音落后文本一两秒——而这份落后迟早
    会被整段丢掉。
  • 只对回答发声:data-chat-flow-kind 必须是 assistant-step,且 data-chat-group-part
    不是 reasoning;代码块、JSON 块、按钮、时间戳等 UI 部分一律不计入。

后台也要发声

最小化、被别的窗口盖住、或者切到别的标签页时,浏览器会停止产生动画帧(requestAnimationFrame
一次都不再触发),并把定时器压到大约一秒一次。排程原来完全挂在动画帧上,所以窗口一进后台就彻底
没声了。现在:

  • 两个时钟:动画帧照旧是主时钟(页面可见时它总是先醒,定时器不参与);另一个 250 ms 的定时器
    盯着帧,超过 400 ms 没有帧就接管排程。它不看 Page Visibility API,因为被遮挡的窗口可能既不产生
    帧、也不肯说自己隐藏了。
  • 按唤醒间隔缓冲:driver 用两次唤醒之间的间隔算出 lead(提前排到音频时钟上的秒数),队列容量
    也由它决定——前台的 lead 是 0.02 秒(⇒ 6 个字),后台是 1.25 秒(⇒ 30 个字,上限 MAX_QUEUE 48)。
    音频时钟不受页面可见性影响,所以只要声音已经排在它上面,就一定响得出来。
  • 收到文字本身就是一次唤醒:后台定时器可能被压到一分钟一次,那时答案早就结束了,所以每个字符
    批次进来都会直接 tick 一次;页面一隐藏也会立刻把 lead 抬上去,而不是等第一次粗唤醒才发现。
  • 说完即停仍然成立:文字停了以后队列会被裁到只剩最后 0.3 秒(PLAYOUT_MS)再播完。前台队列本来
    就短于 0.3 秒,所以「换完音效第一句断断续续」那个 bug 不会因为这次改动回来;掐音的窗口也不会短于
    一次唤醒的间隔——一秒宽的时钟判断不了 140 毫秒的安静,否则 chunk 之间的每个停顿都会被当成"说完了",
    把刚填好的缓冲整段掐掉。
  • 回到前台时 lead 立刻降回帧级并重新开始测量——否则前台会拖着后台那一整秒的积压说话。

音色怎么来的

内置音色由 src/voices.js 的 PRESETS 决定波形、基频、时长、滤波与按字符类别的移调:
柔和 是三角波、打字机 是锯齿加一段高通噪声瞬态。
"自定义"音色由设置里的 custom 字段决定(CUSTOM_DEFAULTS 是出厂值):
source: "synth" 时用 wave/freq/duration/filter 合成,source: "sample" 时播放用户载入的音频。
要加一个内置音色:在 PRESETS 里加一条,再把 id 加进 PRESET_ORDER(PRESET_ORDER[0] 就是新装
默认音色);删掉一个音色不用管旧设置,normalizeSettings 会把认不出来的 id 收回默认值。

结构

package.json        清单:dsh.bundle.patch + dsh.client(web)
cordis.patch.yml    插入 id 为 typewriter-blip 的 Loader 行
index.js            Host 半:空实现(功能全在页面里)
src/settings.js     设置与 localStorage 持久化(含自定义音色)
src/voices.js       音色预设表 + 自定义音色的出厂值与波形表
src/audio.js        Web Audio 合成、采样播放、cut()
src/observer.js     回答文字 → 字符增量 → 排程发声 → 说完即停(音频时钟 + 自适应唤醒间隔)
src/client.js       输入框上方的按钮与面板(React)
build.mjs           把 src/ 拼成单文件 client.js
client.js           生成产物(浏览器模块图每个包只加载一个 ./client)
test.mjs            离线测试台
LICENSE             MIT

开发

页面里的模块图每个包只加载一个 ./client 产物,所以 client.js 是生成文件:
改 src/,然后

node build.mjs          # 重新生成 client.js
node test.mjs           # 离线检查(语法、设置、音色、音频、观察器、节奏、端到端)
node build.mjs --check  # 只检查产物是否过期

本机没有独立的 Node 时,可用 Electron 当 Node:

$env:ELECTRON_RUN_AS_NODE=1
& "C:\Program Files\DSH Desktop\DSH Desktop.exe" build.mjs

改完 client.js 需要刷新页面(或重启 DSH Desktop)才会加载新产物。

实现要点

  • 插件通过 conversation.composer.dock 这个 slot 把按钮挂到输入框上方,样式只用
    Harness 的 --dsw-alias-* / --dsw-specific-* 主题变量,跟随明暗主题。
  • 面板底色用的是 DSH 自己那套浮层表面,而不是随手挑的灰:--dsw-specific-menu
    (浅色 #f8f9fa94、深色 #43454a73)+ 同一支 --dsw-menu-backdrop-filter
    (blur(40px) saturate(150%))毛玻璃 + --dsw-elevation-prominent 投影,和 DSH 的
    stats 面板、各种菜单完全一致。原先用的 --dsw-alias-bg-overlay 是徽标底色
    (浅色 #e9ecf2、深色 #61666b),深色主题下面板会是一块偏亮的灰板,跟界面里其它
    表面都对不上——"背景色不随主题"就是这么来的。
  • 随机音高 / 随机音量 是逐字生成的:src/audio.js 的 pitchJitter() 给每个音一份
    随机半音,volumeScale() 给每个音一份随机增益(加在这个音自己的 gain 上,不碰总音量)。
    合成音色直接改频率/峰值;音频文件没法改音高,用的是同一份半音偏移换出来的
    playbackRate(重采样)
    ——"随机音高对自定义音频没用"就修在 #playSample 里。
    blipSeconds() 取最慢的那一档,所以试听的锁定时间不会短于任何一次实际发声。
  • 面板是 .twb-root 里的 position:absolute,所以 top/left 必须是相对按钮
    的偏移。一旦把窗口坐标当成局部偏移写进去,等于又叠了一次按钮自身的偏移——面板就会
    掉到屏幕外面去。这段换算抽成了纯函数 placePanel(),离线测试直接钉住它的算术。
  • 量面板尺寸只能用 offsetWidth/offsetHeight(布局盒),不能用
    getBoundingClientRect()
    :入场动画带 scale(.97),rect 返回的是动画中的视觉盒,
    拿它算位置会让面板低约 3%(底部压住按钮),直到下一次重新摆放才弹回去——就是"点一下
    面板才回到该在的位置"那个 bug。measurePanel() 固定了这条规则。
  • 逐字音效需要一个"新出现了几个字符"的信号。conversation.chat.node 的 props 里
    hookContext 只有 { turnData, disclosureReset },拿不到流式文本,所以插件观察
    Conversation 层已经打好的 data-chat-flow-kind 容器。
  • 发声在 Web Audio 的时钟上排程:每个音之间至少隔 最小间隔,一次唤醒最多补满 lead 那么长的
    一段(可见时是一帧的量,后台是一整秒),所以既不会在长时间隐藏后炸出一串音,也不会在两次唤醒
    之间静音。driver 不假设帧率,它只按自己观测到的唤醒间隔调整。
  • 排程是一次同步跑完的,所以后台那一下会把一整秒的音全部记进 voices——它们都还没轮到结束。因此
    "超额就掐掉最旧的一个"是错的(最旧的那个正是此刻在响的,会被拉成一秒长的音):#reap 只回收
    音频时钟已经越过的音,onended 照旧负责正常回收。
  • 试听不走 driver 的字符队列,而是直接把音排到音频时钟上,所以在它看来"一直没有任何
    新字符"="模型说完了",说完即停会在第一个音之后就把它掐掉。BlipDriver.hold(秒)
    在试听期间压住这个掐音;试听时长由 BlipAudio.blipSeconds()(单个音最长多久)加上
    排程跨度算出,同一段时间也用来锁住试听按钮。
  • 生成文件里的 loader 契约:window.__ModuleLoader__.load({ id, factory(require) }),
    factory 的第一个参数才是加载器的 require(react 只能从这里拿)。factory 里的任何
    异常都会落在启动批次里,会白屏整页,所以 build.mjs 给整段加载套了 try/catch。

常见问题

7 问
答案由本站依据条目字段整理,不引用上游原文
dsh-typewriter-blip 怎么安装?

本站没有抓到该条目的安装命令,请到仓库主页确认安装方式;这类条目多数是生态应用或尚未发布安装包的项目。

dsh-typewriter-blip 的验证等级是什么意思?

未标注验证等级。上游未给出验证结论,安装前请自行确认

dsh-typewriter-blip 安全吗?

未标注。

dsh-typewriter-blip 装之前要先确认什么?

先看它会读写哪些文件、执行哪些命令、连接哪些网络地址;验证等级只说明装得上、跑得起来,不等于安全。涉及密钥或系统权限的,建议先在隔离环境试装。

dsh-typewriter-blip 用的是什么许可证?

上游标注为 MIT。商用或二次分发前请到仓库确认许可证原文。

dsh-typewriter-blip 有哪些功能?

回答流式逐字发声、柔和/打字机/自定义音色、音高音量与间隔可调、后台最小化照常发声、只对助手回答发声。

这条记录的数据可靠吗?

本站按仓库名去重后合并整理,字段以作者仓库与 npm 元数据为准;安装命令、仓库地址与 README 保持原文,带 L4 / L5 标记的安装命令已在隔离沙盒里真实跑通。

模型与账号接入
按星标排序,可作替代方案

archify

archify

从仓库或系统描述生成经过校验的自包含交互式架构图、流程图、时序图、数据流图和生命周期图。

L4 · 沙盒安装通过 8.0 万 星

nocobase

nocobase

L3 · 安装规范通过 2.5 万 星

dsh-our-free-model

dsh-our-free-model

为 DeepSeek Harness 挂载免登录、免 API Key 的免费前沿模型通道,装完即用,并附用量看板与 OpenAI 兼容本地转

未标注验证等级 8,064 星

dsh-purge

dsh-purge

dsh-purge 是一款 DeepSeek Harness 设置插件,可修改默认副本、权限策略和工具限制,并添加规则卡片以分组应用补丁,支

L5 · 运行验证通过 4,573 星

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 —。