mcpField
V
vscode-playwright

vscode-playwright

github.com/microsoft创意与媒体1.6k71 次安装今天更新
代码仓库

关于 vscode-playwright

用于捕获 VS Code 编辑器截图,并将独立的浏览器动画录制为无声 WebM 视频。提供适用于 CI 的可重复脚本流程,也支持通过 Playwright MCP 进行交互式的单次捕获。

主要功能

  1. 01脚本化捕获 VS Code 截图
  2. 02通过 Playwright MCP 交互捕获
  3. 03验证截图并测量字体
  4. 04将浏览器动画录制为 WebM
  5. 05配置视口并整理编辑器界面

适用场景

  1. 01制作演示文稿或文档用的 VS Code 截图
  2. 02在 CI 中运行可重复的截图捕获
  3. 03将 HTML 动画录制为无声 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.toml
uv.lock
scripts/
capture_vscode.py
record_browser_video.py
tests/
fuzz_harness.py
test_capture_vscode.py
test_record_browser_video.py
tests/corpus/
not-a-mapping.yml
traversal-plan.yml
valid-plan.yml

详细介绍

VS Code 和浏览器录制技能

捕获 VS Code 编辑器视图、代码讲解和 Copilot Chat 示例,并将独立的浏览器动画场景录制为无声 WebM 片段。

概述

此技能提供完整的工作流,用于捕获高质量的 VS Code 截图,适合嵌入幻灯片、文档和其他视觉媒体。它可处理服务生命周期管理、视口配置、界面清理和截图验证。

两种方式遵循相同的限制。对于任何可重复或无人值守的捕获(包括 CI),优先使用脚本方式。对于探索性或一次性捕获,请使用交互式 Playwright MCP 方式。

脚本捕获

scripts/capture_vscode.py 以无头模式运行 YAML 捕获计划:启动 serve-web、应用捕获设置、在 Monaco 中打开每个文件、测量渲染字体,并为每次捕获写入一张截图。它直接驱动 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 退出;并在最后一行标准输出中打印一条 JSON 结果,其中包含每次捕获的测量值 rendered_font_size_pt、zoom 和 source_resolution。捕获失败时也会写入 debug-<id>.png。脚本会在计划验证时拒绝 Markdown 目标;如果深色主题未生效,也会运行失败,因此与之冲突的浅色捕获无法通过验证。在 CI 中通过管道传输其输出时,请在 shell: bash 下运行该步骤,以便 pipefail 保留退出代码。

浏览器动画录制

scripts/record_browser_video.py 会从就绪场景帧中录制一个独立的 HTML 动画,并生成无声 WebM 片段。场景必须在本地资源和动画状态就绪后,将 data-animation-ready="true" 设为其 body 上的属性,并定义 window.startAnimation(),以重置叙事动画和计时器。录制从这一握手信号开始,而不是从页面导航开始。 浏览器上下文处于离线状态,Service Worker 会被拦截,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_*。请使用宿主提供的前缀。

已验证的约束

以下三项约束已通过运行中的 serve-web 实例确认。每一项都否定了一种看似合理但实际行不通的做法。

  • 用户设置保存在浏览器的 IndexedDB 中,而不是磁盘上。将设置写入 --server-data-dir/data/User/settings.json 对 VS Code Web 没有影响。通过触发粘贴事件,在 Preferences: Open User Settings (JSON) 中写入设置,因为粘贴可以避开 EditContext 按键处理和括号自动补全,然后保存并重新加载页面。重新加载会关闭设置编辑器;Insiders 会将其作为模态窗口打开并占据焦点。重新加载还会应用工作区信任等窗口级设置。持久化的浏览器上下文会在重新加载后保留这些设置。
  • Markdown 文件会作为跨源预览 Webview 打开,而不是 Monaco 编辑器。页面无法访问 Webview 的 DOM,因此无法检查或测量其中渲染的文本。如果截图需要可测量的编辑器文本,请截取代码文件或配置文件。
  • 应通过尝试导航来确认浏览器工具,而不是匹配工具名称,因为 MCP 工具前缀会因服务器注册方式而异。VS Code 内置的浏览器工具就是一个已知案例:它能加载页面,却无法向 VS Code Web 工作台发送键盘或鼠标事件,因此使用这些工具会在第一步命令面板操作时失败。

架构

serve-web CLI 是一个基于 Rust 的代理(“服务器的服务器”),用于下载 VS Code Server 发行版,并将连接代理到内部 Node.js 服务。外层 CLI 接受的标志有限;--server-data-dir 是关键标志,用于控制服务器端数据的存储位置,例如下载的服务器构建版本、扩展和计算机状态。它不控制用户设置;用户设置由浏览器保存在 IndexedDB 中。

