wechat-channels-video 是做什麼的?
用 Ego Lite 會話在 視頻號助手 保存視頻草稿。不點「發表」(掃碼發表留給人)。
Save a WeChat Channels draft through Ego Lite. Never click Publish — QR publish is human-only.
先裝 Ego
先裝 Ego Lite,保證 ego-browser 在 PATH。缺失則 soft-fail / 告知用戶去裝,不要硬調瀏覽器。
每次發布前:登錄閘門(必做)
視頻號登錄態過期很快。Agent 在上傳或填表之前必須跑:
node scripts/check-login.mjs
# 需要把窗口留給人掃碼時:
node scripts/check-login.mjs --keep
| 退出碼 | 含義 | Agent 做什麼 |
|---|---|---|
0 | 已登錄 | 把 login_tip 告訴用戶,繼續流程 |
2 | 未登錄 / 無 ego-browser | 展示 how_to_login / how_to_login_zh,停。請人在 Ego 掃碼後再跑 check-login |
1 | 其它錯誤 | 報告 JSON error,不要假裝已發布 |
詳見 references/login.md。不要另做 cookie-healthcheck 技能。
輸入(通用,無本機產品路徑)
調用方提供視頻與文案字段,見 references/inputs.md。本技能不寫死任何 ~/… 業務目錄。
最少需要:本機 video 路徑、description、short_title。可選:tags、cover、位置/原創/活動。
CLI 薄腳本(穩定部分)
ego-browser nodejs 不轉發 shell argv;check-login 已用臨時 entry + ego-browser nodejs -e 包好。
# 倉庫根目錄
node skills/wechat-channels-video/scripts/check-login.mjs
node skills/wechat-channels-video/scripts/check-login.mjs --keep
node skills/wechat-channels-video/scripts/serve-file.mjs --file /absolute/path/to/video.mp4 --port 18765
# 已安裝的技能目錄裡也可以用相對路徑
node scripts/check-login.mjs
node scripts/serve-file.mjs --file /absolute/path/to/video.mp4 --port 18765
- check-login:唯一登錄硬閘門;結束默認
finish({ keep: [] })(--keep除外)。 - serve-file:給頁面
fetch用的本機 CORS 文件服務;打印{ url, bytes, port },SIGINT 結束。大視頻不要 base64。
不把整段發表 UI 打成一個巨型腳本:wujie、座標點擊、封面 waitForFileChooser 需要 Agent 看 snapshot/截圖。腳本負責可判定的登錄與傳文件;表單仍按下面 Agent 步驟。
ego-browser API 速查
每次 ego-browser nodejs 是新進程;TaskSpace / Page 跨調用持久,JS 變量不持久。
| API | 說明 |
|---|---|
| `taskSpace(name | id)` |
task.page("p1") | 首屏用 goto 複用,別亂開頁 |
page.snapshot() | 觀察(能看穿 open shadow);點擊在 wujie 內常被攔截 |
page.evaluate(fn, arg) | 只收一個 JSON 可序列化參數(長文案走這裡) |
page.mouse.click(x, y) | wujie 內彈層常用 |
page.waitForFileChooser() | 封面唯一穩妥上傳路徑 |
task.handOff() | 交給人掃碼發表 / 當面登錄 |
task.finish({ keep: [] }) | 收尾關 space;需人接著看時用 handOff,不要長期佔機器 |
關鍵:snapshot 看得見 wujie shadow;ref/text 點擊會報 intercepts pointer events。wujie 內動作用 evaluate 裡 .click() 或座標 mouse.click。
Agent 流程(登錄通過之後)
0. 路由到發表頁
不要直接 goto /platform/post/create(懶加載白屏)。走 UI:
首頁 → 左欄「內容管理」→「視頻」→ 右側「發表視頻」
就緒:wujie 內文案出現「視頻描述」「短標題」,且有隱藏 input[type=file][accept*="video"] 與「保存草稿」。
const state = await page.evaluate(() => {
const app = document.querySelector('wujie-app');
if (!app?.shadowRoot) return { wujie: false };
const t = app.shadowRoot.textContent || '';
return {
wujie: true,
hasDesc: t.includes('視頻描述'),
hasShort: t.includes('短標題'),
hasUpload: !!app.shadowRoot.querySelector('input[type=file][accept*="video"]'),
hasSave: t.includes('保存草稿'),
};
});
1. 上傳視頻
先起 serve-file(端口默認 18765),再在頁面裡 fetch + DataTransfer 注入隱藏 file input(視頻組件未做 isTrusted 加固;封面做了):
const r = await page.evaluate(async (p) => {
const root = document.querySelector('wujie-app').shadowRoot;
const input = root.querySelector('input[type=file][accept*="video"]');
const resp = await fetch(p.url);
const dt = new DataTransfer();
dt.items.add(new File([await resp.blob()], p.name, { type: 'video/mp4' }));
input.files = dt.files;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
return 'injected ' + dt.files[0].size;
}, { url: 'http://127.0.0.1:18765/video.mp4', name: 'video.mp4' });
驗證只看 DOM:出現「轉發/讚/評論」預覽卡、進度穩定 100%。performance resource 抓不到上傳 POST。上傳中途不要填表;wujie 短暫 null 時等一會再探,不要刷新。
1.5 檢查點:先存草稿
上傳完成後立刻點一次「保存草稿」,再填描述/短標題/位置,最後再存。避免中途翻車重傳大文件。
2. 描述 + 話題
描述是 .input-editor(非 contenteditable)。execCommand;文案從 evaluate 第二參數傳入:
await page.evaluate((p) => {
const ed = document.querySelector('wujie-app').shadowRoot.querySelector('.input-editor');
ed.focus();
document.execCommand('selectAll', false, null);
document.execCommand('delete', false, null);
document.execCommand('insertText', false, p.desc);
}, { desc });
await page.evaluate((p) => {
const ed = document.querySelector('wujie-app').shadowRoot.querySelector('.input-editor');
ed.focus();
document.execCommand('insertParagraph');
document.execCommand('insertText', false, p.tags);
ed.blur();
}, { tags });
3. 短標題
真 <input>,必須 native setter;驗證讀 input.value(innerText 不含 input 值)。
4. 位置
默認常帶城市。穩妥:mouse.click 打開 → snapshot/截圖 → 點「不顯示位置」→ 回讀字段確認。evaluate 座標可能點到隱藏層。
5. 保存草稿(終點)
點「保存草稿」。成功信號:「已保存」+ 底部按鈕變灰。再 goto 草稿箱核對。草稿箱可見前不要離開編輯器。
可選:聲明原創、活動搜索(native setter 寫搜索詞;搜不到就「不參與活動」)。
6. 封面(可選)
唯一穩妥:waitForFileChooser() + 可信點擊「上傳封面」+ chooser.setFiles(<絕對路徑>)。合成 input.files / OS 文件框方案已實測失敗。確認按鈕轉圈結束、預覽不再回退默認幀後再存草稿。
7. 收尾
- 停掉
serve-file(釋放端口)。 - 需要人發表:草稿箱
handOff()。 - 否則
finish({ keep: [] }),不要長期佔 space。
避坑清單
- wujie shadow:查詢從
wujie-app.shadowRoot起。 - 直鏈 create 白屏:必須 UI 路徑進入發表頁。
- wujie 內 ref/text 點擊被攔截 → evaluate 或座標點擊。
- 長文案只經 evaluate 參數傳入。
- 描述用 execCommand;短標題用 native setter。
- 位置兩段式座標 + 回讀驗證。
- 封面只能 waitForFileChooser。
- 上傳驗證只看 DOM;上傳後先存草稿。
- 草稿落盤前不導航離開。
- 登錄頁「加載失敗」是紅鯡魚;handOff 讓人掃碼。
- 每次發布前 check-login;exit 2 必須停。
- 發表是人工終點;本技能只到草稿。
測試
npm test