Communitygithub.com

terryso/wechat-channels-video

透過 Ego Lite 在微信视频号助手保存视频草稿,不上传发表(QR 扫码发表由用户手动完成)。

wechat-channels-video 是什麼?

这个 AI 代理技能 (skill) 旨在让开发者或 AI 助理能够以程序化的方式在微信视频号助手 (channels.weixin.qq.com) 保存视频草稿。它通过 Ego Lite 浏览器工具控制浏览器,实现从视频上传、描述填写到草稿保存的完整流程。该技能特别强调“只保存草稿,不自动发表”——最终发表需要用户手动通过 QR 码完成,以确保安全。它支持多个平台,如 Claude Code、Cursor 或 Codex,并提供了详尽的脚本和 Ego 浏览器 API 来管理登录状态、文件上传以及表单填写。开发者可根据预定义的输入(如本地视频路径、描述、短标题等)调用此技能,而技能内置的“check-login”脚本会强制检查微信视频号的登录态(过期很快),防止在未登录状态下操作。总之,这是一个自动化视频草稿编辑的工具,适用于需要将本地视频内容快速发布到微信视频号草稿箱的场景。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/terryso/ego-skills/tree/main/skills/wechat-channels-video

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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(nameid)`
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。

避坑清單

  1. wujie shadow:查詢從 wujie-app.shadowRoot 起。
  2. 直鏈 create 白屏:必須 UI 路徑進入發表頁。
  3. wujie 內 ref/text 點擊被攔截 → evaluate 或座標點擊。
  4. 長文案只經 evaluate 參數傳入。
  5. 描述用 execCommand;短標題用 native setter。
  6. 位置兩段式座標 + 回讀驗證。
  7. 封面只能 waitForFileChooser。
  8. 上傳驗證只看 DOM;上傳後先存草稿。
  9. 草稿落盤前不導航離開。
  10. 登錄頁「加載失敗」是紅鯡魚;handOff 讓人掃碼。
  11. 每次發布前 check-login;exit 2 必須停。
  12. 發表是人工終點;本技能只到草稿。

測試

npm test

相關技能