vscode-playwright について
VS Code エディターのスクリーンショットを撮影し、ブラウザーアニメーションを単体の無音 WebM クリップとして記録するスキルです。CI 向けの再現可能なスクリプト実行と、Playwright MCP による対話型の単発撮影に対応します。
主な機能
- 01VS Code のスクリプト撮影
- 02Playwright MCP による対話型撮影
- 03スクリーンショット検証と文字サイズ計測
- 04ブラウザーアニメーションの WebM 記録
- 05ビューポート設定とエディター整理
活用シーン
- 01スライドやドキュメント用の VS Code 画像作成
- 02CI での再現可能なスクリーンショット撮影
- 03HTML アニメーションの無音 WebM 記録
MCP 対応
対話型の VS Code 撮影では、Playwright MCP サーバーが提供するブラウザーツールを使用します。スクリプト撮影とブラウザーアニメーション記録には MCP は不要です。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ hve-core --skill vscode-playwrightインストール後、Claude Code で/vscode-playwrightを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
pyproject.tomluv.lockscripts/capture_vscode.pyrecord_browser_video.pytests/fuzz_harness.pytest_capture_vscode.pytest_record_browser_video.pytests/corpus/not-a-mapping.ymltraversal-plan.ymlvalid-plan.yml詳細
VS Code とブラウザーのキャプチャスキル
VS Code のエディタービュー、コードのウォークスルー、Copilot Chat の例をキャプチャし、自己完結型のブラウザーアニメーションシーンを無音の WebM クリップとして記録します。
概要
このスキルでは、スライドデッキ、ドキュメント、その他のビジュアルメディアへの埋め込みに適した、高品質な VS Code スクリーンショットをキャプチャするための完全なワークフローを提供します。サーバーのライフサイクル管理、ビューポート設定、UI の整理、スクリーンショットの検証に対応しています。
2 つの方法で同じ制約を共有します。繰り返し行うキャプチャや、CI を含む無人キャプチャにはスクリプトを使う方法を推奨します。探索的なキャプチャや単発のキャプチャには、対話型の Playwright MCP 方法を使ってください。
スクリプトによるキャプチャ
scripts/capture_vscode.py は、YAML のキャプチャプランをヘッドレスで実行します。serve-web を起動し、キャプチャ設定を適用して、各ファイルを Monaco で開き、レンダリングされたフォントサイズを測定して、キャプチャごとにスクリーンショットを 1 枚書き込みます。Playwright を直接操作するため、MCP サーバーは不要で、CI ランナーで実行できます。
uv sync
uv run playwright install --with-deps chromium
uv run python scripts/capture_vscode.py --plan capture-plan.yml --workspace /path/to/repo
プランでは、各キャプチャの id、ワークスペースからの相対パスで指定する file、およびプランディレクトリからの相対パスで指定する output を記述します。--output-root が指定されている場合は、output はそのディレクトリからの相対パスになります。id は、英字、数字、.、_、- のいずれかで構成される、ファイル名として安全な単一のトークンです。output は / 区切りで .. を含まない相対 .png パスであり、スクリプトは出力ルート外やシンボリックリンク経由への書き込みを拒否します。
resolution: 1920x1080
min_font_pt: 18
font_size: 26
theme: Default Dark Modern
captures:
- id: marketplace-catalog
file: .github/plugin/marketplace.json
output: frames/marketplace-catalog.png
すべてのキャプチャが書き込まれ、min_font_pt を満たした場合に限り、スクリプトは 0 で終了します。また、各キャプチャの測定済み rendered_font_size_pt、zoom、source_resolution を含む JSON 結果を、最後の stdout 行に 1 つ出力します。キャプチャに失敗した場合は、debug-<id>.png も書き込みます。プランの検証時に Markdown を対象とする指定を拒否し、ダークテーマが適用されない場合は失敗するため、明るいテーマのキャプチャが混在しても通過しません。CI で出力をパイプ処理する場合は、パイプの失敗時に終了コードが保持されるよう、shell: bash でステップを実行してください。
ブラウザーアニメーションの記録
scripts/record_browser_video.py は、準備完了シーンのフレームから、自己完結型の HTML アニメーション 1 つを無音の WebM クリップとして記録します。シーンでは、ローカルアセットとアニメーション状態の準備ができた後に、body に data-animation-ready="true" を設定し、ナラティブの動きとタイマーをリセットする window.startAnimation() を定義する必要があります。記録はページのナビゲーション時ではなく、このハンドシェイク時点から開始されます。ブラウザーコンテキストはオフラインで、サービスワーカーはブロックされ、WebSocket トラフィックは転送せずにインターセプトされ、ポップアップは閉じられます。合成オリジンは、承認されたアセットルート以下のファイルのみを提供します。パストラバーサルと、ルート外に抜けるシンボリックリンクは拒否されます。デフォルトのルートはシーンのディレクトリです。シーンを含む、呼び出し元が承認した共有アセットディレクトリを指定するには、--asset-root を使ってください。ワークスペースやホームディレクトリをアセットルートとして許可しないでください。
uv run python scripts/record_browser_video.py \
--scene animation/scene-001/index.html \
--output clips/scene-001.webm \
--duration 8 \
--resolution 1920x1080
レコーダーは無音のクリップを書き込みます。対応するナレーション WAV と組み合わせて demo-video セグメントにすると、アセンブラーがブラウザークリップを指定されたナレーションの長さに合わせてトリミングまたはループし、最終的な音声を追加します。フレームは仮想シーン時間を使って 24 fps でサンプリングされ、その後 FFmpeg でエンコードされます。ブラウザーの起動時と終了時のフレームは除外されます。長さは動画フレームの境界まで正確です。
前提条件
スクリプトによるスクリーンショットのキャプチャには、VS Code または VS Code Insiders の CLI(code または code-insiders)が必要です。対話型の VS Code キャプチャには、本物の Playwright MCP ブラウザーツールと curl も必要です。ブラウザーアニメーションの記録には、uv、Playwright 1.48 以降を含むスキル環境、Chromium、および libvpx-vp9 対応の FFmpeg が必要です。VS Code と MCP は不要です。
このスキルで使うツール名には、mcp_microsoft_pla_browser_* というプレフィックスが付いています。実際のプレフィックスは、ホストにおける MCP サーバーの登録名から導出されるため、たとえば mcp_playwright_browser_* のように異なる場合があります。ホストが公開するプレフィックスを使ってください。
検証済みの制約
以下の3つの制約は、実行中の serve-web インスタンスで確認済みです。どれも、もっともらしく見えても機能しない方法を排除します。
- ユーザー設定はディスク上ではなく、ブラウザーの IndexedDB に保存されます。
--server-data-dir/data/User/settings.jsonに設定を配置しても、VS Code Web には反映されません。貼り付けイベントは EditContext によるキー処理と括弧の自動入力の両方を回避できるため、Preferences: Open User Settings (JSON)を開き、貼り付けイベントをディスパッチして設定を書き込み、その後保存してページを再読み込みしてください。再読み込みすると、Insiders でモーダルとして開かれフォーカスを保持する設定エディターが閉じ、ワークスペースの信頼性などのウィンドウレベルの設定が適用されます。永続ブラウザーコンテキストを使うと、再読み込み後も設定が維持されます。 - Markdown ファイルは Monaco エディターではなく、クロスオリジンのプレビュー WebView として開きます。ページから WebView の DOM にはアクセスできないため、その中にレンダリングされたテキストを調べたり、測定したりできません。スクリーンショットに測定可能なエディターテキストが必要な場合は、コードファイルまたは設定ファイルをキャプチャしてください。
- ツール名との照合ではなく、ナビゲーションを試みてブラウザーツールを確認してください。MCP ツールのプレフィックスはサーバーの登録方法によって異なります。VS Code 組み込みのブラウザーツールは、ページを読み込めても、VS Code Web ワークベンチにキーボードイベントもマウスイベントも送信できないことが確認されているため、これらのツールを使うと最初のコマンドパレット操作で失敗します。
アーキテクチャ
serve-web CLI は、VS Code Server のリリースをダウンロードし、内側の Node.js サーバーへの接続をプロキシする、Rust ベースのプロキシ(「サーバーのサーバー」)です。外側の CLI が受け付けるフラグは限られています。--server-data-dir は、ダウンロードしたサーバービルド、拡張機能、マシン状態など、サーバー側データの保存先を制御する重要なフラグです。ブラウザーの IndexedDB に保存されるユーザー設定は制御しません。
クイックスタート
- VS Code CLI の種類を検出し、Web サーバーを起動します。
- Playwright で VS Code Web インスタンスに移動します。
- UI を整理します(パネル、タブ、通知を閉じます)。
- ファイルを開いてスクリーンショットを撮影します。
- サーバーを停止して後片付けします。
ワークフローの手順
ステップ 1:VS Code CLI の種類を検出する
まず VSCODE_QUALITY 環境変数を確認します。この値に insider が含まれている場合は code-insiders を使います。それ以外の場合は、command -v code-insiders で利用可能か確認し、利用できなければ code に切り替えます。検出結果は再利用できるように保存します。
if [[ "${VSCODE_QUALITY:-}" == *insider* ]] || command -v code-insiders &>/dev/null; then
VSCODE_CLI="code-insiders"
else
VSCODE_CLI="code"
fi
ステップ 2:VS Code Web サーバーを起動する
一時的なサーバーデータディレクトリを作成し、serve-web を起動します。バックグラウンドターミナルでは、別のターミナルセッションのシェル変数を利用できないため、--server-data-dir にはリテラルパスを指定する必要があります。
VSCODE_SERVE_DIR=$(mktemp -d)
$VSCODE_CLI serve-web --port 8765 --without-connection-token \
--accept-server-license-terms --server-data-dir "$VSCODE_SERVE_DIR"
このディレクトリの下に data/User/settings.json ファイルを書き込まないでください。VS Code Web のユーザー設定はブラウザーの IndexedDB に保存されるため、設定ファイルを配置しても何も変わりません。ワークベンチの読み込み後に、コマンドパレットのコマンドでテーマを設定し、復元されたエディターを閉じて UI を非表示にしてください(ステップ 5)。レンダリングされたテキストのサイズは document.body.style.zoom で大きくします。
また、textarea セレクターを使って設定 JSON エディターに入力しようとしないでください。VS Code Insiders は textarea の代わりに EditContext API を使用するため、その要素は存在しません。
serve-web コマンドと mktemp は同じターミナルセッションで実行する必要があります。そうすれば $VSCODE_SERVE_DIR 変数が解決されます。バックグラウンドターミナル(isBackground: true)を使用する場合は、ブロック全体をインラインに記述してください。別のターミナルで設定した変数を参照しないでください。
先に進む前に、サーバーの準備ができていることを確認してください。curl -s -o /dev/null -w "%{http_code}" http://localhost:8765/ は 200 を返す必要があります。
サーバーログに Ignoring option 'server-data-dir': Value must not be empty と記録されている場合、変数が空になっています。サーバーは一時的なデータディレクトリではなく、既定のデータディレクトリを使用しています。プロセスを終了し、リテラルパスを指定して再起動してください。
ステップ 3:移動して待機する
mcp_microsoft_pla_browser_navigateを使って、ワークスペースhttp://localhost:8765/?folder=/path/to/workspaceに移動します。- VS Code の読み込みを待ちます。エディター UI が完全に描画されるまで、
mcp_microsoft_pla_browser_wait_forにtime: 5を指定します。
ステップ 4:ビューポートのサイズを変更する
スクリーンショットを挿入する PPTX のプレースホルダーに合わせて、ビューポートの配置比率を調整します。mcp_microsoft_pla_browser_resize を使い、アスペクト比が一致する解像度に変更します。
width_px = 1200 と height_px = int(1200 / (target_width_inches / target_height_inches)) を使って寸法を計算します。たとえば、5.5" x 4.2" のプレースホルダーの場合、ビューポートは 1200 x 916 になります。
スクリーンショットを 16:9 のスライド全体に表示する場合は、1200 px 幅のルールから算出せず、ビューポートを 1920x1080 に設定します。それ以外の配置では幅のルールを使い、1920x1080 は使わないでください。UI 要素を目標解像度で描画できるよう、クリーンアップの前にサイズを変更します。
ステップ 5:UI を整理する
Command Palette の手順を使い、mcp_microsoft_pla_browser_run_code でエディターをスクリーンショット撮影に適した状態にします。
- ワークスペースの信頼ダイアログが表示されている場合は閉じます。
mcp_microsoft_pla_browser_snapshotを撮って信頼ダイアログを探し、表示されていればmcp_microsoft_pla_browser_clickで「Yes, I trust the authors」をクリックします。 - 開いているエディターとタブをすべて閉じます。Command Palette ->
View: Close All Editors。 - 通知をすべて消去します。Command Palette ->
Notifications: Clear All Notifications。 - おやすみモードを有効にします。Command Palette ->
Notifications: Toggle Do Not Disturb Mode。 - プライマリサイドバーを閉じます。Command Palette ->
View: Close Primary Side Bar。 - 下部パネルを閉じます。最初に
mcp_microsoft_pla_browser_snapshotを撮ります。パネル(Terminal、Problems、Output)が表示されている場合は、Command Palette ->View: Close Panelを実行します。このコマンドは表示状態を切り替え、非表示のパネルを開くため、むやみに実行しないでください。 - セカンダリサイドバーを閉じます。最初に
mcp_microsoft_pla_browser_snapshotを撮ります。セカンダリサイドバー(Chat)が表示されている場合は、Command Palette ->View: Close Secondary Side Barを実行します。 - 読みやすさを高めるためにズームインします。全 UI のズームには、
mcp_microsoft_pla_browser_run_codeでawait page.evaluate(() => { document.body.style.zoom = '1.75'; })を使います。単一の倍率で十分だと判断しないでください。ズーム倍率を上げ、描画されたテキストのサイズを再測定して、呼び出し元が求める読みやすさの基準を満たすまで調整します。エディターの基本フォントサイズが 14 px の場合、18 pt は 24 CSS ピクセルです。そのため、およそ 1.75 倍は開始点にすぎず、保証にはなりません。スライドのプレースホルダーに合わせて縮小すると、デフォルトのフォントサイズは判読できない大きさ(約 7pt)になります。
ステップ 6:ファイルを開いてキャプチャする
Command Palette の手順を使い、mcp_microsoft_pla_browser_run_code でファイルを開きます。Go to File コマンドで Quick Open を開き、ファイル名を入力して Enter キーを押します。
async (page) => {
await page.keyboard.press('F1');
await page.waitForTimeout(400);
await page.keyboard.type('Go to File');
await page.waitForTimeout(300);
await page.keyboard.press('Enter');
await page.waitForTimeout(500);
await page.keyboard.type('doc-ops-update.prompt.md');
await page.waitForTimeout(500);
await page.keyboard.press('Enter');
await page.waitForTimeout(1000);
return 'File opened';
}
表示を設定します。このスクリーンショットに必要なパネル(分割ビュー、Copilot Chat、Explorer)のみを、mcp_microsoft_pla_browser_snapshot で参照を確認してから mcp_microsoft_pla_browser_click でクリックする方法で選択的に開きます。対象に焦点を合わせた表示にします。
スクリーンショットを撮ります。mcp_microsoft_pla_browser_take_screenshot に type: "png" と説明的な filename を指定します。
スクリーンショットが目標の配置に適合しているか確認します。キャプチャした画像のアスペクト比を目標のプレースホルダーの比率と比較します。差が 5% を超える場合は、ビューポートの寸法を修正して撮り直します。描画されたテキストサイズが測定上、呼び出し元の読みやすさの基準を下回る場合は、ズームを上げて撮り直します。スクリーンショットが歪まずに配置寸法に合うまで、ビューポートとズームを調整しながら繰り返します。
追加のスクリーンショットも同様に撮影します。次のファイルを開く前に、現在のファイルのタブを閉じます(Command Palette -> View: Close All Editors)。
ステップ 7:Copilot Chat のスクリーンショット
Copilot Chat のスクリーンショットでは、アクティビティバーはデフォルトで表示され、設定のシード処理では変更できないため、クリーンアップ中もそのままにしておきます。mcp_microsoft_pla_browser_snapshot -> mcp_microsoft_pla_browser_click を使ってアクティビティバーをクリックし、チャットパネルを開きます。mcp_microsoft_pla_browser_run_code で page.keyboard.type() を使ってプロンプトを入力し、mcp_microsoft_pla_browser_wait_for で応答を待ってからキャプチャします。
ステップ 8:クリーンアップ
VS Code の Web サーバーを停止し、一時環境をクリーンアップします:
pkill -f "serve-web.*8765" 2>/dev/null || true
rm -rf "$VSCODE_SERVE_DIR"
また、Playwright ブラウザーも閉じます:mcp_microsoft_pla_browser_close。
Playwright MCP のコマンドパレットパターン
個々の MCP ツール呼び出しは非同期で実行されるため、別々の press_key、type、press_key 呼び出しの間にコマンドパレットが閉じます。コマンドパレットに関する操作では、すべて mcp_microsoft_pla_browser_run_code を使い、1 回の Playwright 実行内で操作を連続してアトミックに実行する必要があります:
async (page) => {
const runCommand = async (command) => {
await page.keyboard.press('F1');
await page.waitForTimeout(400);
await page.keyboard.type(command);
await page.waitForTimeout(300);
await page.keyboard.press('Enter');
await page.waitForTimeout(500);
};
await runCommand('View: Close All Editors');
await runCommand('View: Close Primary Side Bar');
// Chain additional commands as needed
return 'Commands executed';
}
コマンドパレットの操作に、個別の mcp_microsoft_pla_browser_press_key -> mcp_microsoft_pla_browser_type -> mcp_microsoft_pla_browser_press_key 呼び出しを決して使わないでください。呼び出しの間にパレットのフォーカスが失われます。
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
Ignoring option 'server-data-dir': Value must not be empty | シェル変数がバックグラウンドターミナルで空に展開された | 一時ディレクトリのパスを直接指定してコマンド全体を入力するか、同じセッションで mktemp と serve-web を実行します |
| カラーテーマを選ぶとマーケットプレイスのテーマに移動する | まだテーマが選択されておらず、設定のシード処理も適用されていない | ワークベンチの読み込み後、コマンドパレットで Preferences: Color Theme を実行します |
| パネルの切り替えで非表示のパネルが開く | View: Toggle Panel Visibility は切り替えコマンドです | スナップショットでパネルが表示されていることを確認してから、View: Close Panel を使用します |
?file= パラメーターでファイルが自動的に開かない | VS Code Web がサポートしているのは ?folder= のみです | 移動後、コマンドパレットの Go to File コマンドでファイルを開きます |
| スクリーンショットの文字が小さすぎる | デフォルトの約14pxのフォントは、縮小すると約7ptになります | 読みやすさの下限を超えるまで document.body.style.zoom を大きくし、再測定します |
| スクリーンショットのアスペクト比が歪む | ビューポートの比率がプレースホルダーの比率と一致していない | プレースホルダーからビューポートを計算します:width_px = 1200、height_px = int(1200 / (target_w / target_h)) |
| スライドに埋め込むサイズで UI が煩雑になる | エクスプローラー、ミニマップ、タブ、トーストが表示されている | キャプチャの前に、不要な UI 要素をすべて閉じます |
workbench.action.zoomIn が動作しない | Electron 専用のコマンド | editor.action.fontZoomIn または page.evaluate() による CSS ズームを使用します |
| ブラウザーの状態が復元される | IndexedDB/localStorage によって以前のファイルが復元される | 読み込み後にコマンドパレットからエディターを閉じます。可能な場合は、新しいブラウザーコンテキストまたはシークレットモードを使用します |
Meta+P でブラウザーのアクションが実行される | キーボードショートカットがブラウザーに横取りされている | page.keyboard.press('F1') を使用してコマンドパレットを開きます |
| スクリーンショットが誤ったディレクトリに保存される | take_screenshot は Playwright の作業ディレクトリを基準に保存するためです | キャプチャ後に、スクリーンショットを目的のディレクトリにコピーします |
| Copilot Chat の応答が一定しない | トークン単位で出力がストリーミングされる | 期待するテキストを指定するか、時間待ちを設定して mcp_microsoft_pla_browser_wait_for を使用します |