wechat-channels-video は何をしますか?
Ego Lite セッションを使用して 视频号助手 に 動画の下書きを保存 します。「公開」はクリックしません(QRコードでの公開は人間に委ねます)。
Save a WeChat Channels draft through Ego Lite. Never click Publish — QR publish is human-only.
事前準備:Ego のインストール
Ego Lite をインストールし、ego-browser が PATH に含まれていることを確認してください。不足している場合はソフトフェイルし、ユーザーにインストールを促します。ブラウザを直接操作しないでください。
毎回の公開前:ログインチェック(必須)
视频号のログイン状態は非常に早く期限切れになります。Agent はアップロードやフォーム入力の前に以下を実行する必要があります:
node scripts/check-login.mjs
# ユーザーにQRコードスキャンのためにウィンドウを残す場合:
node scripts/check-login.mjs --keep
| 終了コード | 意味 | Agent のアクション |
|---|---|---|
0 | ログイン済み | login_tip をユーザーに表示し、処理を続行 |
2 | 未ログイン / ego-browser なし | how_to_login / how_to_login_zh を表示し、停止。ユーザーが Ego でQRコードをスキャンした後、check-login を再実行 |
1 | その他のエラー | JSON error を報告し、公開済みと偽装しない |
詳細は references/login.md を参照してください。別途 cookie-healthcheck スキルを作成しないでください。
入力(汎用、ローカル製品パスは不使用)
呼び出し元は動画とテキストフィールドを提供します。references/inputs.md を参照してください。本スキルは ~/… のようなビジネスディレクトリをハードコードしません。
最低限必要なもの:ローカルの video パス、description、short_title。オプション:tags、cover、位置情報/オリジナル/イベント。
CLI 薄型スクリプト(安定部分)
ego-browser nodejs はシェルの argv を転送しません。check-login は一時的なエントリと 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全体を1つの巨大なスクリプトにまとめないでください:wujie、座標クリック、カバーの waitForFileChooser などは Agent がスナップショット/スクリーンショットを見て判断する必要があります。スクリプトはログインとファイル転送の判定可能な部分を担当し、フォーム入力は以下の Agent 手順に従います。
ego-browser API クイックリファレンス
ego-browser nodejs を実行するたびに新しいプロセスが起動します。TaskSpace / Page は呼び出し間で永続化されず、JS 変数も永続化されません。
| API | 説明 |
|---|---|
taskSpace(name|id) | 1ユーザー目標に1つの space;spaceId を記録して再利用 |
task.page("p1") | 最初の画面は goto で再利用;ページをむやみに開かない |
page.snapshot() | 観察用(open shadow を見通せる);クリックは wujie 内でよくインターセプトされる |
page.evaluate(fn, arg) | 1つの JSON シリアライズ可能なパラメータのみ受け付ける(長いテキストはこちら) |
page.mouse.click(x, y) | wujie 内のポップアップでよく使用 |
page.waitForFileChooser() | カバーアップロードの唯一の確実な方法 |
task.handOff() | 人間にQRコード公開/ログインを委ねる |
task.finish({ keep: [] }) | 後片付けで space を閉じる;人間が続けて見る必要がある場合は handOff を使用し、長期間マシンを占有しない |
重要: snapshot は wujie shadow を見通せます;ref/text クリックはポインターイベントのインターセプトを報告します。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 を使用して非表示のファイル入力に注入します(動画コンポーネントは 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 チェックポイント:先に下書き保存
アップロード完了後、すぐに「下書きを保存」ボタンを1回クリックしてから、説明文/短タイトル/位置情報を入力し、最後にもう一度保存します。途中で問題が発生して大きなファイルを再アップロードする事態を避けるためです。
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> です。ネイティブセッターを使用する必要があります;input.value を読み取って検証します(innerText には input の値は含まれません)。
4. 位置情報
デフォルトで都市が含まれることがよくあります。確実な方法:mouse.click で開く → スナップショット/スクリーンショット → 「位置情報を表示しない」をクリック → フィールドを読み戻して確認します。evaluate の座標は非表示のレイヤーにクリックしてしまう可能性があります。
5. 下書きを保存(終点)
「下書きを保存」をクリックします。成功の合図:「已保存」というメッセージと、下部のボタンがグレーアウトします。その後、下書きボックスに移動して確認します。下書きボックスが表示されるまではエディターから離れないでください。
オプション:オリジナル宣言、イベント検索(ネイティブセッターで検索語を入力;見つからなければ「イベントに参加しない」を選択)。
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、短タイトルはネイティブセッターを使用します。
- 位置情報は2段階の座標 + 読み戻し検証。
- カバーは waitForFileChooser のみ。
- アップロード検証は DOM のみ;アップロード後は先に下書きを保存します。
- 下書きが保存されるまでナビゲーションで離れない。
- ログインページの「読み込み失敗」はレッドヘリング;handOff で人間にQRコードスキャンを促します。
- 公開前に毎回 check-login;exit 2 の場合は必ず停止します。
- 公開は人間の終点;本スキルは下書きまでです。
テスト
npm test