你的插件
导入播客、导出到 Anki、接上你常用的词典……应用做不到的,插件可以做。写好以后提交,审过就出现在这里。
写一个插件Shadowing 0.9 起
插件给应用加上它本身不带的功能,比如复制一个 YouTube 链接、回到应用按 ⌘V,音频和人工字幕就进了你的文件夹。这里的插件都审过源代码,免费下载;你写的插件,也可以提交到这里。
正在读取插件列表…
导入播客、导出到 Anki、接上你常用的词典……应用做不到的,插件可以做。写好以后提交,审过就出现在这里。
写一个插件现在先在这里下载、从文件夹安装。在应用里直接浏览、一键安装和更新还在做。
点插件上的「下载」,得到一个 .zip。
在“下载”文件夹里双击这个 zip,得到插件的文件夹,比如 youtube。
在 Shadowing 里打开 设置 → 插件,点「从文件夹安装…」,选刚才解压出的文件夹。
设置里会列出插件是谁写的、会联网到哪里、会下载或运行什么,确认后点「安装」。不想用了,在同一个地方删除。
插件是运行在你 Mac 上的程序。应用不会把你的文件夹和钥匙串里的 Key 交给插件,但系统层面拦不住一个原生程序,所以这里只放审过源代码的插件。从别处拿到的插件,只装你信任的。
插件是一个程序加一个 manifest.json。应用要用它时启动这个程序,在标准输入输出上一行一条 JSON-RPC 消息(和 LSP、MCP 同一种做法),用完就结束。崩了、卡了都不影响播放。
manifest.json:它是谁、程序在哪、接哪些链接、会联网到哪里
{
"id": "podcast",
"name": "播客导入",
"version": "0.1.0",
"protocol": 1,
"minAppVersion": "0.9.0",
"author": "你的名字",
"description": "粘贴播客单集的链接,导入音频。",
"main": { "darwin-arm64": "bin/podcast" },
"contributes": {
"importers": [{
"id": "episode",
"title": "播客",
"match": ["https://*.example.fm/episodes/*"]
}]
},
"permissions": {
"network": ["example.fm"],
"runs": "只下载这一集的音频"
}
}
一次导入:先读出是什么,确认后再下载(→ 应用发出,← 插件回答)
→ initialize { protocol, appVersion, dataDir }
← { "name": "播客导入", "version": "0.1.0" }
→ import/resolve { url, importer }
← { "title": "第 42 集", "duration": 1834.5, "subtitles": [] }
→ import/run { url, importer, outDir, subtitles }
← progress { "message": "下载音频", "done": 4200000, "total": 10800000 }
← { "files": [{ "path": "42.mp3", "kind": "audio" }] }
manifest.json 加上程序(放在 bin/)。程序要能直接在 Mac 上运行:Rust、Go、Swift 编译出来的都行,Mac 自带的 shell 脚本也行。import/resolve 读出标题、时长、有哪些字幕,给用户确认;import/run 把音频和字幕下载到应用给的暂存文件夹,中间发 progress 报进度。出错时回一句中文,应用直接显示给用户。data/ 写。应用检查下载的文件、用标题起好名字,再放进用户的文件夹;字幕存成可以移除的导入字幕。每个插件都先读过源代码、核对过安装包才放上来,下载的人可以放心一点。提交需要一个 GitHub 账号。
放在 GitHub 或别的公开的地方。审核要读源代码,看它会联网到哪里、会下载和运行什么。
把插件文件夹(manifest.json 和 bin/)压成一个 zip,最好作为源代码仓库 Release 的附件发布。
在 GitHub 上填「提交插件」:源代码地址、zip 的链接,也可以把 zip 直接拖进表单上传。
我们读源代码、核对 zip 是用这份代码构建的,把它的 SHA-256 记进插件列表,之后就出现在这一页。发新版本时再提交一次。