publish-md-to-wechat について
Markdown 記事の WeChat 公式アカウント草稿への公開、WeChat 動画の生成、転載前の記事翻訳を支援するスキルです。記事のスタイルや画像・カバーの処理と、動画の計画・検証を別々のワークフローで扱います。
主な機能
- 01Markdown 記事を整形して草稿として公開
- 02記事画像の処理とカバーの生成
- 03ナレーションと字幕付き縦型 MP4 の生成
- 04全文翻訳後に草稿として公開
- 05カスタム記事スタイルの作成と管理
活用シーン
- 01Markdown 記事を WeChat に公開
- 02記事をナレーション付き縦型動画に変換
- 03外国語の記事を翻訳して転載
- 04Vault 記事の公開用 frontmatter を調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ walk4rever/ publish-md-to-wechat --skill publish-md-to-wechatインストール後、Claude Code で/publish-md-to-wechatを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignoreAGENTS.mdenv.exampleSECURITY.mdREADME.mdLICENSETODO.mdCNAMEpackage-lock.jsonpackage.jsonpyproject.tomlindex.htmlinstall.shrequirements.txtevals/evals.jsonevals/files/test.mdtest_features.mdreferences/styles.mdwechat_logic.mdscripts/air7_publisher.pyclear_drafts.pyrender_formulas.jsvideo_publisher.pyvideo_pipeline.pygenerate_cover.pystyles.pywechat_publisher.pytemplates/video/gen_scenes.pytests/test_styles.pytest_video_pipeline.py詳細
publish-md-to-wechat
Markdown 記事を、プロフェッショナルなビジュアルスタイル、自動画像処理、カバー画像生成により、WeChat 公式アカウントの下書きとして公開します。
動作モード(厳密に区別)
モード A — 記事の公開(公式アカウント記事)
ユーザーが Markdown から WeChat の下書きへの公開を希望する場合に使用します。
- 入力:
--md、スタイル、任意のサムネイル/タイトル - 出力:WeChat の下書きメディア ID
- コマンド群:
scripts/wechat_publisher.py
モード B — 動画のレンダリング(動画アカウント)
ユーザーが縦型 MP4 の生成を希望する場合に使用します。
- 入力:元記事、再生時間、トーン、対象読者、ビジュアルスタイル、任意の Edge TTS 音声
- 出力:ローカルの
.mp4 - コマンド群:
scripts/video_publisher.py - 重要: エージェントが動画の計画を立て、プロジェクトファイルを作成します。スクリプトはレンダリング、ナレーション、字幕付け、合成を行い、検証用フレームをキャプチャします。
モード C — 翻訳と再投稿(全文翻訳/転載)
ユーザーが外国語の記事を翻訳して WeChat に公開することを希望する場合に使用します。
- トリガー:「全文翻訳」「転載」「translate」「repost」、または元記事が英語などの外国語である場合。
- 入力:元の Markdown ファイル(英語またはその他の言語)
- 出力:WeChat の下書きメディア ID(モード A と同じ)
- ワークフロー:エージェントがネイティブに翻訳(Python スクリプトは使用しません)→
/tmp/translated_article.mdに保存 → モード A に進みます。 - 重要: 翻訳はエージェント自身が行い、スクリプトでは行いません。翻訳のために Python 経由で LLM を呼び出さないでください。
ユーザーが両方の成果物を明示的に求めた場合を除き、モード A とモード B の手順を同じフローで混在させないでください。 モード C は必ずモード A の公開で終了します。独立したパイプラインではなく、前処理のステップです。
フェーズ 1:環境と認証情報
依存関係を確認します:
ls .venv/bin/python 2>/dev/null || echo "MISSING"
.venv がない場合は、./install.sh を実行します。
認証情報: 現在のディレクトリにある .env、またはグローバルなフォールバックとして
~/.config/publish-md-to-wechat/.env から自動的に読み込まれます。スクリプトで認証エラーが明示的に発生した場合に限り、ユーザーに認証情報を尋ねてください。
フェーズ 1B:モード C — 翻訳と再投稿
要約や翻案はせず、記事全体を忠実に翻訳してください。
- 元の Markdown ファイルを最後まで読みます。
- 内容全体を中国語に翻訳し、次の要素を保持します:
- Markdown の構造(見出し、リスト、コードブロック、引用、画像)
- 元のセクションの順序と階層
- 標準的な技術用語は英語のままにします(例:agent、token、context window、bash)
- コードブロックはそのまま保持し、翻訳しません
- フロントマターの著者表記:
> 本文译自:[原文标题](url),作者:[Author]([Publication])
- 中国語の
title、author、descriptionを含む YAML フロントマターを記述します。 /tmp/translated_article.mdに保存します。- 翻訳済みファイルを
--mdとしてフェーズ 2 に進みます。
翻訳前に確認を求めないでください。ユーザーが「全文翻訳/転載」と言った場合は、そのまま翻訳してください。
フェーズ 1C:フロントマターの調整(Vault 記事)
Vault 記事を公開する前に、WeChat パブリッシャーが記事のヘッダーを正しく表示するために必要なフィールドがフロントマターに含まれていることを確認してください。
パブリッシャーは、記事の冒頭に次の特定のキーを使ってメタデータブロックを表示します。
| WeChat キー | 表示内容 | Vault で一般的な別名 | 対応 |
|---|---|---|---|
author | 作者 | 同じ | ✅ 通常は存在します |
published | 公開日 | date | ⚠️ date: しかない場合は published: を追加します |
tags | タグ一覧 | — | ⚠️ なければ追加します |
description | 概要 | excerpt | ⚠️ excerpt: しかない場合は description: を追加します |
source | 出典 | — | ⚠️ Vault 記事には source: AI-DIVE · ai.air7.fun を追加します |
スクリプトのフォールバック(組み込み): パブリッシャースクリプトは自動的に次のフォールバックを適用します。
publishedがない場合はdateを使用しますdescriptionがない場合はexcerptを使用します
そのため、公開前にこれらの別名ペアを手動で修正する必要はありません。残りの 3 つ(author、tags、source)には自動の別名がないため、欠けている場合はフロントマターに追加してください。
Vault から WeChat 記事を作成する場合の、最小限の完全なフロントマター:
---
title: 文章标题
slug: type-YYYY-MM-DD-topic # ai-dive API
date: YYYY-MM-DD # ai-dive API
published: YYYY-MM-DD # WeChat header display
type: analysis # ai-dive API
author: Rafa
tags: [标签1,标签2, 标签3] # WeChat header display
excerpt: 摘要文字 # ai-dive API
description: 摘要文字 # WeChat header display (same content as excerpt)
source: AI-DIVE · ai.air7.fun # WeChat header display
og_image: https://... # ai-dive cover (fill after upload)
cover: assets/topic-cover.png # local preview
---
注: date と published には同じ値を設定し、excerpt と description には同じ内容を設定します。2 つのシステムでは、同じ概念に異なるキーを使用します。
フェーズ 2:記事を読み、スタイルを選択する
Markdown ファイルを読んで、内容のトーンを把握します。その後、スタイルを選択します。
すべてのスタイルを一覧表示:
.venv/bin/python3 scripts/styles.py --list
スタイル選択ガイド:
| カテゴリー | スタイル | 使用する場面 |
|---|---|---|
| ⭐ コア | swiss、editorial、ink | デフォルトの選択肢です。コンテンツの種類の 90% をカバーします。 |
| 📦 拡張 | notebook、geometry、botanical、terminal、bold、cyber、voltage | 特定のシナリオに限って使用します。 |
| 🎨 カスタム | custom-xxx | WeChat 記事の分析をもとにユーザーが作成します。 |
コア 3 スタイルのクイックガイド:
swiss— 技術記事、チュートリアル、レポート、公式発表editorial— オピニオン記事、分析記事、ブログ投稿、パーソナルブランドink— 人文科学、文化、深掘り記事、文学的なコンテンツ
スタイルを 1 行の理由とともに提案します。ユーザーがすでに指定している場合は省略します。
フェーズ 3:最初に検証する(複雑な記事に推奨)
.venv/bin/python3 scripts/wechat_publisher.py \
--md [PATH] --style [STYLE] --dry-run --out-html /tmp/preview.html
open /tmp/preview.html
フェーズ 4:公開する
.venv/bin/python3 scripts/wechat_publisher.py \
--md [PATH] --style [STYLE]
主なフラグ:
--thumb [PATH]— カスタムカバー(省略した場合は自動生成)--title "[TITLE]"— タイトルを上書き(フロントマターまたは H1 から自動検出)--no-verify-ssl— SSL 証明書に問題がある場合に使用します-v— 詳細ログを表示します
YAML フロントマター: タイトル、作成者、概要を自動抽出します。
---
title: Article Title
author: Author Name
description: Short summary for WeChat article list.
---
フェーズ 4B:WeChat 動画(视频号)を生成する
デフォルトでは、明示的に不要と指示されない限り、必ず TTS 音声付きで動画を生成してください。 重要: 動画を生成する前に、リクエスト内で明示されていない場合は、必ず以下の希望をユーザーに確認してください。
- 動画の長さ(例:30s、60s、90s)
- ナレーションのトーン(例:专业克制、轻松幽默、热情洋溢)
- 対象視聴者(例:AI开发者、产品经理、大众)
- ビジュアルスタイル(例:swiss、ink、minimal)
- TTS 音声(任意。デフォルトは
zh-CN-YunxiNeural)
この 5 つのパラメーターを推測したり、決めつけたりしないでください。 ユーザーが「動画に変換して」とだけ言った場合は、必ず作業を止め、動画の長さ、トーン、対象視聴者、スタイルを指定するよう確認してください。
ステップ 1:エージェントがシーンを計画する(LLM 呼び出しに Python スクリプトを使用しないでください)
Markdown ファイルを読みます。プレゼンテーション編集の専門家として、指定された動画の長さ、トーン、対象視聴者、ビジュアルスタイルに基づいて、scenes.txt と gen_scenes.py を含む動画プロジェクトディレクトリをネイティブに作成してください。
空の Python ファイルから始めず、まずプロジェクトを作成してください。
.venv/bin/python3 scripts/video_publisher.py --init-project /tmp/video-project
次に、/tmp/video-project/scenes.txt と /tmp/video-project/gen_scenes.py を編集します。同梱のジェネレーターはビジュアルのベースラインです。1080×1920 のキャンバス、ブランドライン、ページ番号、下部バー、コントラスト、共通 CSS は維持し、ストーリーに合わせてコピーとレイアウトを調整してください。
重要:ナレーションの品質ルール(冗長さや繰り返しを避ける)
- 対象視聴者とトーンは全体に適用される制約であり、シーンごとのスローガンではありません。各シーンで「面向AI开发者」や「关键在于」のようなフレーズを繰り返さないでください。
- 各シーンのナレーションには、テンプレートの水増しではなく、新しい情報(事実、例、対比、実践手順)を含めてください。
- 空疎な導入文は避けてください。直後に具体的な内容が続く場合を除き、「我们来看看」「关键在于」「总的来说」は使用しないでください。
- ナレーションは簡潔で話し言葉らしくしてください。通常、1 シーンにつき短い文を 1〜3 文にし、段落のように長々と話さないでください。
- シーン間で同じ文の型を繰り返さないでください。
- 抽象的なバズワードより、具体的な表現を優先してください。
ファイルを書き込む前のナレーションのセルフチェック:
- すべてのシーンのナレーションを通して読みます。
- 3 つ以上のシーンで同じフレーズの語幹(例:
面向…、关键在…)が繰り返されていたら、書き直します。 - 各シーンに、1 行で表せる固有の要点があることを確認します。
- 情報を含まない冗長な表現をすべて削除します。
重要:縦型動画(9:16)向けの HTML シーン形式
scenes.txtには、順番に並んだシーンを 1 行につき 1 つ記述します:S1|spoken narration|optional written subtitle。gen_scenes.pyは、1080×1920 でscenes/S1.html、scenes/S2.htmlのような HTML ファイルを生成する必要があります。- ジェネレーター内では、安定したブランドライン、ページ番号、下部の情報バー、高コントラストのテキスト、控えめなアクセントカラーを備えた共通 CSS システムを使用してください。
- URL や英語の用語については、音声と字幕でテキストを変えてもかまいません。たとえば、音声では
air7 点 funと読み上げ、字幕ではair7.funと表示します。 - 各シーンでは 1 つのアイデアだけを扱います。スクリプトは生成した音声からタイミングを決定し、短い間を加え、字幕を動画に焼き込みます。
ステップ 2:レンダリングと合成(実行のみ) スクリプトを使って HTML を生成し、シーンの PNG をキャプチャし、ナレーションを合成して字幕を作成し、MP4 を合成し、開始・中間・終了の QA フレームをキャプチャします。
# 导出 MP4
.venv/bin/python3 scripts/video_publisher.py \
--project-dir /tmp/video-project \
--duration [SECONDS] \
--voice zh-CN-YunxiNeural \
--rate +6% \
--out [OUTPUT.mp4]
依存関係:ffmpeg、Python Playwright Chromium、edge-tts。
ステップ 3:必須のビジュアル QA
build/check_start.jpg、build/check_middle.jpg、build/check_end.jpg を開きます。字幕の改行、読みやすいコントラスト、テキストのはみ出し、スペル、ナレーションとシーンの整合性を確認してください。フレームに問題がある場合は、scenes.txt / gen_scenes.py の該当するシーンだけを変更し、レンダラーを再実行します。このチェックに合格するまでは、動画の完成を報告しないでください。
フェーズ 5:成功時の出力
## 🚀 发布成功!
| 字段 | 值 |
|------|-----|
| **标题** | [Title] |
| **风格** | `[style]` — [one-line description] |
| **Media ID** | `[MEDIA_ID]` |
**下一步:** mp.weixin.qq.com → 草稿箱 → 预览 → 发布
カスタムスタイル
スタイルの再現には、色を正確に取得するために、インライン CSS の解析ではなく Playwright の getComputedStyle() を使用します。また、構造パターンも自動で検出します。
- 見出しスタイル:
bg-block(色付きのセクション背景)/left-border/underline/plain - 引用スタイル:
left-border/full-box/plain
カスタムスタイルで公開する際、レンダラーはこれらの構造に関するヒントを適用します。
# Create from WeChat article (give it a meaningful name)
.venv/bin/python3 scripts/styles.py --url https://mp.weixin.qq.com/s/xxx --name custom-myname --no-verify-ssl
# List all styles (core / extend / custom)
.venv/bin/python3 scripts/styles.py --list
# Rename
.venv/bin/python3 scripts/styles.py --rename custom-old custom-new
# Use
.venv/bin/python3 scripts/wechat_publisher.py --md article.md --style custom-xxx
トラブルシューティング
| エラー | 対処法 |
|---|---|
| 40164 IP ホワイトリスト | mp.weixin.qq.com → 设置与开发 → IP白名单 に IP を追加します |
| 40125 / 40013 認証情報が無効 | .env を確認します |
| 45009 レート制限 | 自動で再試行します。解消されない場合は待ってください |
| 45166 無効なコンテンツ(アンカーリンク) | 記事に href="#anchor" リンク(目次など)が含まれています。これらは v0.7.0 以降、後処理によって自動的に削除されます。古いバージョンでこのエラーが発生した場合は、アップグレードしてください。 |
| SSL エラー | --no-verify-ssl を追加します |
| 画像が見つからない | ファイル名(大文字と小文字を区別)を確認し、画像が記事のディレクトリにあることを確認します |
| カバー画像の設定に失敗 | assets/default_thumb.png にフォールバックします。または --thumb を使用します |
| 依存関係の不足 | ./install.sh を実行します |
WeChat の既知のレンダリング制約
これらは WeChat の HTML レンダラーにおけるプラットフォームレベルの制限です。v0.7.0 以降、後処理によって自動的に処理されます。
| 制約 | 動作 | 自動修正 |
|---|---|---|
画像に data-src が必要 | WeChat は data-src を使用して画像を遅延読み込みします。src だけの画像は空白として表示されます。 | 後処理によって URL のアップロード後、すべての <img> に data-src が追加されます。 |
<ol>/<li> 間の空白ノード | <li> タグ間の空白テキストノードは、番号付きの空白項目として余分に表示されます。 | 後処理によって .footnotes セクション全体が、インライン番号付きのフラットな <section> 要素として再構築されます。 |
アンカーリンク(href="#")がブロックされる | <a href="#..."> が含まれていると、下書き API は 45166 を返します。 | 後処理によって、# で始まるすべての <a> タグが解除され、プレーンテキストになります。 |
| 脚注の戻りリンク | mistune は各脚注の末尾に、WeChat では意味をなさない戻りリンク ↩ を挿入します。 | 後処理によって、すべての <a class="footnote"> タグが削除され、残った ↩ 文字も取り除かれます。 |