跳到正文
cccskills
免费在 GitHub 公开中文介绍

proof-video

为功能验证或PR录屏添加字幕、局部放大和播放速度调整,制作带有操作说明的MP4,同时保留原始视频作为证据。

原文查看原文说明

Capture and annotate PR screenshots and videos with measured arrows, outlines, alignment guides, spacing brackets, captions, zoom, and speed cues.

集成工具Playwright
AI 评分90分/ 100查看安装方法

适用场景

  • 为PR录屏添加操作说明字幕
  • 放大界面中的操作位置
  • 缩短功能验证视频中的等待片段
  • 为现有录屏添加字幕

中文介绍

功能

为功能验证或PR(变更提案)的录屏添加字幕、局部放大和播放速度调整,制作带有说明的MP4。可以通过Control UI录制辅助工具记录操作及说明的时间点,也可以为现有的.mov或.webm搭配cues.json进行加工。字幕直接嵌入画面,不生成语音旁白。

适用场景

适合向审阅者展示修改后界面的操作方式,或放大小按钮以便查看。可以快进启动和等待片段,让需要重点检查的操作保持正常播放速度。

使用示例

  • “为PR录屏添加简短字幕,说明各项操作。”
  • “放大筛选控件的操作部分,并快进等待片段。”
  • “为现有录屏添加字幕和局部放大,导出MP4。”

注意事项

使用仓库内的录制辅助工具和渲染脚本,以及系统安装的ffmpeg和ffprobe。生成字幕图片需要Playwright Chromium。可变帧率视频会转换工作副本。保留原始视频,发布前检查是否包含私人内容,以及字幕时间是否错位。不要提交视频或.artifacts/。

本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。

客观评估

AI 仅根据 SKILL.md 的内容,从 4 个方面进行了评估。星标数和热度不计入评估。

指令清晰度能否看出何时使用、做什么
A良好明确说明为Control UI录屏添加字幕、输出MP4并保留原始视频。
步骤具体性步骤、输入输出和示例是否具体
A良好提供录制脚本示例、字幕与缩放及速度设置方法,以及渲染命令。
安全性发送数据、删除文件、执行命令等是否有说明
A良好拒绝覆盖已有输出,要求保留原始视频并在发布前检查私人内容。
安装难易度所需工具和 API 密钥是否少且有说明
B部分不足提供ffmpeg安装方法,但未提供tsx或Playwright的安装步骤。

总分按每项 A=25 分、B=15 分、C=5 分相加。 由 AI(OpenAI Codex)于 2026年10月19日 评估。仅供参考,安装前请同时查看原文。

如果您认为评估有误,请申请复核

请写明哪一项有误以及原因。无需登录。我们会对照 SKILL.md 重新评估,并在此处更新结果。

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

包含的文件(2)

  • SKILL.md10.5 KB
  • references/annotations.md5.1 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Proof video

Use this developer skill for captioned Control UI recordings and native captures. Captions are burned into an MP4; they are visual narration, not synthesized audio. Keep the raw video as evidence, attach the polished MP4, and never commit media or .artifacts/ output. Inspect the entire capture for unrelated or private content before publishing under the PR's existing authorization.

Point out the claim

Choose marks that demonstrate the change. Use arrows to locate a control, outlines to identify a region, alignment guides to compare edges or centers, and spacing brackets to measure gaps. Measurements come from locator.boundingBox() after the asserted layout settles; the renderer calculates the labels. Keep the reference element first and use the same viewport, crop, scale, and edge before and after. Keep marks sparse and labels in empty space. Preserve the raw capture.

For screenshot markup or timed video marks, read annotations. Both paths use the same SVG geometry renderer. Annotations are composited before zoom, while narration stays fixed in the viewport. Re-measure and replace marks after scrolling or layout changes; a cue describes a stationary capture, not a live element tracker. Clear marks during movement when they would become stale.

Standalone recording

From the repository root, save this script as .artifacts/proof-video/record.mts (create the parent directory first), then run node --import tsx .artifacts/proof-video/record.mts. It starts an isolated mocked Control UI, records five captions, a real toolbar zoom, fast-forwarded startup, and an eight-second pause at 4× speed. Every invocation allocates a fresh evidence directory.

import { chromium } from "playwright";
import { createControlUiE2eArtifactDir } from "../../ui/src/test-helpers/control-ui-e2e-artifacts.ts";
import {
  installMockGateway,
  resolvePlaywrightChromiumExecutablePath,
  startControlUiE2eServer,
} from "../../ui/src/test-helpers/control-ui-e2e.ts";
import { startProofRecording } from "../../ui/src/test-helpers/proof-video.ts";

