※ この記事にはアフィリエイトリンクが含まれています。リンク経由で購入しても読者の皆さんに追加費用は発生しません。収益は本サイトの運営費に充てています。
Playwrightで操作を録画→ffmpegでMP4変換→Instagram Reels APIで投稿。この3ステップで、ブラウザ自動操作のデモ動画をSNSに自動投稿できる仕組みを作りました。実際に投稿したReelsはPlaywrightがInstagramにログインして自己紹介を自動入力する35秒のデモ動画です。
こんな方に読んでほしい記事です:
- Playwrightの
recordVideo機能を実用的に使いたい - ブラウザ自動操作のデモ動画をSNSで共有したい
- Instagram Reels APIで動画投稿する実装コードが欲しい
- 前回のInstagramプロフィール自動設定の続きを追いたい
なぜPlaywrightの録画機能でReelsを作ろうと思ったのか
最初はDALL-E 3でカルーセル画像(図解スライド5枚)を作ってInstagramに投稿しました。結果は散々でした。DALL-E 3は日本語テキストの描画が壊滅的で、図解として全く読めない。
それなら実際の操作画面を見せた方がいい。PlaywrightにはrecordVideoという画面録画オプションがあります。テスト用途で使われることが多い機能ですが、「操作のデモ動画を撮影してSNSに投稿する」というコンテンツ制作ツールとして使えるのでは?と考えました。
Playwrightの画面録画の仕組みと設定コード
Playwrightの録画機能(公式ドキュメント)は、browser.newContext()のオプションで有効化します。特別なライブラリは不要です。
基本的な録画設定
const context = await browser.newContext({
// モバイルエミュレーション(Instagram用)
userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0...)",
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
// ここが録画設定
recordVideo: {
dir: "drafts/videos", // 保存先ディレクトリ
size: { width: 390, height: 844 }, // 録画サイズ
},
});
これだけで、このcontextで開いたページの操作がすべて動画として記録されます。出力形式はWebM。録画を止めるにはcontext.close()を呼びます。
注意点:context.close()を忘れると動画が保存されない
Playwrightの録画はcontext.close()のタイミングでファイルに書き出されます。browser.close()だけだと動画が不完全になることがあるので、必ず先にcontextをcloseするのがポイントです。
// ✅ 正しい順番
await context.close(); // ← ここで動画が書き出される
await browser.close();
// ❌ これだと動画が不完全になる場合がある
await browser.close(); // contextのcloseがスキップされる
「映える」デモ動画を撮るための工夫
テスト用の録画と、SNS投稿用の録画は要件が全然違います。正直、最初に撮った動画は134秒のうち大半が「Save your login info?」ダイアログの静止画面で使い物になりませんでした。2回目で以下の工夫を入れて35秒のコンパクトな動画に仕上げました。
工夫1:タイピングを1文字ずつ見せる
// 通常のfill()は一瞬で入力される→動画的に面白くない
await field.fill(username); // ← 一瞬で完了
// type()でdelayを設定すると1文字ずつ入力される→映える
for (const char of username) {
await field.type(char, { delay: 80 }); // 80msごとに1文字
}
自動化が目に見える瞬間がSNSでは一番インパクトがある。特に「文字が勝手に入力されていく」シーンは再生を止めて見てしまう効果があります。
工夫2:ダイアログは即座にevaluate()で閉じる
// waitForTimeout()で待つと無駄な静止画面が長くなる
// evaluate()で即座に閉じる
await page.evaluate(() => {
const btns = document.querySelectorAll('div[role="button"]');
for (const btn of btns) {
const t = btn.textContent?.trim() || "";
if (t === "Not now" || t === "後で") {
btn.click();
return;
}
}
});
ダイアログが表示された瞬間に閉じるので、動画には一瞬だけ映って消える。「あ、ダイアログも自動で閉じてる」という印象を与えつつ、無駄な待ち時間を排除できます。
工夫3:パスワード入力は高速で
パスワードは伏せ字(●●●)で表示されるので、1文字ずつ見せても意味がない。fill()で一瞬で入力します。ユーザー名はゆっくりタイピング、パスワードは瞬時に入力。このメリハリが動画のテンポを良くします。
工夫4:シーンの構成を事前に設計する
今回の35秒動画の構成は以下の通りです。
| 秒数 | シーン | 見どころ |
|---|---|---|
| 0〜3秒 | ログインページ表示 | Instagramの画面が映る |
| 3〜8秒 | ユーザー名タイピング | 文字が1文字ずつ入力される |
| 8〜10秒 | パスワード+ログイン | 瞬時に入力→ボタン押下 |
| 10〜18秒 | ログイン完了→遷移 | ダイアログを自動で閉じる |
| 18〜28秒 | 自己紹介文をタイピング | Bio欄に文字が入力されていく |
| 28〜35秒 | 完成プロフィール表示 | フクロウアイコン+自己紹介が映る |
ぶっちゃけ動画制作のプロからすれば素人レベルだと思いますが、「コードで生成した動画」という文脈ではこれで十分なインパクトがあります。
失敗した1回目の動画と改善
1回目に撮った動画は134秒。サムネイルを抽出して確認したところ、67フレーム中50フレーム以上が「Save your login info?」ダイアログの静止画面でした。ダイアログをwaitForTimeout(2000)で待っていたのが原因です。2回目ではevaluate()で即座に閉じる方式に変更し、35秒に短縮。録画する前にシーン構成を設計して、waitの秒数を最小限にするのが鉄則です。
ついでに:Threadsへの投稿も同時に行う
動画と同じ内容をThreadsにはテキスト投稿しました。ここで1つハマりポイントがあって、bashのCLI引数で複数行テキストを渡すとWindows環境で最初の1行しか投稿されない問題が発生。原因はbashの引数処理で改行が切られること。テキストファイル(.txt)に書き出して、ファイルパスを引数として渡す方式に変更して解決しました。
# ❌ 最初の1行しか投稿されない
npx tsx src/publish/threads.ts '1行目
2行目
3行目'
# ✅ ファイル経由なら全文投稿される
npx tsx src/publish/threads.ts post.txt
地味ですが、複数行テキストをCLIで扱うときはファイル経由が安全です。
WebMからMP4への変換——Instagram Reelsの要件
Playwrightの録画出力はWebM形式ですが、Instagram Reels APIはMP4しか受け付けません。ここで登場するのがffmpegです。
ffmpegとは
ffmpegは動画・音声の変換、編集、ストリーミングを行うオープンソースのコマンドラインツールです。YouTubeやニコニコ動画など多くの動画サービスのバックエンドでも使われています。GUIの動画編集ソフトと違い、コマンド1行で変換処理が完結するのでスクリプトとの相性が抜群。今回のようなパイプライン(Playwright録画→変換→アップロード)に組み込むならffmpeg一択です。
インストールは公式サイトからバイナリをダウンロードするか、macOSならbrew install ffmpeg、Windowsならwinget install ffmpegで入ります。
Instagram Reelsの動画要件
| 項目 | 要件 |
|---|---|
| 形式 | MP4(H.264コーデック) |
| アスペクト比 | 9:16(縦長) |
| 推奨解像度 | 1080 x 1920 |
| 最大長さ | 90秒 |
ffmpegの変換コマンド
ffmpeg -i recording.webm \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black,setsar=1" \
-c:v libx264 -preset fast -crf 23 \
-pix_fmt yuv420p -an -movflags +faststart \
output.mp4
ポイントは3つ。
scale=1080:1920:9:16のアスペクト比にリサイズ。force_original_aspect_ratio=decreaseで比率を維持し、padで余白を黒く埋める-pix_fmt yuv420p:Instagramが要求するピクセルフォーマット。これがないとアップロード時にエラーになる-an:音声なし。Playwrightの録画には音声がないので明示的に除外
Instagram Reels APIでの動画投稿——実装コード
変換したMP4をInstagram Reels APIで投稿します。画像投稿と同じく2ステップですが、動画は処理時間が長いので待機が必要です。
Step 1: コンテナ作成
const createRes = await fetch(
`https://graph.instagram.com/v22.0/${userId}/media`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
media_type: "REELS", // ← REELSを指定
video_url: videoPublicUrl, // 公開URLが必要
caption: "キャプション",
access_token: token,
}),
});
const { id: containerId } = await createRes.json();
重要なのはvideo_urlにローカルファイルパスは使えない点。公開URLが必要なので、先にWordPressのメディアライブラリにアップロードしてそのURLを使います。
Step 2: 動画処理を待って公開
// 動画の処理に時間がかかる(30秒程度待つ)
await new Promise(r => setTimeout(r, 30000));
const publishRes = await fetch(
`https://graph.instagram.com/v22.0/${userId}/media_publish`, {
method: "POST",
body: JSON.stringify({
creation_id: containerId,
access_token: token,
}),
});
画像投稿では5秒待ちで十分でしたが、動画は30秒は待つ必要があります。処理が完了していない状態で公開APIを叩くとエラーになります。正直、ステータスをポーリングする方が確実ですが、30秒固定待ちでも今のところ問題なく動いています。
全体のパイプラインと技術スタック
今回構築した「録画→変換→投稿」のパイプラインをまとめます。
Playwright (recordVideo)
│ WebM出力
▼
ffmpeg
│ MP4変換 (1080x1920, H.264)
▼
WordPress REST API
│ メディアアップロード(公開URL取得)
▼
Instagram Reels API
│ コンテナ作成→公開
▼
Instagram Reels として公開 🎬
- 言語:TypeScript(
tsxで直接実行) - 録画:Playwright recordVideo
- 変換:ffmpeg(WebM→MP4、H.264、9:16リサイズ)
- アップロード:WordPress REST API(公開URL取得用)
- 投稿:Instagram Graph API(Reels)
- ホスティング:ConoHa WINGの料金プランを確認する
関連書籍
今回の実装に関連する書籍を紹介します。
- 『入門 Webフロントエンド E2E テスト』を楽天で見る——Playwrightの基礎。recordVideoの使い方もカバーされています
- 『Web API設計実践入門』を楽天で見る——Instagram Graph APIやThreads APIのようなREST APIの設計思想を理解するのに役立ちます。2ステップ投稿(コンテナ作成→公開)の設計意図が分かるようになります
まとめ:Playwrightは「テスト」だけのツールじゃない
Playwrightの録画機能はE2Eテストのデバッグ用として紹介されることがほとんどです。でも「ブラウザ操作のデモ動画を自動生成してSNSに投稿する」という使い方は、エンジニアのコンテンツ制作ツールとして正直かなり強い。
- コードを書くだけで再現性のあるデモ動画が作れる
- 画面構成やタイミングをコードで制御できる
- モバイルエミュレーションで9:16の縦動画が自然に撮れる
- DALL-E 3の図解画像より圧倒的にリアルでインパクトがある
「自動化の過程を見せる」コンテンツは、文章よりも動画の方が伝わる。Playwrightを使っているなら、テストだけでなくコンテンツ制作にも活用してみてください。
進展があればまたこのブログで報告します。


コメント