dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
让 AI Agent 听懂音频:转写、鸟种识别、语音情感、环境声与音乐分析。全部本地运行,不用大模型。DeepSeek Harness 技能。
让 AI Agent 真正"听懂"音频 —— 全部本地运行,不上传云端,不用大模型。
一个 DeepSeek Harness(DSH)技能: 把音频转成 Agent 能推理的文字、数字和标签,覆盖语音、音乐、环境声、鸟种与情感。
一个音频大模型(如 Qwen3-Omni-30B)要 ~17GB,冷启动 30–90 秒, 输出还是不可复现的自由文本。
这个项目走另一条路:把"一个大模型"换成"一把小尺子"—— 每条能力轴用一个专用小工具,按需组合:
| 层 | 做什么 | 引擎 | 体积 | 耗时 |
|---|---|---|---|---|
| L1 声学画像 | 音高/音调走向/音域/起伏、语速、能量与停顿、节奏、调性、音色 | librosa(纯 DSP) | 0 | 2–4s |
| L2 转写 | 语音 → 文字(分段时间戳;--timestamps 可到词级) | Qwen3-ASR-0.6B(MLX) | 1.9GB | ~10× 实时 |
| L3 事件识别 | 动物/鸟虫、自然、人声、乐器、城市噪音(521 类) | YAMNet(ONNX) | 16MB | <1s |
| L4-A 鸟种 | 具体到物种(6522 种,含中文名) | BirdNET v2.4 | 52MB | 秒级 |
| L4-B 情感 | 9 类语音情感 | emotion2vec_plus_large | 1.8GB | 1–3s(MPS/常驻) |
自动分流:先做廉价声学预分类,再决定跑哪几层。 环境声若被 L3 判为动物,会自动接 L4-A 继续问到物种级—— "这是什么在叫"可以一路问到"这是黑顶麻雀"。
不是"在我造的样本上还行",下面是真实数据:
BirdNET 鸟种识别 —— 标注物种的真实录音(Arremon abeillei):
| 时间段 | 检出 | 置信度 |
|---|---|---|
| 0–3s | 黑顶麻雀 Arremon abeillei | 0.991 |
| 12–14s | 黑顶麻雀 | 0.875 |
阴性对照:合成鸟叫 → 0 检出(不硬猜物种);中文人声 → 判为 Human vocal(内置非鸟类拒识类)。
emotion2vec 情感识别:官方真人示例 → 愤怒 1.0000;中文中性语音 → 中性 1.00。
转写:中文 46.5s 音频 → 4.8s 转完(≈10× 实时),自动切 3 段带时间戳。
前置:macOS(Apple Silicon)+ uv + ffmpeg。
# 1) 放到 DSH 技能目录
git clone https://github.com/liyixuan201211/dsh-audio-read ~/.dsh/skills/audio-read
cd ~/.dsh/skills/audio-read
# 2) 独立 Python 环境(不污染系统)
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python \
numpy scipy soundfile librosa onnxruntime \
torch transformers funasr birdnet
# 3) 自检:告诉你哪一层就位、哪一层还缺什么
node scripts/audio.mjs --doctor
模型会在首次使用时自动下载(YAMNet 16MB 来自 hf-mirror;BirdNET 52MB 来自 Zenodo; emotion2vec 来自 ModelScope)。L2 转写需要额外装 mlx-qwen3-asr 并下载 Qwen3-ASR-0.6B。
国内网络提示:PyPI 走腾讯镜像直连可到 9MB/s,比走代理快得多:
export UV_DEFAULT_INDEX=https://mirrors.cloud.tencent.com/pypi/simple/
A=~/.dsh/skills/audio-read/scripts/audio.mjs
# 自动判断内容类型并分流(最常用)
node $A ~/Desktop/录音.m4a
# 只转写(快)
node $A 会议.mp3 --mode transcribe
# 只做声学画像(音高/节奏/调性)
node $A 歌曲.mp3 --mode acoustic
# 鸟种识别
node $A 野外录音.wav --birds
# 语音情感
node $A 语音.wav --emotion
# 环境声识别(零样本类目)
node $A 野外录音.wav --semantic
# 自检
node $A --doctor
输出是单行 JSON:acousticSummary(中文摘要)、transcript、semantic、birds、emotion、
以及落盘文件路径(长音频会给有界预览 + 完整文件,避免撑爆上下文)。
grep。加 --timestamps 会多跑一个强制对齐模型(Qwen3-ForcedAligner-0.6B),
把每个字/词的时间都标出来,适合做字幕:
node scripts/audio.mjs 会议.wav --language zh --timestamps
# → files.srt 是句级字幕
为什么字幕要自己重算:对齐器会丢掉标点,底层自带 SRT 因此退化成"按字数硬切",
中文实测切出「今天下午三点开会请准 / 时到会议室我们要讨论」这种断句。
本仓库用带标点的原文重建句子边界(scripts/lib/subtitle.mjs),
同一段音频切出 3 句干净的句子:
1 00:00:00,000 --> 00:00:04,080 今天下午三点开会,请准时到会议室。
2 00:00:04,320 --> 00:00:07,280 我们要讨论项目进度和人员安排。
3 00:00:07,440 --> 00:00:11,360 另外,服务器成本超支了,需要重新评估。
audio-read/
├── SKILL.md # 给 Agent 看的说明书(含 17 条实测坑)
├── config.example.json # 复制成 config.json 可覆盖默认值
└── scripts/
├── audio.mjs # 入口:探测 → 声学 → 分流 → 各层 → 落盘
├── asr.mjs # L2:Qwen3-ASR 封装
├── lib/{config,probe}.mjs
└── py/
├── acoustic.py # L1:声学画像 + 内容预分类
├── semantic.py # L3:YAMNet
├── birds.py # L4-A:BirdNET
├── emotion.py # L4-B:客户端
└── emotion_server.py# L4-B:常驻服务
MIT。第三方模型的许可见各自仓库(BirdNET 为 CC-BY-NC-SA,仅限非商业用途)。