视频发布(B 站 / YouTube / 抖音 / 快手 / 小红书)
铁律
- 每一条发布前,将平台、账号、文件、封面、标题、简介、标签、分区、发布方式整理成表格交给用户,用户明确说“发”才能执行。 用户可以一次性批准多条(例如“EP2–EP4 都发”),但只覆盖当时列出的那几条和那些内容;任何内容改动都必须重新确认。
- 登录只能由用户自己完成(终端扫码)。不得代替用户输入账号、密码、手机号、验证码,也不得读取或打印 cookie 内容。
- 抖音、快手、小红书的上传基于 patchright(隐藏自动化痕迹的浏览器)。用户决定使用它,但由用户在自己的终端中运行上传命令: Claude 负责准备好完整命令和投稿信息,但不得自己执行这几个平台的 login / upload,也不能代替用户处理滑块验证码。
准备
- 发布前检查一遍 tech-explainer-video 的
references/plotome-lessons.md合规清单:勾选“含 AI 生成内容”(旁白是 AI 也要勾选)、音乐授权和署名写进简介、不使用真人脸和商标。 - 按照
references/upload-meta-template.md编写out/upload_meta.md。简介只写视频中确实讲到的内容,开头加上“自用学习笔记。”(用户偏好)。 - 封面:1920×1080 分辨率、无字幕;由 tech-explainer-video 的
cover-epKcomposition 生成。 - 发送给用户审核(SendUserFile),询问:封面是否合适、是否需要代码链接(GitHub/Gist)、合集名称。
B 站
工具:dreammis/social-auto-upload(安装在 ~/tools/social-auto-upload),实际投稿使用它自动下载的 biliup。
首次安装(先告知用户来源、内容和大小,等用户同意后再安装):
git clone --depth 1 https://github.com/dreammis/social-auto-upload.git ~/tools/social-auto-upload
cd ~/tools/social-auto-upload && uv venv --python 3.12 && uv pip install -e . && uv pip install playwright
cp conf.example.py conf.py
登录(让用户在自己的终端中运行,菜单选择「扫码登录」,使用 B 站 App 扫码;如果二维码显示不全,打开 qrcode.png):
cd ~/tools/social-auto-upload && .venv/bin/sau bilibili login --account <账号名>
不要选择短信登录:它需要处理滑块验证码并手动填写 challenge,很容易过期失败。
检查登录状态:.venv/bin/sau bilibili check --account <账号名>,输出 valid 即可。
上传:
- 先测试线路:
tools/probe_lines.sh,选取速度最快的那条(通常是 tx 或 bda2)。不要让 biliup 自动测速,经过代理时可能会卡住。 - 逐条投稿:
脚本会将路径转换为绝对路径(它内部会 cd 到 social-auto-upload),在视频项目目录中使用相对路径调用即可。 成功会打印~/.claude/skills/video-publish/tools/bili_upload.sh <账号名> out/ep1.mp4 out/covers/ep1.jpg tx 231 "<标题>" "<简介>" "<标签,逗号分隔>"投稿成功 BVxxxx 链接,失败会打印日志末尾。多集按顺序一集一集上传,每上传完一集就告知用户 BV 号。 - 全部上传完成后提醒用户:在创作中心「合集管理」中创建合集并按顺序加入;审核通过后才公开。
网络故障排查:
- 上传极慢、出现
error sending request、connection reset、服务器 500:多半是代理 TUN 将流量绕道到了海外节点。 让用户在代理规则中将DOMAIN-SUFFIX,bilibili.com,DIRECT、DOMAIN-SUFFIX,bilivideo.com,DIRECT放在靠前的位置,并重新加载配置; 再运行一遍probe_lines.sh,速度达到每秒几百 KB 以上再上传。 - 查看进度:
nettop -p <biliup 进程 ID> -L 1 -x -J bytes_out。biliup 日志在上传完成之前几乎没有输出,不要因为看不到日志就认为卡住了。 - macOS 没有
timeout命令。 - 首次运行 sau 下载 biliup 失败(GitHub Release 访问慢):使用
https://gh-proxy.com/或https://gh-proxy.org/加在 release 地址前面手动下载。 - 重新上传前,先确认上一次没有投稿成功(日志中是否有 bvid),避免重复投稿。
B 站:投稿上限与分 P
- 新建稿件每天约 7 个,超过会返回
21566 投稿过于频繁,需要等待第二天。一章制作成一个分 P 稿件(biliupupload一次上传多个文件,文件名即为分 P 标题,使用硬链接out/parts/P<k> <集标题>.mp4命名,不占用额外空间)。 - 往已有稿件追加分 P 使用
biliup append --vid BV…,不占用新建额度。 - 标签最多 12 个,超出则截断。线路先用
probe_lines.sh测试;bldsa曾出现证书过期,失败时可切换为tx/bda2。 - 队列脚本示例:
tools/examples/upload_chapters.sh(21566 错误每小时重试,最多 24 次;成功后将- 结果:BV… P<k>写回 upload_meta.md)。
B 站:追加到已有稿件(系列合集,2026-10 ~ 11 知识库已验证)
- 一个系列做一个分 P 稿件,后续每篇都使用
biliup append --vid BV…追加;不新建稿件(用户明确要求不新建时更是如此)。 - 队列脚本示例
tools/examples/upload_append.sh:每篇一行app <名字> <BV> <项目目录>,按顺序追加out/parts/*.mp4。- 幂等性:成功写入
<名字> append <BV> <日期>到results.log,再次运行时自动跳过(“已追加过”),因此新一批只需在末尾添加行,整份脚本重新运行。 - 线路轮换:alia → tx → bda2,三条都失败则等待 30 分钟重试,最多 48 轮;成功的标志是输出中包含
稿件修改成功。 - 使用
nohup <脚本> > upload_kbN.log 2>&1 & disown启动,日志按批次编号;另外启动一个后台 until 循环,等待日志中出现“队列完成”。 - 常见失败
client error (Connect):线路抖动,脚本会自动重试,不要手动重新上传(会导致重复分 P)。
- 幂等性:成功写入
- 分 P 标题即文件名:
out/parts/P<k> <钩子>:<主题>.mp4(硬链接到out/epK.mp4,不占用空间)。 - append 无法修改简介:每批在 upload_meta.md 中写一段“简介补充”,然后追加到看板中的一条“待作者”笔记,让用户在创作中心手动粘贴到原稿件简介的末尾。
- 不同语言的版本(如英文配音版)不要追加到中文稿件中,发布到哪个平台由用户决定。
YouTube
- 工具:同一个 sau(
sau youtube login/upload-video,必须使用--headed,无头模式 Google 不允许进入 Studio)。 sau 自带的 YouTube 上传器有两个 bug,修复方法在tools/examples/sau-youtube-fixes.patch:登录检查只等待 3 秒并且使用无头模式(误报 invalid);播放列表选择器点击错误(播放列表从未成功添加,并且异常被吞没)。新机器安装 sau 后需要先应用这个补丁。 - 播放列表需要先在 Studio 中创建好(否则
--playlist参数不生效);上传后抽查一集是否成功加入列表,如果没有,则到 Studio 视频编辑页面手动补选。 - 单日有上传上限:出现“未找到发布按钮”、视频停留在草稿状态,多半是达到了上限。不要重新上传(会留下重复的草稿),应到 Studio 中将草稿补充发布,剩余的视频第二天再上传。
- 队列脚本示例:
tools/examples/youtube_queue.sh(长队列使用nohup … & disown,会话的后台任务会被回收)。 - API 方案(不开浏览器):youtubeuploader(
brew install youtubeuploader)+tools/examples/youtube_api_upload.sh。 前提条件:Google Cloud 项目启用 YouTube Data API v3、OAuth 同意屏幕(外部、添加测试用户)、Web 应用凭据(回调地址http://localhost:8080/oauth2callback)。 未通过审核的项目,通过 API 上传的视频一律被锁定为私有;审核表单 https://support.google.com/youtube/contact/yt_api_form 要求提供公开的首页、隐私政策、服务条款 (可使用 GitHub Pages,示例 cassieliang6709/video-uploader)、首页/隐私页截图、OAuth 流程截图、架构图、用户流程图、完整上传脚本。在审核通过之前继续使用浏览器自动化。
抖音 / 快手 / 小红书
工具:同一个 social-auto-upload 的 sau douyin|kuaishou|xiaohongshu,浏览器自动化(patchright)。
命令由用户在自己的终端中运行(见铁律),Claude 只准备命令并检查结果。
视频:这三个平台以竖屏为主,建议使用 1080×1920 分辨率或剪辑成 1 分钟左右的精华;如果需要,可以回到 tech-explainer-video 另行渲染竖版。 横版也可以上传,但会带有黑边。
首次安装浏览器(用户运行):
cd ~/tools/social-auto-upload && PLAYWRIGHT_DOWNLOAD_HOST="https://npmmirror.com/mirrors/playwright" .venv/bin/patchright install chromium
登录与检查(用户运行,<平台> 是 douyin / kuaishou / xiaohongshu):
cd ~/tools/social-auto-upload && .venv/bin/sau <平台> login --account <账号名> --headed
.venv/bin/sau <平台> check --account <账号名>
上传(Claude 根据 upload_meta.md 填写完整命令并发送给用户,用户确认内容后自行运行):
cd ~/tools/social-auto-upload && .venv/bin/sau <平台> upload-video --account <账号名> \
--file <mp4 绝对路径> --title "<标题>" --desc "<正文>" --tags <标签,逗号分隔> \
[--thumbnail <封面>] [--schedule "YYYY-MM-DD HH:MM"] [--collection <已存在的合集名>]
- 抖音:
--thumbnail需要 3:4 竖版,另外还有--thumbnail-landscape(4:3);标题不超过 30 字。 - 快手:
--thumbnail任意比例;脚本只填写前 3 个标签,最重要的放在前面。 - 小红书:标题不超过 20 字;不支持
--collection。 - 用户运行完成后将终端输出粘贴回来,Claude 判断是否成功,并将链接写回 upload_meta.md。出现滑块验证码由用户自行处理。
- 抖音一章发布一个整章合集(各集拼接成
out/chapter.mp4,使用 4:3 横版封面)比逐集发布更易于管理;队列脚本示例tools/examples/douyin_upload_all.sh(用户在自己终端运行,登录检查使用有界面模式DOUYIN_COOKIE_AUTH_HEADLESS=false)。
备选方案(不想使用脚本时):在用户已登录的 Chrome 浏览器中打开创作者平台的发布页面,帮用户选择文件、填写标题和正文,停留在发布按钮之前截图,由用户自己点击“发布”。
批量流水线(仅当用户明确授权)
用户可以对一个系列给予长期授权:“渲染完一批 → 直接上传 → 删除成片”(例如 nudgecode 算法图解,2026-10-24 授权)。 这种授权只覆盖用户指定的那个系列,更换系列或平台需要重新询问。在授权范围内:
- 这一批每章渲染完成后,按照该系列已有的 upload_meta.md 格式自行编写标题、简介、标签(简介仍然以“自用学习笔记。”开头,只写视频中已有的内容),
不再逐条给用户审核;仍然需要先用
sau bilibili check确认登录状态、使用probe_lines.sh选择线路。 - 按章、按集顺序上传,每章上传完成后在对话中列出“集 / 标题 / 链接”,BV 号写回 upload_meta.md。
- 只有成功获取 BV 号的那一集才会被删除:
out/epK.mp4、out/*.raw.mp4、out/check/、out/bundle/(以及该项目自身的 node_modules,共享的软链接不动)。 保留源代码、配音、字幕、封面、upload_meta.md,以便将来重新渲染。上传失败的集一律不删除。 - 如果删除命令被权限拦截,将命令原样交给用户自行运行,不得使用其他方式绕过。
清理
- 成片必须所有目标平台都获得链接后才能删除;删除操作经常被权限拦截,因此写成脚本交给用户运行,示例
tools/examples/cleanup_uploaded.sh(只删除 upload_meta.md 中已有结果的集,可反复运行)。
记录
发布完成后,将每集的 BV 号写回 out/upload_meta.md 的“结果”一栏,并在对话中列出“集 / 标题 / 链接”表格。