前言

最近做了一个基于 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 privateofficial ❌ 写了 public
logo 相对路径 ❌ 写了 URL

修复:精简描述、删减标签、改 mark 为 private

坑 2:logo 字段不能用 URL(第二、三次构建失败)

这是最大的坑。我先后试了三种 logo 配置:

  1. Fork 仓库 URLhttps://cnb.cool/xzzlwl/market/-/git/raw/main/plugins/xzzlwl/funasr-spk/logo.png
  2. GitHub 头像直链https://avatars.githubusercontent.com/u/109945100?s=256&v=4
  3. 相对路径"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 插件开发的关键避坑点:

  1. logoreadme 必须用相对路径,CI 环境无外网
  2. description ≤ 130 字符,数一下中文字符数
  3. tags 最多 4 个,多了直接挂
  4. mark 只认 privateofficial,没有 public
  5. 构建日志 API 需要 repo-cnb-history:r 权限,且需重新创建令牌(不可追加权限);公开仓库默认有只读权限
  6. Docker 大模型镜像预下载模型,避免运行时超时

六、相关链接