Communitygithub.com

hadimoti/joy-media-windows-mcp

使用 Windows-MCP 工具操控 JOY Media(JOY Studio)Electron 桌面应用(Windows 平台)。可启动独立的测试副本、创建项目、导入媒体、点击“导出 MP4”、保存 Windows 保存对话框,然后根据应用自身的数据库检查结果(ffprobe、完整解码、色块、时间)。适用于需要在 JOY Media 桌面应用中测试、运行、计时或验证导出,或比较不同构建版本时使用。

joy-media-windows-mcp 是什么?

此技能为 AI 代理提供了一套在 Windows 上通过 Windows-MCP 工具安全、程序化地驱动 JOY Media(JOY Studio)Electron 桌面应用的方法。它专门设计用于在不触碰用户真实安装或数据的前提下,对应用进行测试和验证。技能的核心是创建一个独立的、解包的应用副本,并使用隔离的用户数据目录,确保测试环境的纯净性和可复现性。它利用 PowerShell 脚本启动应用,通过 Windows-MCP 的 Snapshot、Click、Type 等动作模拟用户操作,从项目创建、媒体导入到执行“导出 MP4”并处理 Windows 保存对话框。导出完成后,技能会通过 ffprobe 检查视频流的编码参数、颜色标签,使用 ffmpeg 进行完整解码验证,并通过定制的 Python 脚本(如 fxcheck.py、fxplace.py)分析色彩准确度。此外,它还能从应用的 SQLite 数据库中提取各阶段的耗时数据(如浏览器阶段时间、工作线程时间),为性能对比提供量化依据。该技能特别强调执行前的“边界条件确认”(如询问用户许可)和运行后的环境清理与证据保全(如注册表键值校验、文件夹差异对比),确保整个测试过程安全、可审计。它主要面向需要自动化测试 JOY Media 导出功能、比较不同构建版本性能的开发者和 QA 工程师。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/hadimoti/joy-media-skill/tree/HEAD/skills/joy-media-windows-mcp

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

使用 Windows-MCP 操控 JOY Media

此技能基于 JOY Media 1.1.0 版本(Electron 44.3.0,Windows 11)开发。它指导 AI 代理如何在不影响用户真实安装或数据的情况下运行桌面应用,通过 Windows-MCP 工具在编辑器中执行操作,并依据事实(而非外观)来评估导出结果。

使用的工具:Snapshot、Screenshot、Click、Type、App、Wait(Windows-MCP),以及用于启动、文件检查和 ffmpeg/ffprobe 的 PowerShell。

0. 基本原则(不可跳过)

  • 每次运行前先询问用户。 启动应用、导入和导出操作需要用户在场并明确同意。一次只运行一个任务。绝不能针对用户的真实配置文件进行操作。
  • 绝不要触碰已安装的应用(其文件夹、安装脚本、卸载程序)。应运行一个独立的解包副本(见第 1 节)。
  • 数据隔离:始终传递一个新的 --user-data-dir 参数。若要复用已有项目,请先关闭应用,然后使用 robocopy /E 将旧的配置文件复制到新文件夹(不要使用 /MIR,不要清除),并在复制的副本上启动应用。
  • joy:// 注册表项(HKCU\Software\Classes\joy)必须保持不变。在启动前、启动后和关闭后,分别使用 reg export 将其导出为新文件,并比较其 SHA-256 值。如果值不同,请停止操作并告知用户;只有用户同意后才能恢复。
  • 测试期间不要删除任何内容(副本、配置文件、导出的文件都是证据)。Chromium 可能会在新的测试配置文件中清理其自身的临时文件,这是正常的。
  • 一旦发现崩溃迹象(GPU 进程退出、应用程序错误事件、驱动重置)立即停止:保留所有内容,不要在其之上重新运行,并告知用户。
  • 切勿在应用中输入密码或在备注中包含令牌。

1. 获取可安全运行的应用副本

