视频号日更智能运营流水线
这是什么
一个本地运行的内容生产线。输入是一个账号的定位,输出是每天可发布、可回流、
可持续优化的短视频。
为什么必须是本地的:发布和抓取要用账号登录态,登录态在客户自己电脑的浏览器里,
任何云端服务都拿不到。这是本产品与云端生成工具的根本差别 —— 云端能帮你写稿,
但发不了你的号。
交付包结构
video-daily/
├── SKILL.md ← 你正在读的文件,agent 的唯一入口
├── VERSION 版本号
├── requirements.txt Python 依赖(只有 2 项)
├── tools/
│ ├── bootstrap.py ★ 一键引导(agent 第一步:装依赖 + 报「人要做几件」)
│ ├── doctor.py 环境自检(细粒度诊断)
│ ├── login.py ★ 拉起浏览器 + 引导扫码(登录态落 data/browser/)
│ ├── verify_chain.py ★ 零成本全链验收(交付验收凭据,花 ¥0)
│ ├── run_chain.py 日更链路主入口
│ ├── publish_one.py 发布(默认干跑)
│ ├── fetch_stats.py 数据回流
│ ├── compare_producers.py 跨产线/分期对比
│ └── gen_one.py 单条画面生成(调试用)
├── vendor/
│ └── channels/ ★ 内置视频号适配层(提交 / 账号探针 / 抓取 / 烧字)
│ ├── README.md 契约说明:客户可整体替换自己的实现
│ └── package.json node 依赖声明(playwright-core)
├── config/
│ └── examples/*.yaml 客户配置样例(含 browser 段:端口 / profile / 登录引导)
├── stages/ providers/ adapters/ core/ 产品代码(零第三方 Python 依赖)
│ └── core/browser.py ★ 自托管浏览器(登录态的唯一入口,纯标准库)
└── data/
├── browser/ 登录态 profile(⚠️ 敏感:绝不提交、绝不随包分发)
└── run/ 产物、台账(运行时生成)
重要规则(agent 必须遵守)
- 动手前先引导。任何操作之前先跑
python tools/bootstrap.py(步骤 0)——
它会自动把能装的装好,并列出必须人做的项。需要细粒度诊断时再跑
tools/doctor.py --json。不要带着缺依赖的环境往下跑,也不要给人一串安装命令。 - 发布是唯一不可撤销的动作。
publish_one.py默认干跑;只有用户明确说「发」
才加--yes。绝不自行加--yes。 - 渲染要花钱。
run_chain.py不加--allow-paid时 render 阶段只出计划不花钱;
加之前必须让用户确认,并显式给--max-cost(金额硬闸门,超预算即停)。 - Key 由客户自带,不代收。渲染与 LLM 的 Key 写在客户自己的
.env里,
不要向任何第三方服务转发客户的 Key。 - 真人只在两处介入(见下节),其余全自动。遇到需要真人的点,明确提示并等待,
不要自己编一个值往下跑。 - 不要修改现有代码或配置来"绕过"报错。报错本身就是信息,按「失败处理」表处理。
执行流程
步骤 0 · 一键引导(★ 唯一入口,先跑这条)
python tools/bootstrap.py
一条命令顶掉一长串人肉操作:探测环境 → 装 Python 依赖 → 装 node 依赖 →
建 .env 骨架 → 复检,并明确告诉你还剩几件必须人做的事。
每步都先探测再动手,幂等,反复跑安全。
| 参数 | 用途 |
|---|---|
| (无) | 探测 + 自动修 + 报告「人要做几件」 |
--check |
只看不改(零副作用;不确定时先跑这个) |
--json |
机器可读(agent 消费) |
--install-system |
显式授权:用包管理器装 ffmpeg / Node(含 sudo 的仍不自动执行) |
- 它会自动处理:Python 包(PyYAML / edge-tts)、node 包(playwright-core,约 14MB)、
.env骨架(从.env.example复制,Key 留空 —— 绝不代填)。 - 它不会代劳(必须人做,脚本会逐条列出):
填 API Key、扫码登录、
装系统软件(ffmpeg / Node ≥18 / Chrome 或 Edge —— 需包管理器与授权)。 - 若本机已有 playwright-core:无需重装,在
.env写一行
NODE_PATH=<其 node_modules 目录>即可复用(脚本与 doctor 都会认)。 - ⚠️ 不要给人一串命令让他敲。交付包的读者是 agent —— 命令的出处只有本文件一处,
agent 跑bootstrap.py就够了。用户只需回答「目标是什么」+ 扫码 + 填 Key。 - 期望:
【只剩人做 N 件】;按它逐项处理,处理完重跑本步即可复检。 - 失败:脚本回显原始输出尾部(pip / npm 的真实报错),不要靠猜。
- macOS / Linux 上若
pip被 PEP 668(系统托管 Python)拦下,脚本会直接给出
虚拟环境方案(python3 -m venv .venv),照它做即可。
步骤 1 · 环境自检(细粒度诊断,需要时再跑)
python tools/doctor.py --config config/examples/xinxin_tea.yaml --json
- 期望:
"ok": true - 失败:读
checks[]里ok=false的项,按其fix字段逐项处理,然后重跑。
next_actions[]已经是排好序的修复清单。 - ⚠️ 每次换机器、换账号、重装依赖后都要重跑。
bootstrap.py就是在本步外面包一层「自动修 + 人要做清单」——
两者共用同一套判定(bootstrap 直接 import doctor,不另立第二套口径)。
步骤 2 · 配置客户账号
复制 config/examples/xinxin_tea.yaml 为 <客户>.yaml,只让用户回答两块:
| 块 | 内容 | 谁填 |
|---|---|---|
account |
账号名、领域、一句话定位、受众、每日条数 | 用户答,你写 |
goals.primary |
主目标(涨粉 / 带货 / 品牌) | 用户答,你写 |
其余全部有默认值。不要为了"更完整"去追问 —— 默认值就是设计好的起点。
步骤 3 · 登录(真人介入点 1 = 用户扫码)
# 产品自己拉起浏览器并引导扫码;登录态落在 data/browser/
python tools/login.py --config <客户>.yaml --account <账号名>
- 你需要做的:把命令跑起来,然后告诉用户「浏览器已打开,请用手机扫码」。
命令会阻塞等待,扫码成功后自动返回。 - 期望输出:
登录态 ✓ 已确认+ 账号名;或--check时"logged_in": true。 - 幂等:端口已通就直接复用,不会重复开窗口;重跑安全。
- 多号:不同账号各用一个 profile 目录(
data/browser/<账号名>/),互不覆盖。
切换账号前先--stop关掉当前实例,再用目标账号跑一次。 - ⚠️ 登录判定不许只看 URL:视频号未登录时会短暂停在
/platform(过渡态)。
产品的登录结论来自「URL + 账号探针」,探针说没登录就是没登录。别绕过它下结论。 - ⚠️ 登录态不可迁移:每台电脑、每个账号都要人工登录一次。这是产品的硬边界,
不是缺陷 —— 对应「软件不能替客户实名」这条合规要求。
步骤 4 · 零成本干跑(先验证配置,不花钱)
python tools/run_chain.py --config <客户>.yaml --dry-run
- 期望:打印客户 / 账号 / 目标 / 引擎 / 信源 / 阶段,无异常退出。
- 失败:
✗ 配置校验失败→ 回到步骤 2 补goals.primary。
步骤 4.5 · 零成本全链验收(★ 交付验收的正式凭据)
python tools/verify_chain.py --config <客户>.yaml
这一步用已有的真实产物把八段整条链验一遍,花费 ¥0
(不调 LLM、不提交渲染、不发布、不碰浏览器)。它回答的是唯一有意义的那个问题:
> 「能不能一口气从 fetch 跑到 stats?」
单段各自跑通 ≠ 整链跑通 —— 交付给陌生环境的验收标准就是整链。六道断言:
| 断言 | 在测什么 | 最怕的失效方式 |
|---|---|---|
| T1 全 8 阶段 dry-run | 编排骨架能走完 | 某段短路、阶段名拼错 |
| T2 6/6 段命中「已有产物 → 跳过」 | 复用口径逐段正确 | 跳过错 → 重跑就再花一遍钱 |
| T3 本地合成出成片 | 片段+音轨+字幕 → 真文件 | 文件产出但为空/损坏 |
| T4 回流出「问题 → 动作」 | 诊断链可用 | 只出数据不出动作 |
| T5a 标准目录 → 显示真实金额 | 成本可追溯 | 成本口径静默归零 |
| T5b 非标准目录 → 显示「缺数据」 | 不许把未知当 ¥0 | 显示 ¥0 → 被读成「不花钱」 |
- 期望:有历史样本时
6 通过 | 0 跳过 | 0 失败;没有样本时1 通过 | 5 跳过 | 0 失败
(两者退出码都是 0)。 - ⚠️ 「跳过」不是「失败」:T2~T5 需要一份带真实产物的历史 run,全新环境必然没有。
这种情况会明确打「跳过」并给出补样本的三种办法,不会判红、不会让客户误以为产品坏了;
只有在「样本存在但缺件」(例如少了stats/raw/)时才判失败。
想立刻验满六项 → 先跑步骤 5 出一条成片,再回来跑本步。 - 样本选择器按「完整度」挑(
fetch.json+render/render.json+stats/raw/*.json
各算一分),同分取最新 —— 不是按目录名取最新。实测踩过:目录名最新的那个恰好缺
stats/raw/,被选为样本后直接报红,而真正完整的样本就在旁边没人用。 - 失败:每条断言失败都会回显原始输出尾部(排查不要靠猜)。
步骤 5 · 跑通一条成片
# 5a 前 3 段(只花 LLM 的几分钱)
python tools/run_chain.py --config <客户>.yaml --stages fetch,rank,write
# 5b 到合成(★ 会产生渲染费用,先跟用户确认)
python tools/run_chain.py --config <客户>.yaml \
--stages fetch,rank,write,voice,render,compose \
--allow-paid --max-cost 4.0
- 期望:
data/run/<客户>/<日期>/compose/final_s01.mp4生成,竖屏 1080×1920。 - 失败:见「失败处理」表。渲染失败时不要盲目重跑 —— 先看是否命中
--max-cost闸门(超预算会主动停下,这是设计行为不是故障)。 - 补渲:中断后用
--resume(复用已成功片段,零花费);
只重渲某几条用--only-scripts 1(其余原样带过,不重渲不计费)。
步骤 6 · 发布(真人介入点 2 = 用户点头)
# 干跑:走完所有门禁但不发
python tools/publish_one.py --config <客户>.yaml
# 真实发布:★ 必须用户明确同意后才加 --yes
python tools/publish_one.py --config <客户>.yaml --yes
- 门禁(会自动核,失败原因写在输出里):标题 ≤16 字 / 符号白名单 /
时长上限 / AI 标注 / 账号登录态比对(防「往 B 号发 A 号的内容」)/
发布窗口 / 幂等防重 / 连续失败熔断。 - 幂等:同一条不会发第二次(指纹台账只认成功);要重发得显式
--force。
6.1 · 改过平台脚本后,先做「零发布演练」
平台前端会改版(2026-10-10 首页入口与「发表」按钮已挪进 wujie 微前端 + shadow DOM)。
只要动过 vendor/channels/publish_channels.js,或怀疑平台改版,先跑演练:
python tools/publish_script_check.py --config <客户>.yaml \
--run-dir data/run/<客户>/<日期> --only s01
- 脚本会走完 入场 → 上传 → 填描述/短标题 → 定位「发表」按钮,
在第一次点击提交之前停手并打印证据(视口尺寸、按钮坐标、命中的根)。 - 花费 ¥0,零不可撤销操作(有断言锁死顺序:演练必定停在提交前)。
- 它会抓:入口/按钮换 iframe 或进 shadowRoot(坑26/31)、按钮落在视口外(坑27/30)、
上传桥接失效(坑3/7/8)、表单被平台拒绝(会打印错误原文,坑25/29)。 - 它抓不到:原创声明三层链的后半段(那发生在点下「发表」之后)——
所以演练不代替一次真发布,只把风险推到真发那一刻之前。
步骤 7 · 数据回流(每天一次)
python tools/fetch_stats.py --config <客户>.yaml --full
- 期望:
data/run/<客户>/<日期>/stats/stats_report.md生成,内容为
「问题 → 可执行动作」清单,每条带action / apply / owner / due四件套。 - ⚠️ 数据回流的目的不是看数,是改配置。报告里每条动作都要落到具体的
字段或文件上,否则这次回流等于没做。 - 失败:输出含
NEED_LOGIN→ 让用户重新登录(回到步骤 3)。
步骤 8 · 对比产线效果(可选)
python tools/compare_producers.py --account <账号名> --split <YYYY-MM-DD>
- 只比单位效率(单条播放中位 / 单条净涨粉 / ¥千播 / ¥条 / 转化率),不比绝对值。
- 样本不足时工具会主动报「样本不足」—— 如实转述,不要编造胜负结论。
真人介入点(只有三处,其余全自动)
| # | 时机 | 为什么必须真人 | agent 该做什么 |
|---|---|---|---|
| 1 | 填 API Key(一处,一次性) | 合规:Key 是客户的,agent 不代填、不外传 | 只报「缺哪个变量名」,让用户在 .env 里填;bootstrap.py 会列出 |
| 2 | 登录(每台机器 / 每账号一次) | 合规:软件不能替客户实名 | 跑 tools/login.py,提示用户扫码,等它返回 ok=true |
| 3 | 发布前 | 发布不可撤销 | 干跑给用户看结果,等明确同意再加 --yes |
外加一个「业务输入」:步骤 2 里账号定位与主目标要用户回答(这是唯一的内容侧输入)。
bootstrap.py 会把上面这几件逐条列出来(那是它输出的主要目的)。
失败处理(错误 → 动作)
| 现象 | 原因 | 动作 |
|---|---|---|
[✗] ffmpeg |
未安装 | Windows winget install Gyan.FFmpeg / macOS brew install ffmpeg / Linux apt install ffmpeg,重跑 doctor |
[✗] Node.js |
未安装 | 装 Node ≥18,重跑 doctor |
[✗] Python 依赖包 |
未装包 | pip install -r requirements.txt |
[✗] 内置视频号适配层 |
安装包不完整 | 重新解压完整安装包(缺的是 vendor/channels/ 下的脚本) |
[✗] node 依赖(playwright-core) |
未装 node 依赖 | cd vendor/channels && npm install --omit=dev;或在 .env 设 NODE_PATH |
[✗] 配置引用的外部脚本 |
配置里显式指向了包外路径 | 把该项留空即用内置实现;或把脚本放进包内 |
[!] 浏览器登录态(CDP 端口不通) |
浏览器未起 / 未登录 / 登录态过期 | 跑 python tools/login.py(自动拉起并等扫码);不要自己拼 chrome 命令行 |
浏览器未启动或已关闭 |
抓取/发布时 CDP 连不上 | 跑 tools/login.py 拉起并登录,再重跑;不要盲目重试 |
登录时报 URL 像已登录、但账号未确认 |
撞上 /platform 过渡态 |
正常现象:继续等扫码即可(产品已做防假阳性,不会误报成功) |
NEED_LOGIN |
登录态失效 | 跑 tools/login.py 让用户重新扫码,不要重试超过 2 次 |
✗ 配置校验失败 |
缺 goals.primary |
回到步骤 2 |
渲染被 --max-cost 拦下 |
预算闸门(正常行为) | 先跟用户确认是否加预算,不要直接改大数字 |
duplicate_of / md5 重复 |
同批产出两片内容相同 | 停止发布这批,报告给用户(防"拿错成片"类故障) |
发布报 Protocol error |
CDP 会话抖动 | 有补点兜底逻辑;仍失败则重跑一次,不要连发 |
当前边界(不声称未验证的能力)
- 本包 v0.3.14(2026-10-13):
- 首次发布致谢的打赏动作升级为「屏幕直接扫码」:弹窗时自动用系统看图程序
弹出包内assets/donate_qr.png(微信赞赏码),微信「扫一扫」对准屏幕即可 ——
实测原「打开文章 → 滚到文末 → 赞赏」在 PC 上要走 ≈9 步、跨 2 台设备,几乎无人走完;
现在步数 9 → 2。文章链接保留为兜底(headless 弹不出图时仍有入口)。
⚠️ 微信赞赏码是专有编码(非标准 QR,通用解码器读不出),所以随包带原图,
不做终端重绘。弹出失败一律静默降级、绝不阻塞发布流程(非交互环境完全不弹图)。 - 本包 v0.3.13(2026-10-12):
- 版本号唯一来源改为本文件 frontmatter 的
version:——原顶层VERSION
裸文件被技能平台拒收(「不允许的文件类型: VERSION」,2026-10-12 实测),
已删除;tools/doctor.py与打包脚本均改为从 frontmatter 读取。
⚠️ 包内不得再出现无扩展名裸文件(点开头的 dotfile 如.env.example
已被平台实际放行,豁免)。打包自检已加断言。 - v0.3.12(2026-10-12):
- 启动器三平台合一:
start_browser.bat/start_browser.sh合并为
tools/start_browser.py(一条命令python tools/start_browser.py,找 python
交给sys.executable)。起因:skillhub 上架平台拒收.bat类型
(提交报「不允许的文件类型: start_browser.bat」)——交付物读者是 agent,
agent 本来就会跑 python,平台专属脚本反而是给人看的旧形态。
行为不变:默认不传--port(端口走唯一来源)、透传--hold --timeout 900。
⚠️ 本包内不得再出现.bat/.sh/.exe等可执行脚本类型(打包自检已加断言)。 - 本包 v0.3.11(2026-10-12):
- data/ 占位文件改用 README.md(替代
.gitkeep):skillhub 上架平台拒收
.gitkeep类型(提交时报「不允许的文件类型: data/.gitkeep」)。README.md 既过审
又顺带说明了各子目录用途。包内红线自检同步新增「无 .gitkeep」断言,防回归。 - 本包 v0.3.10(2026-10-12):
- 首次发布致谢里的打赏文章链接随文章重发更新:公众号那篇介绍文章为补二维码删文重发,
链接由https://mp.weixin.qq.com/s/uHD-h1fkaniuIVcMHf_4Sw变为
https://mp.weixin.qq.com/s/un8cPejuKtaF52e0fAqpZA(旧链接已失效)。
唯一来源仍是core/milestones.py:DONATE_ARTICLE_URL—— 测试引用常量、不写死值,
所以这类运营侧链接变更只需改一处。注意:公众号文章删文重发必换链接,
这是本包唯一一个会随外部运营动作变化的值,别把它写进任何第二处。 - 本包 v0.3.9(2026-10-12):
- 改名:技能标识
video-saas→video-daily,显示名「视频号日更智能运营流水线」。
理由:saas与产品定位自相矛盾(本地运行、客户零 GPU、渲染费客户自付给厂商),
且与官网/skills-pkg/的短 slug 惯例对齐。slug 是上架后的对外契约,此改只在上架前做。
包标识已收敛到唯一来源core/assets.py的PKG_SLUG/PKG_TITLE(doctor / bootstrap /
login / 打包脚本 / 界面标题全部同源,不再各写一份字面量)。
⚠️ 与产品改名无关、保持原值的两处:①stats.producer = "video-saas"—— 那是数据口径,
历史台账已写满它,改了同一账号的数据会断成两条产线(对比 CLI 会当两个号);
②~/.video-saas/.env—— 老客户 Key 所在,现新增~/.video-daily/.env优先读,旧路径仍兼容。 - 验收器不再「无样本就报红」(
tools/verify_chain.py):全新环境必然没有历史样本,
旧版把这种情形判成 3 项失败、退出码 1 —— 客户第一眼就是一片红,容易误判「产品坏了」。
现为三态 通过/跳过/失败:无样本 → 明确跳过 + 打印补样本的三种办法,退出码 0;
样本存在但缺件才失败;--source-run指错目录仍失败(那是输入错误,不静默放过)。
样本选择器同时改按「完整度」挑(fetch.json/render/render.json/stats/raw/*.json
各一分),不再按目录名取最新 —— 实测踩过:目录名最新的那个恰好缺stats/raw/,被选为
样本后直接报红,而完整样本就在旁边没人用。 - 端口不再被启动脚本写死(
start_browser.sh/start_browser.bat,两者已于
v0.3.12 合并为tools/start_browser.py):两个脚本原写死
--port 9223,而它落在优先级最高的「显式」槽 → 静默覆盖配置。换一个写 9222 的配置时,
浏览器起在 9223、发布与抓取却连 9222(浏览器活着,但没人连得上)。
现改为「用户显式设了PORT才传--port」,其余情况交给唯一来源
core.browser.resolve_port(配置 > 环境变量CDP_PORT> 内置默认);
BrowserSpec.port同时由9222改为0(0 = 未配置),让环境变量层不再被默认值抢占。 - 本包 v0.3.8:
- 首次发布里程碑致谢(
core/milestones.py):本机第一次成功发布后,会递上一条
致谢 + 回报提示 —— 只留打赏(打开介绍本技能包的文章,文末有平台原生「赞赏」入口)。
早先的「帮人场/帮钱场」二选一已于 2026-10-11 取消(帮人场不可测,留着等于白问一次)。
无人值守时不阻塞(只落.pending待办,下次人在终端跑doctor/bootstrap强制补上),
看过一次(回车即确认)写.done,此后永不再出现。判据是台账published计数
0→≥1 的跨越,不误报历史台账。 - L0 署名与支持入口:
README.md出品方 + 官网;SKILL.mdfrontmatter 含
author/homepage/support;bootstrap.py输出末尾打印出品方;包内
docs/服务与支持.md说明能力边界、费用口径与联系入口。 - 内置 L1 视频号适配层(
vendor/channels/):publish.adapter_script/
publish.account_script/stats.script留空即用内置实现,客户零配置即可跑通。
要换自己的实现时填路径覆盖,契约见vendor/channels/README.md。 - 登录态由产品自管(
tools/login.py+core/browser.py):产品自己拉起
独立 profile 的浏览器、引导扫码、把登录态留在data/browser/,后续发布与回流
自动连它。CDP 端口只在browser.port一处定义,发布/抓取/探针共用。 - 零成本全链验收(
tools/verify_chain.py):六道断言、花费 ¥0,
给出「八段整链跑通」的可执行凭据(步骤 4.5)。 - 零发布演练(
tools/publish_script_check.py):走完发布链路前段、在提交前停手,
花费 ¥0(步骤 6.1);平台改版后必跑。 - 真人只剩一件必做事:扫码。
- 支持 Windows / macOS / Linux:浏览器探测、进程分离(
DETACHED_PROCESS↔
start_new_session)、存活检测(tasklist↔os.kill)、打开 URL(startfile↔
open↔xdg-open)三平台各一套分支;启动器为tools/start_browser.py
(三平台同一条命令:python tools/start_browser.py;原.bat/.sh两份已并入,
因 skillhub 等上架平台拒收.bat类型)。
⚠️ 本包在 Windows 上完成实测;macOS / Linux 为同源分支,未做实测(不声称已通过)。 - 渲染与 LLM 默认走云端 API(Key 客户自带)。本地算力(ComfyUI)尚未实现。
- 本包不包含任何 API Key、不含
node_modules、不含data/browser/。
.env与登录态都只存在于客户本机,绝不随包分发。 - 多账号并发(一个端口同时服务多个号)未实现;当前是「一个 profile 一个号,
切号需重启实例」。界面层、云壳(官网 API 对接)亦未实现。