bnote — B站视频 → 讲义 + 学习笔记
〇、环境依赖与安装(新机器先做这一步)
这套 skill 自包含(SKILL.md + references/ + scripts/ + config/ + 代码都在本目录), 但 venv 与 ffmpeg 不随 skill 走 —— 换机器要各自准备,和大多数 CLI 工具的惯例一致。
适用平台:Linux / macOS(入口与安装脚本是 bash)。Windows 用 WSL2——原生 Windows 下 scripts/bnote、
scripts/setup-env.sh 跑不起来(venv 目录布局也不同);装好 WSL2 之后本节所有命令与 Linux 完全一致。
路径约定:本文件所在目录就是 skill 根;下文的相对路径(scripts/bnote、references/…)都相对它。
若当前工作目录不在 skill 根,请用 <skill根>/scripts/bnote 调用(数据根与 cwd 无关,见下)。
| 依赖 | 怎么装 | 说明 |
|---|---|---|
| Python >= 3.10 | 系统自带或 conda | 本项目代码不在 PyPI 上,所以随 skill 一起复制;第三方依赖由 setup-env.sh 安装 |
| venv + 依赖 | bash scripts/setup-env.sh |
建 venv 并 pip install -e .(默认清华镜像;海外/内网环境务必用 PIP_INDEX_URL 覆盖为可达索引) |
| ffmpeg | 建议装系统版:Linux apt install ffmpeg/macOS brew install ffmpeg(WSL2 里同 Linux);或在 [tools] ffmpeg 写绝对路径 / BN_TOOLS_FFMPEG |
--sections、HLS、音视频合并都需要能解析域名的 ffmpeg;imageio-ffmpeg 自带的静态包只作兜底(整集下载、抽帧、本地文件可用,但部分环境下碰域名直接崩)。环境有问题就在环境里解决(装系统 ffmpeg / 配绝对路径),不要绕过、也不要改代码去迁就 |
| 解释器 | config/local.toml 的 [tools] python,或 BN_PYTHON 环境变量 |
不想配也行:默认 python3;入口脚本 scripts/bnote 会自动读取 |
| B 站登录态 | scripts/bnote auth status / auth login(扫码,须本人操作) |
官方字幕轨(AI 与 CC)的列表目前只对登录态返回(游客实测恒为空;字幕文件本身不校验登录)。取不到字幕时有三条路:① 扫码登录 ② 自带 srt → --subtitle-backends file ③ 本地 ASR(需 pip install -e ".[asr]",装不装由使用者定)。走哪条由 agent 判断(agent 也可以去问用户),并在回报里写明选择与理由——不要默认把决定推给用户,也不要静默降级 |
bash scripts/setup-env.sh # 一次性:建 venv + 装依赖
scripts/bnote config --paths # 确认解释器与数据根解析正确
scripts/bnote auth status # 看登录态(没有就 auth login 扫码)
scripts/bnote run <URL> --page N --sections 00:00:00-00:05:00 # 先用 5 分钟验证管线跑得通,再全量
# 换/新数据根时没有登录态:先 `auth login`,或用 `--cookie-file <旧根>/state/auth/bilibili_cookies.txt` 复用旧根登录态
数据根(默认跟随 cwd,不写死绝对路径)
解析顺序:BNOTE_ROOT > config/local.toml 的 [paths] root > <当前工作目录>/.bnote。三个根分开:
<数据根>/state/<vid>/ 术语表、画像、登录态等跨集沉淀(删 cache 不带走)
<数据根>/cache/<vid>/ 中间产物:视频/音频/帧/OCR/切片结果(可随时删)
<数据根>/out/<vid>/ 交付物:lecture.md / note.md / slides/ / chapters/ / _meta/
其中 <vid> = <BV号>_p<分P>(例:BV1xxxxxxxxx_p20)。
out// 的内部结构是冻结的(正文用 ../slides/NNNN.jpg 相对引用),可配置的只是"根"。
每条命令都会打印解析后的根路径:取数命令(run/fetch/slides/meta)是完整横幅,其余命令是一行 [paths] … —— 路径不对会立刻看见。
除取数命令与 clean 外,数据根下没有该集的取数结果时,命令会直接以人话退出(并打印解析结果与补救命令),不会抛异常。
环境前提:数据根必须可写(cache/、out/ 都写在那里);skill 根不需要可写 —— 代码目录随 skill 分发,可能是只读安装(容器挂载 / 系统目录),运行期产物一律落在数据根。
换数据根=换一整套 state/(术语表、画像、登录态都跟着根走):要复用旧根的登录态就用 --cookie-file <旧根>/state/auth/bilibili_cookies.txt,或在新根重新 auth login。
注意:yt-dlp 会写回它读的那个 cookie 文件(刷新有效期),所以「跨根复用」会改到旧根的登录态文件——介意就先把 cookie 复制一份再指过去。
一、产出什么(三层,别混)
| 层 | 文件 | 是什么 | 读者 |
|---|---|---|---|
| L1 | transcript.md |
字幕原文(时间戳 + 文本;可能是平台 AI 轨、UP 上传的 CC,或本地 ASR) | 需要核对原话时 |
| L2 | lecture.md |
视频的文字版:按原时间轴、逐节、配图 | 想看完整内容的人 |
| L3 | note.md |
单 lecture 学习笔记:沿时间轴的 6-30 个关键节点 + 理解层注释 | 未来的自己(复习/检索) |
配套:lecture.standalone.md(图片内嵌,可直接外发)、slides/(每页终态帧)、
chapters/manifest.json(结构唯一来源)、_meta/(校验报告、派单 prompt、修复件、loop 台账、钩子)。
参考文件索引(按需读,正文不展开)
本 skill 依赖同目录的 references/:brief 派单时会读取 references/contracts/*.md 渲染任务书,
契约缺失会直接退出并提示「契约模板缺失」。只复制 SKILL.md 一个文件无法派单,references/ 要一起带上。
| 触发条件 | 读哪一份 |
|---|---|
| 你要派章节写作单时 | references/contracts/chapter_writer.md |
| 你要派笔记写作单时 | references/contracts/note_synth.md |
| 你要派结构修复单时 | references/contracts/fix.md |
| 你要派内容审阅单时 | references/contracts/review.md |
| 你要派信息流整理稿单时 | references/contracts/text_writer.md |
写正文、改正文格式,或要确认 check 的校验口径时 |
references/schema/body-contract.md |
| 改 manifest 字段或核对章节结构时 | references/schema/bnote-chapters-1.schema.json |
查参数默认值与 BN_<段>_<键> 覆盖写法时 |
references/params.md |
| 当前 harness 是 DSH,遇到委派工具或 ffmpeg 静态包的问题时 | references/dsh-notes.md |
| 需要查内容问题(漏讲/编造/图注错)时 | references/flow-review.md |
| 视频是口播/播客/访谈、画面无信息量时 | references/mode-text.md |
| 要把讲义导入 B 站笔记时 | references/export.md |
| 命令报错、校验失败或产物异常时 | references/troubleshooting.md |
| 要改工具、契约、参数或发布新版本时 | references/maintenance.md |
遇到问题时
产物异常时先读三个文件再判断:<out>/_meta/validation.json(机器可读、每条带 owner 路由)、validation.md(人读版)、loop.json(修复轮次台账);三者都正常才轮到怀疑 skill 与工具,逐条处置见 references/troubleshooting.md。
确认是 skill 的问题:到 https://github.com/HarveyZed/skill-bnote/issues 提 issue,附复现命令与 scripts/bnote config --paths 的输出,先去掉本机路径与个人信息。
也可以直接按 references/contracts/ 的契约自行修改,改完把改动说明写进回报。
二、端到端流程(含 agent 节点与门禁)
run 取数 ──▶ scaffold 分章 ──▶ brief --stage chapter ──▶ writers 并行写章
▲ 门禁① ▲ 门禁② │
└ 必须给 _groups.json └ 术语表必须已确认 ▼
collect 汇总补丁
│
retime(工具生成时间行)◀────┘
│
┌─────────────── check(结构,按 owner 路由)◀──────────────────────┘
│ 失败 → brief --stage fix --owner X → 发回原写手(不可用/被污染则改派新的干净子代理)→ 再 check(≤2 轮,超了升级给人)
▼ 通过
merge 出 lecture.md ──▶ brief --stage note ──▶ 单个全局 agent 写 note.md ──▶ note 校验/导钩子
│
└─(可选)review:brief --stage review → 独立 agent 只审内容 → review --ingest → 回同一条 fix 流
2.1 工具层(确定性,一步一命令,幂等)
auth 登录态(扫码 / 手动 / 检查)
run 取数一条龙:meta + media + subtitle + frames + segment + ocr + bundle
fetch 只取数(meta + media + subtitle),不做抽帧/切片
stream 信息流/口播类(无幻灯片):取音频+字幕 → 分段分块 → 整理稿(--assemble 拼接+校验)
meta 只取元信息(BV/p/cid/标题/时长/**简介/标签/分区**;旧缓存会自动补取这三样)
slides 只做抽帧 + 切片 + OCR(改了切片参数后重跑它,再跑 bundle)
bundle 只重建交付物(slides/ + slides.json + transcript.md),并快照旧讲义
scaffold 生成章节结构(manifest + _plan);分章是语义判断:给 --groups,或显式 --auto 接受一页一章(--no-leading-merge:封面不与目录合并)
brief 渲染派单 prompt:--stage chapter|note|fix|review
glossary 查看/修改/确认术语表(未确认时 brief --stage chapter 会拒绝派发)
patch 打印某章的补丁文件路径与 schema(写手写这里,不直接改 manifest)
collect 把 _meta/patch/<章号>.json 汇总进 manifest(多写手并发时不丢更新)
retime 按 slides.json 幂等重写小节时间行(时间由工具生成,写手不写时间)
check 结构校验;--chapter 06,07 限定作用域(写手自检用)
merge 合并讲义(结构校验通过才落盘)+ 刷新 note_brief
note 校验 note.md + 导出钩子
export 导出可粘贴进 B 站笔记的富文本(--format bili-note;--from lecture|note;CF_HTML + Windows 装载脚本;不调平台写接口)
xref 把多集的钩子与结构汇成跨讲综合工作表(--from-page A --to-page B;输出到 <数据根>/out/_xref/;缺集会拒绝)
remap 重切片后按时间重叠同步正文与 manifest 的图号(幂等;--from <旧 slides.json> 或 --force-map 强制重写;bundle 会自动快照上一版)
dispatch 登记 owner → 该章的原写手(修复时据此发回原作者)
fix 修复队列:不带参数打印待修清单与投递对象;--done <owner> 标记已修
review 摄入审阅发现(_meta/review_<n>.json)→ 归一 owner → 并入派修流
clean 清理 <URL> --page N(--level state|cache|out|all,先报占用;--dry-run 只看不删)
config 打印生效配置 / --paths 解析后的根 / --md 参数表
2.2 agent 层与两道门禁(防止关键判断被静默跳过)
- 分章(门禁①):
scaffold不给--groups就报错退出 —— 分章是语义判断,不接受"一页一章"的退化产物, 要看自动产物请显式--auto; - 术语表(门禁②):
brief --stage chapter在术语表未确认时拒绝派发(--allow-unconfirmed可显式越过); 理由:未确认的白名单会被写手当成"必须使用的写法",错的白名单比没有更糟; - 写作:每章一个写手,只写正文 + 自己的补丁文件
_meta/patch/NN.json(不并发改同一份 manifest); - 时间轴:写手只写
*slide 0006*/*slides 0014, 0015, 0016*,由retime展开时间; - 同页阶段合并:由 writer 看图决定(切片层不做),结果记进 manifest 的
stage_merges; - 笔记:单个全局 agent 读
note_brief.md+ 全部章节写note.md(不碎片化)。
2.3 派单方式:写手 / 笔记用「全新上下文」的子代理
派写手、派笔记这类独立任务,用全新上下文的委派工具(DSH 里是 spawn 语义的 subagent):子代理只拿到任务书,
不继承父会话历史——上下文小,也不会沿用父会话的角色与目标。任务书必须自包含:读哪些文件(契约 / 字幕 / slides)、
写哪些文件、不许动什么(chapters/manifest.json、仓库、已装副本)。
继承父会话全部轮次的 fork 语义,只适合「接着当前这段对话继续干活」。
若当前会话拿不到这类工具(DSH 有已知缺陷、官方未修),判别与绕法见
references/dsh-notes.md—— 不要用 fork 顶替。
2.4 修复与轮次(loop 必须真的能 loop)
工具负责把修复件写好、把队列与轮次算出来;投递由编排者执行 —— 默认发回该章的「原写作 agent」
(send_message 或你所用 harness 的等价工具):它知道这章为什么这样写,改得最准。修复件仍要自包含
(错误原文 + fix_hint + 文件路径 + 只改此处)。
只有两种情况才改派一个新的干净子代理(只带修复件):① 原 agent 已不可用(会话结束/被清理);
② 原 agent 已被污染或跑偏(例如它是 fork 出来的、或动过仓库与产物)。
(唤醒子代理要用 agent 侧工具——DSH 里是 send_message;脚本调不到它,所以投递这一步只能由编排者做。)
scripts/bnote dispatch <URL> --page N --owner chapter:01,02 --agent <agent-id> # 派单后登记一次(--owner 与 --agent 都必填)
scripts/bnote check <URL> --page N # 失败 → 生成 _meta/validation.json
scripts/bnote brief <URL> --page N --stage fix --owner chapter:01
scripts/bnote fix <URL> --page N # 打印待修清单与投递对象(原 agent / 改派的新代理)
scripts/bnote fix <URL> --page N --done chapter:01 # 子 agent 回报后标记(写 _meta/loop.json;轮次自动累加)
轮次上限 2:fix 按台账自动累加轮次,到上限仍在队列里会标 ⚠「建议升级给人」(无需手工传 --round)。owner 决定谁修:
| owner | 谁修 | 怎么修 |
|---|---|---|
chapter:<id> |
该章原写作 agent | 发修复件给它,只改被指出的地方;不可用/被污染时改派新的干净子代理 |
manifest |
编排者(父 agent) | 章界、时间范围、末章覆盖 |
pipeline |
工具/流水线 | 例如时间轴问题跑 retime、页序漂移跑 remap —— 不是写作 agent 的锅 |
2.5 术语表评审闭环(谁读、几轮、何时停)
| 环节 | 谁做 | 动作 |
|---|---|---|
| 提议 | 脚本 | brief 自动写 <state>/glossary/<vid>.json(confirmed: false),_proposal 里分来源给证据 |
| 一审 | 编排者 | glossary <URL> --page N 看清单:① 仅字幕出现的可疑词 ② 自动判定的 ASR 变体 ③ slide OCR 噪声(水印/型号/墨迹乱码) |
| 二审(可选) | 独立 reviewer | 只审术语、不写正文,产出 drop / add / avoid |
| 应用 | 编排者 | glossary <URL> --page N --drop A B --add C --avoid "X->Y" --confirm --by <你> |
| 生效 | 工具 | 之后 brief 用评审版白名单;未确认则拒绝派发(门禁②) |
| 停止 | —— | 已确认;或两轮后仍有歧义 → 升级给用户 |
- 可选审阅(review):见
references/flow-review.md(当需要查内容问题:漏讲/编造/图注错时) - 信息流模式(无幻灯片):见
references/mode-text.md(当视频是口播/播客/访谈、画面无信息量时)
三、结构 vs 内容:工具管什么、agent 管什么
- 结构(工具强校验,失败不覆盖成品):manifest schema、章界连续与覆盖、slide 归属、
正文小节时间行(格式统一 / 单调 / 不重叠 / 不越章界)、多图小节的每图时间戳、图存在、
corrections三字段、stage_merges一致性、note 节点格式与 20% 预算;校验口径详见references/schema/body-contract.md; - 内容(写进写作契约,工具不 grep):覆盖每个知识点、图注必须自己打开图看过再写(读图工具:DSH 里是
read_image,其它 harness 用等价工具;OCR 会漏字)、 分类落表格、小结/思考、不编造;术语白名单与排版规则由内容画像注入; - 派生数据由工具生成:时间行(
retime)、节点索引(note)、钩子(note); - 工程性信息(听写校正、存疑、覆盖说明)一律进 manifest 字段 —— 正文里没有位置可写;
- 视频页元信息(简介 / 标签 / 分区)在取数时落进
<数据根>/cache/<vid>/meta.json,并注入派单 prompt(章节写手、笔记写手、整理稿写手都能看到,当背景);人也从index.md看到它。 它不是课程内容:可以用来判断主题、术语写法、是否属于某个系列,但不许写进讲义/笔记正文(讲师没说的不算课程讲的)。
四、故障、维护与发布(按需读)
- 常见故障:见
references/troubleshooting.md(当命令报错、校验失败或产物异常时;先读_meta/validation.json/validation.md/loop.json) - 要改工具或发布版本:见
references/maintenance.md(当要改代码、契约、参数或发新版本时)