将你想要测试的提交构建或解包到一个短路径(长度不超过 260 个字符)下,例如 C:\jg\app-<sha>:

  1. 使用 git archive <sha> 打包为 tar 文件,解压到 C:\jg\<名称>。
  2. 运行 pnpm install --offline --frozen-lockfile(需要预先存在的 pnpm store)。
  3. 从现有副本的 node_modules\.pnpm\electron@<ver>\node_modules\electron 复制 Electron 的 dist 文件夹和 path.txt(离线安装不会下载 Electron)。检查 electron.exe 的 SHA-256 值。
  4. 运行 pnpm build,然后运行 pnpm --filter @joy-media/desktop package:unpacked。
  5. 使用 robocopy apps\desktop\dist\joy-media-unpacked C:\jg\app-<sha> /E。

解包后的副本在 isPackaged = false 状态下运行,因此它不会注册 joy:// 协议。但仍需检查该注册表项。

2. 启动应用(PowerShell)

$env:NODE_ENV = 'production'
$app = 'C:\jg\app-<sha>'
Start-Process -FilePath '<path to>\electron.exe' `
  -ArgumentList @($app, '--user-data-dir=C:\jgp\<new-profile>', '--enable-logging=stderr') `
  -WorkingDirectory $app `
  -RedirectStandardOutput 'C:\jgp\run\stdout.log' -RedirectStandardError 'C:\jgp\run\stderr.log' -PassThru

--enable-logging=stderr 会将渲染进程的 console.* 输出写入 stderr 文件(对临时诊断很有用)。检查没有进程的命令行包含 --joy-media-gpu-encode-fallback(那将是后备重启,而不是正常启动)。窗口标题是 JOY Studio。在新配置文件中,应用会打开“项目”页面;在复制的配置文件中,它会恢复上一次的项目。

3. 使用 Windows-MCP 操控窗口

缩放:截图大约是真实屏幕的 2.56 倍小。务必使用来自 Snapshot 的真实坐标进行点击,切勿使用截图中的像素坐标。每次页面变更后,拍摄一张小的 Screenshot(scale 为 0.4)。

顺序:一次只执行一个窗口操作。曾经有一次,在导出后立即发送了一批操作,导致点击和输入落在了错误的项目中。App switch "JOY Studio" 有时会失败并提示“无效的窗口句柄”;如果窗口已经处于前端,则继续执行。

以下坐标来自一个 4920x2160 的屏幕,且 JOY 窗口为默认大小和位置。它们只是一个起始映射,并非绝对准确:当任何内容看起来不同时,请使用 Snapshot 并参考其元素列表。

操作位置(真实坐标)
文件菜单(910, 288)
文件 > 项目库(1077, 358)
新建项目按钮(3023, 311),然后点击名称字段 (1165, 727),使用 Type 输入名称并附加 press_enter
第一个项目卡片(1680, 873)
时间线“导入媒体”(空时间线)(2199, 1312)
打开文件对话框:名称框 / 打开(1587, 1208) / (2268, 1264)
导出 MP4(2672, 288)
选择片段,检查缩放点击片段条 (1762, 1349);检查器中会显示缩放 X/Y
关闭应用窗口(3143, 288)
保存对话框:名称框 / 保存约 (1717, 1058) / (2283, 1266)

一个典型用例的流程:项目库 > 新建项目 > 输入名称 > 导入媒体 > 输入完整的文件路径 > 打开(片段会放入时间线) > 检查预览 > 导出 MP4 > 等待 > 保存对话框 > 验证。

保存对话框。 导出操作最终会显示一个标准的 Windows 保存对话框(默认文件夹为“下载”,建议一个不带扩展名的文件名)。只有用户点击保存后,文件才会出现在桌面上,因此从“工作线程完成”到“文件出现在桌面”之间的延迟正是这个对话框等待操作的时间。在工作线程应完成时截图;要么由用户点击保存,要么(在用户同意后)将完整的目标路径 ...\Desktop\<建议的文件名>.mp4 输入到名称框中并点击保存。应用数据库中的作业计时不受等待时间的影响。

4. 运行前、运行中和运行后

运行前:使用 reg export 导出 joy:// 注册表项并计算哈希值;列出用户的真实配置文件夹和任何证据文件夹(scripts/list-tree.ps1),以便证明在运行期间没有发生任何更改。

运行中(长时间导出):在后台启动 scripts/sampler.ps1 -Pattern '*<profile>*' -Out <csv> -Stop <stopfile>。它会每秒记录一次每个 Electron 进程的工作集、私有字节、CPU 时间、NVENC 会话和 GPU 使用率。创建停止文件以结束记录。

运行后:关闭应用(点击关闭窗口按钮),确认没有残留的 electron 进程,再次导出注册表项并对比哈希值,再次列出文件夹并进行差异对比,检查配置文件中是否有 .upload 残留文件,并检查应用程序错误/WER 以及 Display/nvlddmkm 事件(忽略无关信息,如 Docker 相关事件)。

5. 根据事实评估导出结果

  • ffprobe -show_streams:编码格式、尺寸、帧数、时长、颜色标签(color_space、color_primaries、color_transfer、color_range)。
  • 完整解码必须干净:ffmpeg -v error -i out.mp4 -f null - 且退出码为 0。
  • 计算文件哈希值(Get-FileHash);当代码路径相同时,不同构建版本的相同布局应产生相同的哈希值。
  • 从应用自身数据库获取的阶段时间(joy-media.sqlite3 的副本及其 -wal/-shm 文件,以只读方式打开):运行 scripts/export-times.py <copy>,会为每次导出打印浏览器阶段(从点击时间戳到原始素材暂存)、暂存字节数和工作线程时间。点击时间戳是文件名中的 13 位数字。
  • 色彩准确性:使用 scripts/fxgen.py <folder> 构建测试素材(包含已知 sRGB 值的纯色块以及二进制帧计数器;素材类型包括 BT.709、BT.601、未标记 SD、全范围、旋转、VFR、10-bit、HEVC、VP9、AV1、隔行扫描、一个过渡对和音频率对),然后使用 scripts/fxcheck.py <folder> 进行检查,最终使用 JOY_FX_DIR=<folder> python -I scripts/fxplace.py <export.mp4> <fixture-file-name> [frame] 对导出结果进行评分。该脚本会找到素材在画布上的位置(尺寸小于画布的素材会在左上角以 1:1 比例放置,不缩放),并打印在四种矩阵/范围读取方式下的最大/平均偏差;正确的读取结果应在约 3 个级别范围内。
  • 音频:通过 astats 的过零率检测音调,通过 RMS 检测电平;单声道源会变为立体声(每个声道降低约 3 dB)。

6. 值得注意的已知行为(JOY Media 1.1.0 版本)

  • 每次色彩测试都应在全新的应用会话中运行。 在测试的机器上(RTX 5070 Ti,Electron 44.3.0),启动后的第一次导出以 BT.709 编码(标签 bt709);后续的导出在同一会话中会以 BT.601 编码(标签 smpte170m),文件变得更大,在长布局上速度更慢,且字节不同。诊断版本显示,第一次的捕获画布帧是 RGBA(GPU 支持),之后的则是 BGRA(CPU 支持);应用本身未设置任何色彩空间。在应用内部转换为 NV12 BT.709 可使每次导出结果一致。
  • 未标记的 SD 视频会被当作 BT.709 读取(颜色偏移最多可达约 20 个级别)。
  • 没有音轨的源文件会导出一个静音的立体声 AAC 轨道。
  • 只有在对等条件下才能比较构建版本:相同的布局、在会话中的相同位置(第一次导出与第一次导出)、窗口在前端并处于焦点(未聚焦的窗口可能慢约 30%)、使用同一配置文件的副本。
  • 同一桌面上的其他代理或聊天窗口可能会窃取焦点:点击前先截图。
  • 窗口上的第一次点击可能只会使其获得焦点。

7. 报告格式如下

说明运行的内容(构建版本、配置文件副本、布局),列出数据(阶段时间、峰值内存、文件大小、标签),通过哪些检查(joy:// 注册表项未改变、文件夹差异为空、解码干净),未验证的内容,以及需要用户做出的一个决定。当你只有一次运行时,请说“每个构建版本只运行一次”。

相关技能