const dir = createControlUiE2eArtifactDir("captioned-toolbar", ".artifacts/proof-video");
const server = await startControlUiE2eServer(undefined, { source: true });
const browser = await chromium.launch({
  executablePath: resolvePlaywrightChromiumExecutablePath(chromium.executablePath()),
  args: ["--force-device-scale-factor=2"],
});
try {
  const recording = await startProofRecording(browser, {
    dir,
    contextOptions: { colorScheme: "dark", locale: "en-US", reducedMotion: "reduce" },
  });
  const { page } = recording;
  const sessions = ["Main", "Weekly planning", "Reading list"].map((label, index) => ({
    key: index === 0 ? "agent:main:main" : `agent:main:proof-${index}`,
    label,
    displayName: label,
    kind: "direct",
    status: "done",
    hasActiveRun: false,
    updatedAt: Date.parse("2026-09-01T12:00:00Z") - index * 60000,
    contextTokens: 200000,
    totalTokens: 0,
    model: "gpt-5.6-luna",
    modelProvider: "openai",
  }));
  const gateway = await installMockGateway(page, {
    sessionKey: "agent:main:main",
    sessionArchiveFiltering: true,
    methodResponses: {
      "sessions.list": {
        sessions,
        count: sessions.length,
        totalCount: sessions.length,
        hasMore: false,
        offset: 0,
        limitApplied: 50,
        nextOffset: null,
        path: "",
        ts: sessions[0].updatedAt,
        defaults: { contextTokens: 200000, model: "gpt-5.6-luna", modelProvider: "openai" },
      },
    },
  });
  recording.caption("Open the mocked Control UI.");
  recording.speed(8);
  await page.goto(`${server.baseUrl}chat`);
  await gateway.waitForRequest("sessions.list");
  await page.getByRole("link", { name: "Weekly planning", exact: true }).waitFor();
  const toolbar = page.locator(".sidebar-session-toolbar");
  await toolbar.getByText("Sessions", { exact: true }).waitFor();
  recording.speed(1);
  await page.waitForTimeout(1500);
  recording.caption("Find your conversations in the session list.");
  await page.waitForTimeout(3000);
  await recording.zoom(toolbar);
  recording.caption("Zoom in on the session filter controls.");
  await toolbar.getByRole("button", { name: "Filter & sort" }).click();
  await page.locator(".sidebar-session-sort-menu").waitFor({ state: "visible" });
  await page.waitForTimeout(4000);
  recording.zoomOut();
  recording.caption("Fast-forward an eight-second pause.");
  recording.speed(4);
  await page.waitForTimeout(8000);
  recording.speed(1);
  recording.caption("Return to the full session list.");
  await page.getByRole("menuitemradio", { name: "All", exact: true }).click();
  await page.waitForFunction(() =>
    document
      .querySelector(".sidebar-session-sort")
      ?.classList.contains("sidebar-session-sort--filtered"),
  );
  await page.waitForTimeout(3000);
  console.log(JSON.stringify(await recording.finish(), null, 2));
} finally {
  await browser.close();
  await server.close();
}

Use caption(text) to replace the current caption, clearCaption() to end it, zoom(locatorOrRect, { factor: 2, padding: 24, ease: 0.5 }) to start or replace a zoom, and zoomOut() to end it. Rectangles use viewport CSS pixels. Padding expands and clamps the target rectangle; its center determines the zoom focus. speed(factor) changes playback speed until the next call; speed(1) restores normal playback. finish() closes open cues at the finalized video's end, closes the recording context, rasterizes captions, writes cues.json, and returns { dir, videoPath, cuesPath }. The caller closes the browser and server.

The helper is test tooling at ui/src/test-helpers/proof-video.ts; production code must not import it. contextOptions carries ordinary Playwright context options, while the helper owns the viewport, recording size, and device scale. Keep narration to one or two short lines; oversized text fails instead of silently clipping. Caption PNGs are transparent viewport-width, 120-pixel-high strips with a centered dark rounded card and 30-pixel system text.

Render

Use the exact directory printed by the recording:

node --import tsx scripts/render-proof-video.mts --cues .artifacts/proof-video/<capture>/cues.json

The renderer prints the output path and duration. Optional --input <video> overrides the raw input and --out <file.mp4> chooses the output. Existing output files are refused, preserving raw evidence and earlier renders. It uses trusted system ffmpeg and ffprobe, never Playwright's bundled encoder. Install a full system build with brew install ffmpeg or apt install ffmpeg.

Speed segments split the raw timeline with trim/setpts/concat, then normalize it to the input frame rate. Caption windows and zoom transitions are remapped to output time. Zoom uses zoompan with d=1 and matching input FPS; a 100-frame, 4-second, 25-FPS synthetic capture retained exactly 100 frames and 4 seconds, with a visibly and numerically different zoom hold. Dynamic crop width/height expressions do not animate: ffmpeg evaluates them only at initialization. Output is viewport-sized H.264 MP4, yuv420p, CRF 23, with faststart and no audio.

Cue sidecar v1 and native captures

Save a hand-written cues.json beside an untouched native .mov or .webm. Use scale for actual raw pixels per viewport CSS pixel, not display metadata. Input dimensions must equal viewport × scale and frame rate must be constant. All times below are seconds in the RAW video. Caption image paths are relative to the sidecar directory. Zoom cues cannot overlap other zoom cues; speed cues cannot overlap other speed cues. Adjacent cues are allowed.

