四源合一搜音声,在线播放还能推给智能体
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/15 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 133563825as-ai/dsh-asmrone该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · platform
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 20 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 46 处,展示前 45 条)
- 写入本地文件src/index.js:231
mkdirSync(dir, { recursive: true }) - 写入本地文件src/index.js:232
writeFileSync(join(dir, 'boot.log'), `${lines.join('\n')}\n`, 'utf8') - 发起网络请求client/client.js:338
const response = await fetch(url, init) - 读取剪贴板client/client.js:2707
const text = await navigator.clipboard.readText() - 发起网络请求src/api.js:77
const response = await fetch(url, { - 发起网络请求src/api.js:171
const response = await fetch(this.streamUrl(hash), { - 发起网络请求src/api.js:198
const response = await fetch(this.streamUrl(hash), { - 发起网络请求src/api.js:231
const response = await fetch(this.streamUrl(hash), { - 发起网络请求src/bilibili.js:277
const response = await fetch(`${this.#baseUrl}${pathname}?${query}`, { - 发起网络请求src/bilibili.js:351
const spiResponse = await fetch(`${this.#baseUrl}/x/frontend/finger/spi`, { headers }) - 发起网络请求src/bilibili.js:356
const navResponse = await fetch(`${this.#baseUrl}/x/web-interface/nav`, { - 发起网络请求src/bilibili.js:619
return await fetch(record.url, { method, headers, signal: controller.signal }) - 发起网络请求src/dlsite.js:345
async #fetch (url, { as = 'text', timeoutMs } = {}) { - 发起网络请求src/dlsite.js:350
const response = await fetch(url, { signal: controller.signal, headers: SITE_HEADERS }) - 发起网络请求src/dlsite.js:371
const response = await fetch(url, { - 发起网络请求src/dlsite.js:425
const html = await this.#fetch(url, { timeoutMs: Math.max(this.timeoutMs, 30000) }) - 发起网络请求src/dlsite.js:439
const html = await this.#fetch(url) - 发起网络请求src/dlsite.js:501
const response = await fetch(`${this.trialBaseUrl}/`, { - 发起网络请求src/doh.js:116
const response = await fetch( - 发起网络请求src/http.js:359
const upstream = await fetch(target, { method, headers }) - 读取本地文件src/http.js:436
total = statSync(target).size - 读取本地文件src/http.js:462
createReadStream(target, { start: range.start, end: range.end }).pipe(res) - 读取本地文件src/http.js:476
createReadStream(target).pipe(res) - 读取本地文件src/http.js:644
if (existsSync(filePath) && statSync(filePath).size > 1024) { - 读取本地文件src/http.js:644
if (existsSync(filePath) && statSync(filePath).size > 1024) { - 读取本地文件src/http.js:645
return { name, status: 'skipped', bytes: statSync(filePath).size } - 读取本地文件src/local.js:104
entries = readdirSync(dir, { withFileTypes: true }) - 读取本地文件src/local.js:120
stat = statSync(full) - 读取本地文件src/local.js:187
const exists = existsSync(root) - 读取本地文件src/local.js:191
isDirectory = statSync(root).isDirectory() - 读取本地文件src/local.js:315
if (!existsSync(real)) return null - 删除本地文件src/local.js:421
if (!dryRun) unlinkSync(safe) - 删除本地文件递归src/local.js:437
rmSync(dirInfo.real, { recursive: true, force: true }) - 写入本地文件src/trial.js:335
mkdirSync(dirname(filePath), { recursive: true }) - 写入本地文件src/trial.js:336
writeFileSync(filePath, data) - 读取本地文件src/store.js:77
if (existsSync(this.configPath)) { - 读取本地文件src/store.js:79
const parsed = JSON.parse(readFileSync(this.configPath, 'utf8')) - 读取本地文件src/store.js:112
return existsSync('/sdcard') ? '/sdcard/Download/ASMR' : join(this.dataRoot, 'downloads') - 写入本地文件src/store.js:129
mkdirSync(this.dataRoot, { recursive: true }) - 写入本地文件src/store.js:130
writeFileSync(this.configPath, `${JSON.stringify(this.current, null, 2)}\n`, 'utf8') - 写入本地文件src/store.js:142
mkdirSync(target, { recursive: true }) - 读取本地文件src/tools/download.js:106
if (existsSync(filePath) && statSync(filePath).size > 1024) { - 读取本地文件src/tools/download.js:106
if (existsSync(filePath) && statSync(filePath).size > 1024) { - 读取本地文件src/tools/download.js:107
return { name, status: 'skipped', bytes: statSync(filePath).size, track } - 写入本地文件src/tools/trial.js:198
writeFileSync(filePath, data)
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 音声库插件:asmr.one / B站 / DLsite 试听 / 本机曲库四源合一
README
由 DeepSeek 最新模型翻译生成dsh-asmrone
开源(MIT)的 DeepSeek Harness 专用插件:把 asmr.one (DLsite 同人音声整库镜像,六万余部)、B 站、DLsite 官方免费试听、以及手机本地已经下好的音声 四个来源接进对话 —— 搜作品、看音轨、在线播放(后台播放 + 拖进度)、按自己的权重重排结果、批量下载与删除,全程不必离开 DSH。带 Web 面板,也带一条让智能体直接推歌出声的通道。
四个来源对网络的要求不一样:asmr.one 与 DLsite 要代理;B 站和本机曲库不用 ——没挂梯子的时候也有得听。
装
dsh plugin --profile web add link:/root/dsh-asmrone
装完要重启 dsh 才生效(dsh plugin 只是 pnpm 转发,没有 reload 子命令)。
Web 面板
侧边栏底部一枚 音声库 按钮(跟会话管理插件同款双行样式),点开是居中面板:
- 顶部:搜索框(回车即搜)、排序下拉(销量 / 评分 / 发售日 / 最新上架)
- 筛选 chips:「只要中文」「排除女性向」,以及一枚 权重排序 开关
- 权重面板:销量 / 评分 / 评价数 / 新鲜度 四条滑块(0~2),松手即重排;另有候选池深度(1~5 页)与「推荐配置 / 归零」两个预设。
展开完整文档(README 剩余 1 节)
dsh-asmrone
开源(MIT)的 DeepSeek Harness 专用插件:把 asmr.one (DLsite 同人音声整库镜像,六万余部)、B 站、DLsite 官方免费试听、以及手机本地已经下好的音声 四个来源接进对话 —— 搜作品、看音轨、在线播放(后台播放 + 拖进度)、按自己的权重重排结果、批量下载与删除,全程不必离开 DSH。带 Web 面板,也带一条让智能体直接推歌出声的通道。
四个来源对网络的要求不一样:asmr.one 与 DLsite 要代理;B 站和本机曲库不用 ——没挂梯子的时候也有得听。
装
dsh plugin --profile web add link:/root/dsh-asmrone
装完要重启 dsh 才生效(dsh plugin 只是 pnpm 转发,没有 reload 子命令)。
Web 面板
侧边栏底部一枚 音声库 按钮(跟会话管理插件同款双行样式),点开是居中面板:
- 顶部:搜索框(回车即搜)、排序下拉(销量 / 评分 / 发售日 / 最新上架)
- 筛选 chips:「只要中文」「排除女性向」,以及一枚 权重排序 开关
- 权重面板:销量 / 评分 / 评价数 / 新鲜度 四条滑块(0~2),松手即重排;另有候选池深度(1~5 页)与「推荐配置 / 归零」两个预设。权重全 0 时走官方排序
- 作品卡片:封面、标题、社团、评分、销量、时长、声优、标签;开权重时右下角显示归一化得分
- 点卡片 → 音轨清单内联展开在该卡片正下方(不跳页、不开新窗口)
- 底栏常驻播放条:播放/暂停、可拖动的进度条、当前 / 总时长、音量
界面用 dsh 自己的设计令牌(--dsw-alias-*)与 #4f7cff 主色,纯 SVG 图标,跟随系统深浅色 —— 跟余额、会话管理两个插件是同一套观感。
后台播放
不在 React 树里,它是挂在 document.body 上的页面级元素。所以容器怎么重建都不影响它,具体表现:
- 关掉面板 → 继续放,屏幕底部留一条悬浮迷你条(播放/暂停、进度、停、展开)
- 切回对话页 → 继续放,迷你条跟着在
- 锁屏 / 通知栏 → 有系统媒体控制(MediaSession,含 ±15s / ±30s 跳转)
藏 audio 用 1px + opacity:0,没用 display:none —— 后者在部分 WebView 上会直接停播。
音频走 host 代理 /asmrone/stream 而不是前端直连 —— asmr.one 的 CDN 不回 CORS 头,前端 fetch 会被浏览器挡死;走代理还能把 302 与 Range 一并透传。
七个工具
| 工具 | 干什么 |
| asmr_search | 搜作品。关键词 / 排序 / 分页 / 中文版筛选 / 性别过滤,返回评分、销量、时长、声优、标签和作品页地址 |
| asmr_work | 列某部作品的完整音轨树,可顺带并发探测每轨体积 |
| asmr_local | 本地音声库:列已经下到手机上的作品与音轨、按名字/RJ 号找、直接推给面板播放。不需要网络 |
| asmr_play | 取音轨播放直链,并默认推给面板播放器立即出声(push:false 只取地址不打扰) |
| asmr_download | 批量下载音频到本机。默认只下 MP3、跳过已存在的文件、按作品名建子目录 |
| asmr_trial | 抓 DLsite 官方试听包(免费公开,免登录),自带 zip 解压与 Shift-JIS 文件名修复 |
| asmr_config | 查看 / 修改偏好;action=tags 直接列 asmr.one 的 422 个中文标签 |
典型用法:
asmr_search query=简体中文版 order=dl_count chineseOnly=true asmr_work id=1006912 resolveSizes=true asmr_play id=1006912 index=2 # 推第 2 轨到面板开始放 asmr_download id=1006912 title=舔耳按摩店 keyword=通常 asmr_trial workno=RJ01726233 download=true
智能体推歌
模型侧没有播放能力 —— asmr_play 顶多算出一串 URL,用户在对话里点了也听不到任何东西。
所以工具在返回直链的同时,往一个单槽待播队列里压一条;前端每 3 秒轮询 /asmrone/pending 取走并播放。配上 asmr-ambience 技能,用户说一句「失眠了」或「写东西想听点东西」就能直接出声,不用自己开面板。
队列刻意做得很小:只留最后一条 + 自增 seq + 2 分钟 TTL。
- 带 seq 轮询 → 同一首不会被反复重播
- TTL → 迟到的推送不会在半小时后突然响起来
- 单槽 → 连推三首只放最后一首,避免攒出一屋子「早就忘了的曲子」
技能在 /root/.dsh/skills/asmr-ambience/,里面还写了按音轨名判断开头直入还是慢热铺垫 的挑片规则(導入 / ご挨拶 这类第 1 轨是铺垫,本番 / いきなり 这类是直接开始)——助眠要挑前者,直奔主题要挑后者。
没开代理时:本地曲库
asmr.one 是境外站。没有代理时在线那条链路(搜索 / 音轨 / 封面 / 在线播放)整条不通 —— fetch failed、超时、连接重置都算。这时候面板不该变成一块砖,所以有一条完全离线的路:
- 面板:顶部「本地曲库」标签页。列出已经下到本机的音声(asmr_download 落的,加上 localDirs 指向的目录),点开是音轨,点了就放。
- 模型:asmr_local 工具。action=list 看有什么,action=play key=<作品> index=2 直接推给播放器。
- 播放:音频走 /asmrone/local-stream,从磁盘直读,支持 Range 拖进度,一个字节都不出网。
跟在线播放共用同一个播放器 —— 一样能后台播、一样有悬浮条。
扫盘带 60 秒缓存(5 G / 154 个文件要遍历目录树 + 逐个 stat),面板上的「重扫磁盘」强制刷新。
配置的目录不存在时面板会明确标出来,不会静默算成 0 部。
文件绝对路径只留在 host 侧:前端用 key+index 取流,不回传路径。
/asmrone/local-stream?path= 那条入口只对配置过的根目录内、且是音频扩展名的文件放行 ——前缀比较带分隔符(挡住 /x/asmr-evil 蹭 /x/asmr),并走 realpath 解析,符号链接也绕不出去。
HTTP 数据面
面板用的接口,挂在 webServer 的 /asmrone 前缀下。
| 方法与路径 | 说明 |
| GET /asmrone/config | 读配置 + 可用排序字段 |
| POST /asmrone/config | 改配置(白名单键) |
| GET /asmrone/search | q / order / page / pageSize / chinese / female |
| GET /asmrone/work | id= 取音轨树 |
| GET /asmrone/sizes | POST {hashes} 批量探测体积 |
| GET /asmrone/stream | hash= 音频代理,透传 302 与 Range |
| GET /asmrone/pending | since= 取待播条目(agent 推歌的拉取端) |
| GET /asmrone/local | 本地曲库列表;q= 过滤、force=1 绕过 60 秒缓存重扫 |
| GET /asmrone/local-stream | 本地文件流;key=+index= 或 path=,支持 Range |
| POST /asmrone/play | {id, hash?, index?} 解析音轨并入队,供 agent / 脚本推歌;带 localKey 时推本地文件 |
| POST /asmrone/download | {id, title?, hashes?, keyword?, includeWav?} |
| GET /asmrone/trial | rj= 探 DLsite 试听包 |
| GET /asmrone/tags | 标签表 |
配置
容器里的 JSON:<DSH_HOME>/asmrone/config.json,用 asmr_config 改,改完立即生效。
| 键 | 默认 | 说明 |
| outputDir | /sdcard/Download/ASMR(无外置存储时退回数据目录) | 下载落盘目录,同时是本地曲库的第 0 个根 |
| localDirs | [] | 额外的本地音声根目录(试听包解出来的、手动拷进去的都算) |
| languageFilter | male | male 剔除女性向/乙女向/BL;all 不过滤 |
| defaultOrder | dl_count | 默认排序字段 |
| downloadConcurrency | 4 | 下载并发,1~8 |
| maxWorkMb | 800 | 单个试听包体积上限 |
| pageSize | 20 | 搜索默认每页条数 |
基础设施项(接口地址、超时)在同名 profile 的 cordis.patch.yml 里覆盖,别改随包的 cordis.patch.yml —— 升级时会被覆盖。
接口依据
全部端点都实测过(2026-10):
| 端点 | 用途 |
| GET /api/search/{q} | 关键词搜索,支持 page / pageSize / order |
| GET /api/works | 全库列表 |
| GET /api/tags/ | 标签表,422 条,带 zh-cn 译名 |
| GET /api/tracks/{id} | 音轨树(folder / audio 嵌套) |
| GET /api/media/stream/{hash} | 音频流,302 跳 CDN,支持 Range |
GET /api/works/{id} 返回 401,作品详情从列表/搜索结果里取 —— 那些对象本身带全部字段。
DLsite 试听的坑
试听不是 mp3,是 zip 包。早期按 .mp3 拼 URL 全部 404,就因为后缀猜错了。
真实地址在 touch 页的 Nuxt payload 里:"trials":<索引> 指向无服务器序列化数组,展开后拿到 //trial.dlsite.com/doujin/RJ01727000/RJ01726233_trial.zip。
play.dlsite.com/api/viewer/work/<RJ> 只有元数据(sample_type: "image" 那类),拿不到音频。
不少音声作品确实只有图片试听,这时工具会明确报「无音频试听」。
zip 解压自己实现了(只用 zlib.inflateRawSync + 中央目录解析),因为宿主机器不一定有 unzip。老 DLsite 包的 Shift-JIS 文件名靠 TextDecoder('shift_jis') 还原。
开发
npm run check # 语法检查(src/ + src/tools/ + client/)
npm test # 45 个用例;在线用例网络不通时自动跳过
npm run verify:http # 起假 webServer 打真实端点(需要能访问 asmr.one)
test/rank.test.mjs 用了一个取巧但不偷工的做法:它从 client/client.js 里把 #region rank-core 那段纯函数截出来再求值。被测的就是线上那一份代码,不存在「测试跑的是另一份复制品」的漂移;谁把那段改成不纯(引用 window / react)会当场报错。
test/http-pending.test.mjs 则用假 api 顶掉 asmr.one,所以推歌链路离线也能验。
硬约束
运行期零依赖。 只 import Node 内置模块,dependencies 是空的。装了插件的人不需要往插件目录里塞 node_modules 软链 —— 也就不会出现「在插件目录跑一次 npm install 却写进宿主 node_modules」这类事故。src/define-tool.js 顶部有完整说明。
不内置内容偏好。 插件不预设任何题材倾向,性别过滤、排序、落盘目录全部来自可改的配置。
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
133563825as-ai/dsh-asmrone
四源合一搜音声,在线播放还能推给智能体
相关插件 · 平台集成
智能体工程课walkinglabs/learn-harness-engineering
一门项目制课程,教你搭建环境、管理状态、做验证、加控制机制,让 AI 编程智能体稳定干活。
★ 21,155已汉化DSH
71.7
视频翻译配音liuzhao1225/YouDub-webui
开源视频本地化工作台:导入视频,识别、翻译并逐句克隆原声,生成字幕和配音成片。
★ 5,792已汉化Cordis
71.4
失败经验库Ikalus1988/MisakaNet
📚 零依赖、由 git 支撑的微课程库,让 AI 智能体异步分享并检索经过验证的调试经验。| https://misakanet.org
★ 550已汉化DSH
71.2
桌面智能体工作区freestylefly/wesight
WeSight 是开源桌面控制台,面向本地 AI 智能体。它帮你安装或复用 Claude…
★ 933已汉化MCP
71
IM 机器人接入xmanrui/dsh-im
让 DeepSeek Harness 触手可及 Connecting DeepSeek Harness
★ 3,110已汉化DeepSeek 客户端
70.9
中国平台研究引擎Jesseovo/last30days-skill-cn
给 AI Agent 的中文互联网研究 Skill:检索 8 大平台最近 30…
★ 2,031已汉化DSH
70.7
这是你的仓库?认领条目