快速开始

  1. 检测 VS Code CLI 变体并启动 Web 服务。
  2. 使用 Playwright 导航到 VS Code Web 实例。
  3. 清理界面(关闭面板、标签页和通知)。
  4. 打开文件并截取屏幕截图。
  5. 停止服务并进行清理。

工作流步骤

步骤 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 标志必须接收字面路径,因为其他终端会话中的 shell 变量在后台终端中不可用:

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 中,因此预置设置文件不会产生任何变化。工作台加载后,通过命令面板命令设置主题、关闭恢复的编辑器并隐藏界面元素(步骤 5);使用 document.body.style.zoom 增大渲染文本的尺寸。

也不要尝试通过 textarea 选择器输入来编辑设置 JSON 编辑器。VS Code Insiders 使用 EditContext API 而非 textarea,因此不存在该元素。

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 步:导航并等待
  1. 导航到工作区:使用 mcp_microsoft_pla_browser_navigate 前往 http://localhost:8765/?folder=/path/to/workspace。
  2. 等待 VS Code 加载:使用 mcp_microsoft_pla_browser_wait_for,设置 time: 5,让编辑器界面完全呈现。
第 4 步:调整视口大小

调整视口大小,使其符合目标放置区域的宽高比:使用 mcp_microsoft_pla_browser_resize,将分辨率设为与要插入截图的 PPTX 占位符宽高比一致。

使用 width_px = 1200 和 height_px = int(1200 / (target_width_inches / target_height_inches)) 计算尺寸。例如,5.5" x 4.2" 的占位符对应 1200 x 916 的视口。

如果截图要填满 16:9 的幻灯片,请将视口设为 1920x1080,而不要根据 1200 px 宽度规则计算。其他所有情况均使用宽度规则,不要在这些情况下使用 1920x1080。请在清理界面前调整视口大小,以便界面元素按目标分辨率呈现。

第 5 步:清理界面

使用 mcp_microsoft_pla_browser_run_code 和命令面板操作模式,为清晰截图做好编辑器准备:

  1. 如果存在工作区信任对话框,请将其关闭:使用 mcp_microsoft_pla_browser_snapshot 检查是否有信任对话框;如果可见,则通过 mcp_microsoft_pla_browser_click 点击 “Yes, I trust the authors”。
  2. 关闭所有编辑器和标签页:命令面板 -> View: Close All Editors。
  3. 清除通知:命令面板 -> Notifications: Clear All Notifications。
  4. 启用“请勿打扰”模式:命令面板 -> Notifications: Toggle Do Not Disturb Mode。
  5. 关闭主侧边栏:命令面板 -> View: Close Primary Side Bar。
  6. 关闭底部面板:先使用 mcp_microsoft_pla_browser_snapshot。如果面板(Terminal、Problems、Output)可见,则运行命令面板 -> View: Close Panel。不要盲目运行此命令——它会切换显示状态,并打开隐藏的面板。
  7. 关闭辅助侧边栏:先使用 mcp_microsoft_pla_browser_snapshot。如果辅助侧边栏(Chat)可见,则运行命令面板 -> View: Close Secondary Side Bar。
  8. 放大以提高可读性:使用 mcp_microsoft_pla_browser_run_code,执行 await page.evaluate(() => { document.body.style.zoom = '1.75'; }),以放大整个 UI。不要认为任何单一缩放比例都足够:请提高缩放比例并重新测量渲染后的文字大小,直到达到调用方要求的可读性下限。若编辑器的基础字体大小为 14 px,则 18 pt 相当于 24 CSS 像素,因此约 1.75 倍只是起始值,并非保证值,因为基础字体大小会有所不同。截图缩小以适应幻灯片占位符时,默认字体大小会变得无法辨认(约 7 pt)。
第 6 步:打开文件并截图

使用 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%,请调整视口尺寸后重新截图。如果测得的渲染文字大小低于调用方要求的可读性下限,请提高缩放比例后重新截图。反复调整视口和缩放比例,直到截图符合放置尺寸且不失真。

其他截图也重复上述操作。打开下一个文件前,请关闭当前文件的标签页(命令面板 -> View: Close All Editors)。

第 7 步:Copilot Chat 截图

对于 Copilot Chat 截图:Activity Bar 默认可见,设置初始化无法更改这一点,因此清理时请保留它。通过点击 Activity Bar 打开 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,在单次 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后台终端中的 Shell 变量解析为空将完整命令内联,并使用临时目录的字面路径;或者在同一会话中运行 mktemp 和 serve-web
颜色主题跳转到 Marketplace 主题尚未选择主题,且设置填充未生效工作台加载后,运行命令面板 -> 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 回复不确定输出按 token 逐个流式传输使用 mcp_microsoft_pla_browser_wait_for 等待预期文本,或设置时间延迟

评论

支持 Markdown