{
  "version": 1,
  "video": "capture.mov",
  "viewport": { "width": 1280, "height": 800 },
  "scale": 2,
  "captionHeight": 120,
  "cues": [
    {
      "kind": "caption",
      "start": 1,
      "end": 4,
      "text": "Inspect the session controls.",
      "image": "captions/0.png"
    },
    {
      "kind": "zoom",
      "start": 1,
      "end": 4,
      "rect": { "x": 20, "y": 150, "width": 280, "height": 80 },
      "factor": 2,
      "ease": 0.5
    },
    { "kind": "speed", "start": 5, "end": 9, "factor": 4 }
  ]
}
node --import tsx scripts/render-proof-video.mts --cues <dir>/cues.json --rasterize

--rasterize creates missing caption and annotation PNGs with fresh Playwright Chromium pages. The exported rasterizeProofOverlays(browser, cues, dir) also supports programmatic native-capture workflows. Neither path needs libass or drawtext: Chromium rasterizes text and geometry. ffmpeg overlays annotations before zoom and captions after zoom.

Verified capture mode and limitations

On macOS with Playwright 1.62.1 and Chromium 151.0.7922.34, context deviceScaleFactor: 2 produced a 2560×1600 WebM containing only 1280×800 page content plus gray padding. Launching with --force-device-scale-factor=2 and leaving context emulation at 1 recorded true 2× content: a 100-CSS-pixel marker measured 200×200 at raw coordinates (2360, 1400). The helper defaults to deviceScaleFactor: 2 for recording size and sidecar scale; the launch flag in the template is required. This parameter does not enable context emulation. For verified 1× capture, launch without the flag and pass deviceScaleFactor: 1. The renderer uses Lanczos pre-upscaling for 1× sources, but cannot restore lost detail: a 2× zoom on those recordings is softer.

The cue clock starts at context creation using performance.now(). Playwright's video clock can differ by roughly 100 ms, and startup/load can increase the skew; inspect action/caption alignment in the finalized recording. Avoid clipped, locator, or full-page screenshots during recording: Chromium can corrupt the screencast surface. Caption rasterization happens only after recording closes, in a fresh context. See the Control UI E2E skill's screenshot guidance.

GitHub's player ignores subtitle tracks, so captions must be burned in. The renderer requires crop, scale, overlay, setpts, trim, concat, fps, and zoompan in the system ffmpeg build. It does not use subtitles= or drawtext=. Variable frame-rate native captures need conversion to a separate constant-frame-rate working copy first; retain the original. Frame-rate quantization can shift speed-segment boundaries by about one output frame. Check output duration and extract caption, zoom-hold, and sped-segment frames before attaching the MP4.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

1password

免费

Set up and authenticate the 1Password CLI, then supply stored passwords and API keys to commands or configuration. The skill covers desktop integration, service accounts, and interactive sign-in while keeping secrets out of chat and logs.

中文简介正在准备中。当前显示英语简介。

  • Setting up the 1Password CLI
  • Supplying API keys to commands
  • Using service account authentication in CI
openclaw/openclaw39.2万2026年10月18日 更新

acp-router

免费有简介AI 评分 80分

将提交给OpenClaw的自然语言请求转交给Claude Code等外部编程智能体,通过ACP或acpx启动、继续会话,并保留对话上下文。

  • 在讨论串中启动Claude Code
  • 继续外部智能体的现有工作
  • 通过acpx直接传递指令
openclaw/openclaw39.2万2026年10月18日 更新

Add a model provider to OpenClaw and verify it with a real response. The skill validates configuration, keeps credentials in environment or file references, and reports test results and any default model changes.

中文简介正在准备中。当前显示英语简介。

  • Adding a model provider to OpenClaw
  • Configuring credentials through environment or file references
  • Checking whether a model returns a real response
openclaw/openclaw39.2万2026年10月18日 更新

Prepare an agent activity transcript for a GitHub pull request or issue. Extract relevant prompts, decisions, and results from local logs, remove sensitive material, and preview the edited record before separately authorized publication.

中文简介正在准备中。当前显示英语简介。

  • Preparing an agent activity record for a pull request
  • Extracting task-relevant prompts and results from local logs
  • Previewing a transcript with sensitive information removed
openclaw/openclaw39.2万2026年10月18日 更新

Manage Apple Notes on macOS through memo, a command-line tool. Create, browse, search, edit, delete, and move notes between folders, or export selected notes to HTML or Markdown for use outside the app.

中文简介正在准备中。当前显示英语简介。

  • Creating notes with titles
  • Finding notes by folder or approximate search
  • Editing notes and organizing them into folders
openclaw/openclaw39.2万2026年10月18日 更新

Manage Apple Reminders from your Mac with remindctl, a terminal tool. View tasks by date, add or edit reminders, organize lists, and mark tasks complete or delete them, including personal to-dos that sync to iOS.

中文简介正在准备中。当前显示英语简介。

  • Review today’s tasks and overdue reminders
  • Add personal to-dos with due dates
  • Organize tasks visible on an iPhone or iPad
openclaw/openclaw39.2万2026年10月18日 更新

查看 openclaw 的全部技能

报告此技能的问题