CNB 插件开发实战:从零到上架的踩坑记录
前言
最近做了一个基于 FunASR 的说话人识别插件,能输入音频 URL,输出带时间戳和说话人标注的文本。功能本身不复杂,但提交到 CNB 插件市场 的过程却踩了不少坑,构建挂了四次才通过。
这篇文章以这个插件为案例,完整记录 CNB 插件开发的流程和避坑指南。
一、插件概览
FunASR 说话人识别插件(xzzlwl/funasr-spk):
- 功能:基于 FunASR SenseVoiceSmall 模型,支持中/英/日/粤语音频转文字 + 说话人识别
- 输入:公开可访问的音频文件 URL
- 输出:带时间戳、说话人标注的文本
- 触发方式:API 触发(云原生构建)
二、开发流程
2.1 创建仓库与 Docker 构建
首先在 CNB 上创建仓库,编写 Dockerfile 和推理脚本 inference.py:
FROM python:3.10-slim
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 关键:在构建阶段预下载模型,避免每次运行都下载 893MB
RUN python -c "from modelscope import snapshot_download; snapshot_download('iic/SenseVoiceSmall', local_dir='./model')"
COPY . .
CMD ["python", "inference.py"]
2.2 Docker 制品推送
利用 CNB 的云原生构建能力,构建完成后自动推送同名 Docker 制品,无需额外登录。
三、提交插件市场的踩坑记录
功能开发完成后,提交到 cnb/plugins/market 的 PR 才是真正的噩梦开始。
坑 1:plugin-meta.json 字段限制(第一次构建失败)
plugin-meta.json 有严格的格式要求:
| 字段 | 限制 | 我的错误 |
|---|---|---|
name |
≤ 24 字符 | ✅ 没问题 |
description |
≤ 130 字符 | ❌ 写了 140 字 |
tags |
≤ 4 个 | ❌ 放了 5 个 |
mark |
private 或 official |
❌ 写了 public |
logo |
相对路径 | ❌ 写了 URL |
修复:精简描述、删减标签、改 mark 为 private。
坑 2:logo 字段不能用 URL(第二、三次构建失败)
这是最大的坑。我先后试了三种 logo 配置:
- Fork 仓库 URL:
https://cnb.cool/xzzlwl/market/-/git/raw/main/plugins/xzzlwl/funasr-spk/logo.png - GitHub 头像直链:
https://avatars.githubusercontent.com/u/109945100?s=256&v=4 - 相对路径:
"logo.png"✅
前两种都报错:logo 文件不存在或无法读取。
根本原因:CNB 的 plugin-lint 在 CI 环境中运行,无法访问任何外部 URL。它只能读取仓库内的文件。
正确做法:将 logo 文件放在插件目录下,plugin-meta.json 中用相对路径引用:
{
"logo": "logo.png"
}
同理,readme 字段也应使用相对路径 "README.md"。
坑 3:构建日志 API 权限
查询构建日志需要 repo-cnb-history:r 权限。如果你的 Access Token 没有这个权限,API 会返回 errcode: 5。
注意:在 CNB 的 个人设置 → 访问令牌(https://cnb.cool/profile/token)页面无法给已有令牌追加权限,只能重新创建一个带有 repo-cnb-history:r 权限的令牌。另外,公开仓库默认已有只读权限,私有仓库才需要手动添加。
四、最终的 plugin-meta.json
经过四次迭代,最终通过 lint 的配置如下:
{
"id": "xzzlwl/funasr-spk",
"name": "FunASR 说话人识别",
"description": "基于FunASR的音频转文字与说话人识别插件,支持中英日粤语,输入音频URL输出带时间戳文本。",
"tags": ["音频处理", "AI", "语音识别", "说话人识别"],
"readme": "README.md",
"logo": "logo.png",
"images": "https://hub.docker.com/r/xzzlwl/funasr-spk/tags",
"repository": "https://cnb.cool/xzzlwl/funasr-spk",
"homepage": "https://modelscope.github.io/FunASR/",
"bugs": "https://cnb.cool/xzzlwl/funasr-spk/-/issues",
"locales": {
"en": {
"name": "FunASR Speaker Recognition",
"description": "Audio transcription and speaker recognition plugin powered by FunASR SenseVoiceSmall. Supports Chinese, English, Japanese and Cantonese."
}
},
"mark": "private",
"generate_from": "xzzlwl/market"
}
五、避坑清单
总结一下 CNB 插件开发的关键避坑点:
logo和readme必须用相对路径,CI 环境无外网description≤ 130 字符,数一下中文字符数tags最多 4 个,多了直接挂mark只认private或official,没有public- 构建日志 API 需要
repo-cnb-history:r权限,且需重新创建令牌(不可追加权限);公开仓库默认有只读权限 - Docker 大模型镜像预下载模型,避免运行时超时
六、相关链接
- 插件仓库:xzzlwl/funasr-spk
- 插件市场 PR:cnb/plugins/market#740
- CNB 插件开发文档:docs.cnb.cool
- FunASR 项目:github.com/modelscope/FunASR