Use when 王建硕 wants to turn his uploaded VoiceDrop voice memos into 微信公众号 article drafts — pulling the unprocessed recordings sitting on jianshuo.dev/files (the R2 inbox), transcribing them, and mining articles from each. Triggers — "处理 VoiceDrop 录音", "把新录音挖成文章", "口述备忘变文章", "处理一下我的录音", "/wjs-mining-voicedrop".
npx skills add https://github.com/jianshuo/claude-skills --skill wjs-mining-voicedrop
VoiceDrop 收件箱(jianshuo.dev/files 上的 VoiceDrop-*.m4a)→ 逐条转写 → 交给 wjs-mining-articles 出公众号草稿。这是 VoiceDrop iOS app(开口即录、停即上传)的 Mac 端闭环。
本 skill 自身的产出 = ① 公众号草稿(~/code/wechat-publish/)+ ② 本地音频/SRT 存档(~/code/voicedrop/archive/)+ ③ R2 上的处理标记(articles/<stem>.json 或 .empty)+ ④ 一份批次报告(处理几条、各出几篇、哪些标了无语音及原因、还剩几条未处理)。 完整接口契约见 agents/interface.yaml。
复用,不重写。 本 skill 只做两件本身没有的事:收件箱的进出(列/下载/标记)和逐条编排。转写交 wjs-transcribing-audio,成文交 wjs-mining-articles,一行都不重写。
R2 永不删,用标记文件表示处理状态。 音频一直留在 R2,直到用户自己在 app 里删。「未处理」= 还没有 articles/<stem>.json(已成文)也没有 articles/<stem>.empty(无语音)标记的 VoiceDrop-*.m4a;list 已自动只列未处理的。一条成功成文后写 mark-done,没语音/损坏写 mark-empty——两者都让这条不再被重复处理。绝不 delete(delete 只留给用户在 app 里手动清理)。
/wjs-mining-voicedropwjs-mining-articleswjs-transcribing-audio 出 SRT,再 wjs-mining-articlesVoiceDrop-*.m4a 前缀,其余不碰~/code/.env 里有 FILES_TOKEN(收件箱鉴权)和火山 ASR creds(VOLC_ASR_* / VOLC_TTS_*,转写用)。set -a; source ~/code/.env; set +a。唯一的新增代码:scripts/voicedrop-inbox.sh(list / download / mark-done / mark-empty / delete,token 运行时从 ~/code/.env 读,绝不落代码)。list 只列未处理;mark-done/mark-empty 写处理标记;delete 只给手动清理用,成文流程不调它。
INBOX=~/.claude/skills/wjs-mining-voicedrop/scripts/voicedrop-inbox.sh
set -a; source ~/code/.env; set +a # FILES_TOKEN + 火山 ASR creds
用绝对路径 $INBOX 调脚本——不要写成 scripts/voicedrop-inbox.sh,那依赖「人恰好在 skill 根目录」这个隐藏假设,换目录就崩。
"$INBOX" list # 打印未处理的 VoiceDrop-*.m4a,一行一个
~/code/.env」并停,不进入循环。串行。批次韧性:单条任何一步失败 → 记录原因、跳到下一条、绝不中止整批、绝不漏标。 每条录音最终必须落到三个终态之一:已成文(mark-done)/ 无语音(mark-empty)/ 失败(不标,留待下次)——绝不「处理了却什么都没标」。对每个 <name>:
"$INBOX" download <name> ~/code/voicedrop/archive
音频落 ~/code/voicedrop/archive/<name>。R2 上的原件始终保留,本地这份只是离线副本。
dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$audio" 2>/dev/null)
dur 为空(非音频/损坏)→ "$INBOX" mark-empty <name> corrupt;< 1.0 秒(误传/静音)→ "$INBOX" mark-empty <name> silent。标完报告用户,跳到下一条——这条已是终态,不再重复处理。
wjs-transcribing-audio(中文走火山豆包 volc_asr_stream.py + build_srt_from_asr.py + 在 session 内做 AI 润色改错别字)。SRT 落 ~/code/voicedrop/archive/<stem>.srt。"$INBOX" mark-empty <name> no-speech,报告、跳下一条。wjs-mining-articles 跑它的完整流程——出选题清单(它的人工闸,照走别跳)、成文、建微信草稿。语音备忘多是短独白单主题,清单常只有 1 条,照常让用户确认。{"schema":2,"status":"ready","sourceAudio":"<name>","articles":[{"title","body"},…]},可含 transcript/srt)写到临时文件,再: "$INBOX" mark-done <name> /tmp/<stem>.json
这条就标成已成文、app 里也能看到,且不会被服务器或下次再挖。
转写失败 / 用户没勾任何选题 / 挖不出文章 → 不标 done 也不标 empty,留未处理,下次再来,报告原因。
处理了几条、各挖出几篇草稿(落在 ~/code/wechat-publish/)、哪些标了无语音及原因(corrupt/silent/no-speech)、本地存档路径、R2 还剩几条未处理。
download(存档) → 判别 → 成文 ? mark-done : 无语音 ? mark-empty : 留着不标
↑ 绝不 delete
mark-done;损坏/静音/无语音 → mark-empty(带 reason);真失败(转写报错、用户中止、没挖出文章)→ 不标,留未处理下次再试。绝不出现「跑过一遍却没留任何标记」——那会让这条每次都被重新处理。| 复用 | 用法 |
|---|---|
| wjs-transcribing-audio | 每条音频 → SRT(中文火山豆包,含润色改错别字) |
| wjs-mining-articles | 每个 SRT → 选题清单 → 成文 → 微信草稿(含它自己的人工闸) |
| ~/code/.env | FILES_TOKEN + 火山 ASR creds |
| VoiceDrop app | 上游:文件名形如 VoiceDrop-<时间戳>-<时长>-<星期>-<时段>[-<城市-城区>].m4a(全 ASCII)。本 skill 靠 VoiceDrop- 前缀 + .m4a 后缀认领;中间的时长/星期/时段/地点是上下文,成文时可借来判断这条录音是何时何地的口述 |
| 服务器 miner(~/code/voicedrop/mining/mine.py,每 2h) | 同一套标记约定:成文写 articles/<stem>.json、无语音写 articles/<stem>.empty、永不删音频。它会自动处理收件箱,所以本 skill 跑时 list 常常已经空了——这是预期,本 skill 是手动补位 |
本 skill 唯一新增代码:scripts/voicedrop-inbox.sh。
mark-done/mark-empty;delete 仅用户在 app 里手动用。mark-empty,否则它每次都被重新下载转写,永远「待处理」。mark-done。wjs-mining-articles 的选题闸自己硬写 —— 那个闸是它的设计,照走。VoiceDrop-*.m4a 前缀;list 也只列未处理的。mark-empty,别送去转写。Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.
Downloads videos from YouTube and other platforms for offline viewing, editing, or archival. Handles various formats and quality options.
Lightweight WSI tile extraction and preprocessing. Use for basic slide processing tissue detection, tile extraction, stain normalization for H&E images. Best for simple pipelines, dataset preparation, quick tile-based analysis. For advanced spatial proteomics, multiplexed imaging, or deep learning pipelines use pathml.
Microscopy data management platform. Access images via Python, retrieve datasets, analyze pixels, manage ROIs/annotations, batch processing, for high-content screening and microscopy workflows.
Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications.
This skill should be used when working with pre-trained transformer models for natural language processing, computer vision, audio, or multimodal tasks. Use for text generation, classification, question answering, translation, summarization, image classification, object detection, speech recognition, and fine-tuning models on custom datasets.
Take jianshuo/wjs-mining-voicedrop from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.