[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M698RVZT2TXWYENG7DYRJK65":3,"skill-same:01M698RVZT2TXWYENG7DYRJK65":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":51,"ownerHtmlUrl":52,"ownerBlogUrl":51,"ownerDescription":53,"updatedAt":54,"install":55,"resources":68},"01M698RVZT2TXWYENG7DYRJK65","proof-video",null,"Capture and annotate PR screenshots and videos with measured arrows, outlines, alignment guides, spacing brackets, captions, zoom, and speed cues.","openclaw\u002Fopenclaw","openclaw","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F252820863?v=4","01M698P3FSAZ6B4R928ZF19KPT","01M698PDMDRVH56MV30D253NFP",394302,"MIT","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fproof-video\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"proof video","Video","proof","spacing","screenshots","videos","with","zoom","guides","brackets","speed","annotate","alignment","capture","Captions","Outlines","pr screenshots","pr","2026-11-10 10:12:30",false,"---\nname: proof-video\ndescription: Capture and annotate PR screenshots and videos with measured arrows, outlines, alignment guides, spacing brackets, captions, zoom, and speed cues.\n---\n\n# Proof video\n\nUse this developer skill for captioned Control UI recordings and native captures.\nCaptions are burned into an MP4; they are visual narration, not synthesized audio.\nKeep the raw video as evidence, attach the polished MP4, and never commit media or\n`.artifacts\u002F` output. Inspect the entire capture for unrelated or private content\nbefore publishing under the PR's existing authorization.\n\n## Point out the claim\n\nChoose marks that demonstrate the change. Use arrows to locate a control, outlines\nto identify a region, alignment guides to compare edges or centers, and spacing\nbrackets to measure gaps. Measurements come from `locator.boundingBox()` after the\nasserted layout settles; the renderer calculates the labels. Keep the reference\nelement first and use the same viewport, crop, scale, and edge before and after.\nKeep marks sparse and labels in empty space. Preserve the raw capture.\n\nFor screenshot markup or timed video marks, read [annotations](references\u002Fannotations.md).\nBoth paths use the same SVG geometry renderer. Annotations are composited before\nzoom, while narration stays fixed in the viewport. Re-measure and replace marks\nafter scrolling or layout changes; a cue describes a stationary capture, not a\nlive element tracker. Clear marks during movement when they would become stale.\n\n## Standalone recording\n\nFrom the repository root, save this script as `.artifacts\u002Fproof-video\u002Frecord.mts`\n(create the parent directory first), then run\n`node --import tsx .artifacts\u002Fproof-video\u002Frecord.mts`. It starts an isolated mocked\nControl UI, records five captions, a real toolbar zoom, fast-forwarded startup, and an eight-second pause\nat 4× speed. Every invocation allocates a fresh evidence directory.\n\n```ts\nimport { chromium } from \"playwright\";\nimport { createControlUiE2eArtifactDir } from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fcontrol-ui-e2e-artifacts.ts\";\nimport {\n  installMockGateway,\n  resolvePlaywrightChromiumExecutablePath,\n  startControlUiE2eServer,\n} from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fcontrol-ui-e2e.ts\";\nimport { startProofRecording } from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fproof-video.ts\";\n\nconst dir = createControlUiE2eArtifactDir(\"captioned-toolbar\", \".artifacts\u002Fproof-video\");\nconst server = await startControlUiE2eServer(undefined, { source: true });\nconst browser = await chromium.launch({\n  executablePath: resolvePlaywrightChromiumExecutablePath(chromium.executablePath()),\n  args: [\"--force-device-scale-factor=2\"],\n});\ntry {\n  const recording = await startProofRecording(browser, {\n    dir,\n    contextOptions: { colorScheme: \"dark\", locale: \"en-US\", reducedMotion: \"reduce\" },\n  });\n  const { page } = recording;\n  const sessions = [\"Main\", \"Weekly planning\", \"Reading list\"].map((label, index) => ({\n    key: index === 0 ? \"agent:main:main\" : `agent:main:proof-${index}`,\n    label,\n    displayName: label,\n    kind: \"direct\",\n    status: \"done\",\n    hasActiveRun: false,\n    updatedAt: Date.parse(\"2026-09-01T12:00:00Z\") - index * 60000,\n    contextTokens: 200000,\n    totalTokens: 0,\n    model: \"gpt-5.6-luna\",\n    modelProvider: \"openai\",\n  }));\n  const gateway = await installMockGateway(page, {\n    sessionKey: \"agent:main:main\",\n    sessionArchiveFiltering: true,\n    methodResponses: {\n      \"sessions.list\": {\n        sessions,\n        count: sessions.length,\n        totalCount: sessions.length,\n        hasMore: false,\n        offset: 0,\n        limitApplied: 50,\n        nextOffset: null,\n        path: \"\",\n        ts: sessions[0].updatedAt,\n        defaults: { contextTokens: 200000, model: \"gpt-5.6-luna\", modelProvider: \"openai\" },\n      },\n    },\n  });\n  recording.caption(\"Open the mocked Control UI.\");\n  recording.speed(8);\n  await page.goto(`${server.baseUrl}chat`);\n  await gateway.waitForRequest(\"sessions.list\");\n  await page.getByRole(\"link\", { name: \"Weekly planning\", exact: true }).waitFor();\n  const toolbar = page.locator(\".sidebar-session-toolbar\");\n  await toolbar.getByText(\"Sessions\", { exact: true }).waitFor();\n  recording.speed(1);\n  await page.waitForTimeout(1500);\n  recording.caption(\"Find your conversations in the session list.\");\n  await page.waitForTimeout(3000);\n  await recording.zoom(toolbar);\n  recording.caption(\"Zoom in on the session filter controls.\");\n  await toolbar.getByRole(\"button\", { name: \"Filter & sort\" }).click();\n  await page.locator(\".sidebar-session-sort-menu\").waitFor({ state: \"visible\" });\n  await page.waitForTimeout(4000);\n  recording.zoomOut();\n  recording.caption(\"Fast-forward an eight-second pause.\");\n  recording.speed(4);\n  await page.waitForTimeout(8000);\n  recording.speed(1);\n  recording.caption(\"Return to the full session list.\");\n  await page.getByRole(\"radio\", { name: \"All\", exact: true }).click();\n  await page.waitForFunction(() =>\n    document\n      .querySelector(\".sidebar-session-sort\")\n      ?.classList.contains(\"sidebar-session-sort--filtered\"),\n  );\n  await page.waitForTimeout(3000);\n  console.log(JSON.stringify(await recording.finish(), null, 2));\n} finally {\n  await browser.close();\n  await server.close();\n}\n```\n\nUse `caption(text)` to replace the current caption, `clearCaption()` to end it,\n`zoom(locatorOrRect, { factor: 2, padding: 24, ease: 0.5 })` to start or replace a\nzoom, and `zoomOut()` to end it. Rectangles use viewport CSS pixels. Padding\nexpands and clamps the target rectangle; its center determines the zoom focus.\n`speed(factor)` changes playback speed until the next call; `speed(1)` restores\nnormal playback. `finish()` closes open cues at the finalized video's end,\ncloses the recording context, rasterizes captions, writes `cues.json`, and returns\n`{ dir, videoPath, cuesPath }`. The caller closes the browser and server.\n\nThe helper is test tooling at `ui\u002Fsrc\u002Ftest-helpers\u002Fproof-video.ts`; production\ncode must not import it. `contextOptions` carries ordinary Playwright context\noptions, while the helper owns the viewport, recording size, and device scale.\nKeep narration to one or two short lines; oversized text fails instead of\nsilently clipping. Caption PNGs are transparent viewport-width, 120-pixel-high\nstrips with a centered dark rounded card and 30-pixel system text.\n\n## Render\n\nUse the exact directory printed by the recording:\n\n```bash\nnode --import tsx scripts\u002Frender-proof-video.mts --cues .artifacts\u002Fproof-video\u002F\u003Ccapture>\u002Fcues.json\n```\n\nThe renderer prints the output path and duration. Optional `--input \u003Cvideo>`\noverrides the raw input and `--out \u003Cfile.mp4>` chooses the output. Existing output\nfiles are refused, preserving raw evidence and earlier renders. It uses trusted\nsystem `ffmpeg` and `ffprobe`, never Playwright's bundled encoder. Install a full\nsystem build with `brew install ffmpeg` or `apt install ffmpeg`.\n\nSpeed segments split the raw timeline with trim\u002Fsetpts\u002Fconcat, then normalize it\nto the input frame rate. Caption windows and zoom transitions are remapped to\noutput time. Zoom uses `zoompan` with `d=1` and matching input FPS; a 100-frame,\n4-second, 25-FPS synthetic capture retained exactly 100 frames and 4 seconds,\nwith a visibly and numerically different zoom hold. Dynamic crop width\u002Fheight\nexpressions do not animate: ffmpeg evaluates them only at initialization.\nOutput is viewport-sized H.264 MP4, yuv420p, CRF 23, with faststart and no audio.\n\n## Cue sidecar v1 and native captures\n\nSave a hand-written `cues.json` beside an untouched native `.mov` or `.webm`.\nUse `scale` for actual raw pixels per viewport CSS pixel, not display metadata.\nInput dimensions must equal viewport × scale and frame rate must be constant.\nAll times below are seconds in the RAW video. Caption image paths are relative\nto the sidecar directory. Zoom cues cannot overlap other zoom cues; speed cues\ncannot overlap other speed cues. Adjacent cues are allowed.\n\n```json\n{\n  \"version\": 1,\n  \"video\": \"capture.mov\",\n  \"viewport\": { \"width\": 1280, \"height\": 800 },\n  \"scale\": 2,\n  \"captionHeight\": 120,\n  \"cues\": [\n    {\n      \"kind\": \"caption\",\n      \"start\": 1,\n      \"end\": 4,\n      \"text\": \"Inspect the session controls.\",\n      \"image\": \"captions\u002F0.png\"\n    },\n    {\n      \"kind\": \"zoom\",\n      \"start\": 1,\n      \"end\": 4,\n      \"rect\": { \"x\": 20, \"y\": 150, \"width\": 280, \"height\": 80 },\n      \"factor\": 2,\n      \"ease\": 0.5\n    },\n    { \"kind\": \"speed\", \"start\": 5, \"end\": 9, \"factor\": 4 }\n  ]\n}\n```\n\n```bash\nnode --import tsx scripts\u002Frender-proof-video.mts --cues \u003Cdir>\u002Fcues.json --rasterize\n```\n\n`--rasterize` creates missing caption and annotation PNGs with fresh Playwright Chromium pages.\nThe exported `rasterizeProofOverlays(browser, cues, dir)` also supports programmatic\nnative-capture workflows. Neither path needs libass or drawtext: Chromium\nrasterizes text and geometry. ffmpeg overlays annotations before zoom and captions\nafter zoom.\n\n## Verified capture mode and limitations\n\nOn macOS with Playwright 1.62.1 and Chromium 151.0.7922.34, context\n`deviceScaleFactor: 2` produced a 2560×1600 WebM containing only 1280×800 page\ncontent plus gray padding. Launching with `--force-device-scale-factor=2` and\nleaving context emulation at 1 recorded true 2× content: a 100-CSS-pixel marker\nmeasured 200×200 at raw coordinates (2360, 1400). The helper defaults to\n`deviceScaleFactor: 2` for recording size and sidecar scale; the launch flag in\nthe template is required. This parameter does not enable context emulation.\nFor verified 1× capture, launch without the flag and pass `deviceScaleFactor: 1`.\nThe renderer uses Lanczos pre-upscaling for 1× sources, but cannot restore lost\ndetail: a 2× zoom on those recordings is softer.\n\nThe cue clock starts at context creation using `performance.now()`. Playwright's\nvideo clock can differ by roughly 100 ms, and startup\u002Fload can increase the skew;\ninspect action\u002Fcaption alignment in the finalized recording. Avoid clipped,\nlocator, or full-page screenshots during recording: Chromium can corrupt the\nscreencast surface. Caption rasterization happens only after recording closes,\nin a fresh context. See the Control UI E2E skill's screenshot guidance.\n\nGitHub's player ignores subtitle tracks, so captions must be burned in. The\nrenderer requires crop, scale, overlay, setpts, trim, concat, fps, and zoompan in\nthe system ffmpeg build. It does not use `subtitles=` or `drawtext=`. Variable\nframe-rate native captures need conversion to a separate constant-frame-rate\nworking copy first; retain the original. Frame-rate quantization can shift\nspeed-segment boundaries by about one output frame. Check output duration and\nextract caption, zoom-hold, and sped-segment frames before attaching the MP4.\n","# Proof video\n\nUse this developer skill for captioned Control UI recordings and native captures.\nCaptions are burned into an MP4; they are visual narration, not synthesized audio.\nKeep the raw video as evidence, attach the polished MP4, and never commit media or\n`.artifacts\u002F` output. Inspect the entire capture for unrelated or private content\nbefore publishing under the PR's existing authorization.\n\n## Point out the claim\n\nChoose marks that demonstrate the change. Use arrows to locate a control, outlines\nto identify a region, alignment guides to compare edges or centers, and spacing\nbrackets to measure gaps. Measurements come from `locator.boundingBox()` after the\nasserted layout settles; the renderer calculates the labels. Keep the reference\nelement first and use the same viewport, crop, scale, and edge before and after.\nKeep marks sparse and labels in empty space. Preserve the raw capture.\n\nFor screenshot markup or timed video marks, read [annotations](references\u002Fannotations.md).\nBoth paths use the same SVG geometry renderer. Annotations are composited before\nzoom, while narration stays fixed in the viewport. Re-measure and replace marks\nafter scrolling or layout changes; a cue describes a stationary capture, not a\nlive element tracker. Clear marks during movement when they would become stale.\n\n## Standalone recording\n\nFrom the repository root, save this script as `.artifacts\u002Fproof-video\u002Frecord.mts`\n(create the parent directory first), then run\n`node --import tsx .artifacts\u002Fproof-video\u002Frecord.mts`. It starts an isolated mocked\nControl UI, records five captions, a real toolbar zoom, fast-forwarded startup, and an eight-second pause\nat 4× speed. Every invocation allocates a fresh evidence directory.\n\n```ts\nimport { chromium } from \"playwright\";\nimport { createControlUiE2eArtifactDir } from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fcontrol-ui-e2e-artifacts.ts\";\nimport {\n  installMockGateway,\n  resolvePlaywrightChromiumExecutablePath,\n  startControlUiE2eServer,\n} from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fcontrol-ui-e2e.ts\";\nimport { startProofRecording } from \"..\u002F..\u002Fui\u002Fsrc\u002Ftest-helpers\u002Fproof-video.ts\";\n\nconst dir = createControlUiE2eArtifactDir(\"captioned-toolbar\", \".artifacts\u002Fproof-video\");\nconst server = await startControlUiE2eServer(undefined, { source: true });\nconst browser = await chromium.launch({\n  executablePath: resolvePlaywrightChromiumExecutablePath(chromium.executablePath()),\n  args: [\"--force-device-scale-factor=2\"],\n});\ntry {\n  const recording = await startProofRecording(browser, {\n    dir,\n    contextOptions: { colorScheme: \"dark\", locale: \"en-US\", reducedMotion: \"reduce\" },\n  });\n  const { page } = recording;\n  const sessions = [\"Main\", \"Weekly planning\", \"Reading list\"].map((label, index) => ({\n    key: index === 0 ? \"agent:main:main\" : `agent:main:proof-${index}`,\n    label,\n    displayName: label,\n    kind: \"direct\",\n    status: \"done\",\n    hasActiveRun: false,\n    updatedAt: Date.parse(\"2026-09-01T12:00:00Z\") - index * 60000,\n    contextTokens: 200000,\n    totalTokens: 0,\n    model: \"gpt-5.6-luna\",\n    modelProvider: \"openai\",\n  }));\n  const gateway = await installMockGateway(page, {\n    sessionKey: \"agent:main:main\",\n    sessionArchiveFiltering: true,\n    methodResponses: {\n      \"sessions.list\": {\n        sessions,\n        count: sessions.length,\n        totalCount: sessions.length,\n        hasMore: false,\n        offset: 0,\n        limitApplied: 50,\n        nextOffset: null,\n        path: \"\",\n        ts: sessions[0].updatedAt,\n        defaults: { contextTokens: 200000, model: \"gpt-5.6-luna\", modelProvider: \"openai\" },\n      },\n    },\n  });\n  recording.caption(\"Open the mocked Control UI.\");\n  recording.speed(8);\n  await page.goto(`${server.baseUrl}chat`);\n  await gateway.waitForRequest(\"sessions.list\");\n  await page.getByRole(\"link\", { name: \"Weekly planning\", exact: true }).waitFor();\n  const toolbar = page.locator(\".sidebar-session-toolbar\");\n  await toolbar.getByText(\"Sessions\", { exact: true }).waitFor();\n  recording.speed(1);\n  await page.waitForTimeout(1500);\n  recording.caption(\"Find your conversations in the session list.\");\n  await page.waitForTimeout(3000);\n  await recording.zoom(toolbar);\n  recording.caption(\"Zoom in on the session filter controls.\");\n  await toolbar.getByRole(\"button\", { name: \"Filter & sort\" }).click();\n  await page.locator(\".sidebar-session-sort-menu\").waitFor({ state: \"visible\" });\n  await page.waitForTimeout(4000);\n  recording.zoomOut();\n  recording.caption(\"Fast-forward an eight-second pause.\");\n  recording.speed(4);\n  await page.waitForTimeout(8000);\n  recording.speed(1);\n  recording.caption(\"Return to the full session list.\");\n  await page.getByRole(\"radio\", { name: \"All\", exact: true }).click();\n  await page.waitForFunction(() =>\n    document\n      .querySelector(\".sidebar-session-sort\")\n      ?.classList.contains(\"sidebar-session-sort--filtered\"),\n  );\n  await page.waitForTimeout(3000);\n  console.log(JSON.stringify(await recording.finish(), null, 2));\n} finally {\n  await browser.close();\n  await server.close();\n}\n```\n\nUse `caption(text)` to replace the current caption, `clearCaption()` to end it,\n`zoom(locatorOrRect, { factor: 2, padding: 24, ease: 0.5 })` to start or replace a\nzoom, and `zoomOut()` to end it. Rectangles use viewport CSS pixels. Padding\nexpands and clamps the target rectangle; its center determines the zoom focus.\n`speed(factor)` changes playback speed until the next call; `speed(1)` restores\nnormal playback. `finish()` closes open cues at the finalized video's end,\ncloses the recording context, rasterizes captions, writes `cues.json`, and returns\n`{ dir, videoPath, cuesPath }`. The caller closes the browser and server.\n\nThe helper is test tooling at `ui\u002Fsrc\u002Ftest-helpers\u002Fproof-video.ts`; production\ncode must not import it. `contextOptions` carries ordinary Playwright context\noptions, while the helper owns the viewport, recording size, and device scale.\nKeep narration to one or two short lines; oversized text fails instead of\nsilently clipping. Caption PNGs are transparent viewport-width, 120-pixel-high\nstrips with a centered dark rounded card and 30-pixel system text.\n\n## Render\n\nUse the exact directory printed by the recording:\n\n```bash\nnode --import tsx scripts\u002Frender-proof-video.mts --cues .artifacts\u002Fproof-video\u002F\u003Ccapture>\u002Fcues.json\n```\n\nThe renderer prints the output path and duration. Optional `--input \u003Cvideo>`\noverrides the raw input and `--out \u003Cfile.mp4>` chooses the output. Existing output\nfiles are refused, preserving raw evidence and earlier renders. It uses trusted\nsystem `ffmpeg` and `ffprobe`, never Playwright's bundled encoder. Install a full\nsystem build with `brew install ffmpeg` or `apt install ffmpeg`.\n\nSpeed segments split the raw timeline with trim\u002Fsetpts\u002Fconcat, then normalize it\nto the input frame rate. Caption windows and zoom transitions are remapped to\noutput time. Zoom uses `zoompan` with `d=1` and matching input FPS; a 100-frame,\n4-second, 25-FPS synthetic capture retained exactly 100 frames and 4 seconds,\nwith a visibly and numerically different zoom hold. Dynamic crop width\u002Fheight\nexpressions do not animate: ffmpeg evaluates them only at initialization.\nOutput is viewport-sized H.264 MP4, yuv420p, CRF 23, with faststart and no audio.\n\n## Cue sidecar v1 and native captures\n\nSave a hand-written `cues.json` beside an untouched native `.mov` or `.webm`.\nUse `scale` for actual raw pixels per viewport CSS pixel, not display metadata.\nInput dimensions must equal viewport × scale and frame rate must be constant.\nAll times below are seconds in the RAW video. Caption image paths are relative\nto the sidecar directory. Zoom cues cannot overlap other zoom cues; speed cues\ncannot overlap other speed cues. Adjacent cues are allowed.\n\n```json\n{\n  \"version\": 1,\n  \"video\": \"capture.mov\",\n  \"viewport\": { \"width\": 1280, \"height\": 800 },\n  \"scale\": 2,\n  \"captionHeight\": 120,\n  \"cues\": [\n    {\n      \"kind\": \"caption\",\n      \"start\": 1,\n      \"end\": 4,\n      \"text\": \"Inspect the session controls.\",\n      \"image\": \"captions\u002F0.png\"\n    },\n    {\n      \"kind\": \"zoom\",\n      \"start\": 1,\n      \"end\": 4,\n      \"rect\": { \"x\": 20, \"y\": 150, \"width\": 280, \"height\": 80 },\n      \"factor\": 2,\n      \"ease\": 0.5\n    },\n    { \"kind\": \"speed\", \"start\": 5, \"end\": 9, \"factor\": 4 }\n  ]\n}\n```\n\n```bash\nnode --import tsx scripts\u002Frender-proof-video.mts --cues \u003Cdir>\u002Fcues.json --rasterize\n```\n\n`--rasterize` creates missing caption and annotation PNGs with fresh Playwright Chromium pages.\nThe exported `rasterizeProofOverlays(browser, cues, dir)` also supports programmatic\nnative-capture workflows. Neither path needs libass or drawtext: Chromium\nrasterizes text and geometry. ffmpeg overlays annotations before zoom and captions\nafter zoom.\n\n## Verified capture mode and limitations\n\nOn macOS with Playwright 1.62.1 and Chromium 151.0.7922.34, context\n`deviceScaleFactor: 2` produced a 2560×1600 WebM containing only 1280×800 page\ncontent plus gray padding. Launching with `--force-device-scale-factor=2` and\nleaving context emulation at 1 recorded true 2× content: a 100-CSS-pixel marker\nmeasured 200×200 at raw coordinates (2360, 1400). The helper defaults to\n`deviceScaleFactor: 2` for recording size and sidecar scale; the launch flag in\nthe template is required. This parameter does not enable context emulation.\nFor verified 1× capture, launch without the flag and pass `deviceScaleFactor: 1`.\nThe renderer uses Lanczos pre-upscaling for 1× sources, but cannot restore lost\ndetail: a 2× zoom on those recordings is softer.\n\nThe cue clock starts at context creation using `performance.now()`. Playwright's\nvideo clock can differ by roughly 100 ms, and startup\u002Fload can increase the skew;\ninspect action\u002Fcaption alignment in the finalized recording. Avoid clipped,\nlocator, or full-page screenshots during recording: Chromium can corrupt the\nscreencast surface. Caption rasterization happens only after recording closes,\nin a fresh context. See the Control UI E2E skill's screenshot guidance.\n\nGitHub's player ignores subtitle tracks, so captions must be burned in. The\nrenderer requires crop, scale, overlay, setpts, trim, concat, fps, and zoompan in\nthe system ffmpeg build. It does not use `subtitles=` or `drawtext=`. Variable\nframe-rate native captures need conversion to a separate constant-frame-rate\nworking copy first; retain the original. Frame-rate quantization can shift\nspeed-segment boundaries by about one output frame. Check output duration and\nextract caption, zoom-hold, and sped-segment frames before attaching the MP4.\n",{"name":5,"description":7},"main","df9d3240e52a533ea176e98cf047ed6b40cf37d6",".agents\u002Fskills\u002Fproof-video",82862,"https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw","https:\u002F\u002Fopenclaw.ai","https:\u002F\u002Fgithub.com\u002Fopenclaw","Your personal, open source AI assistant.","2026-11-11 08:46:30",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add openclaw\u002Fopenclaw --skill proof-video",{"tool":61,"command":62},"bunx","bunx skills add openclaw\u002Fopenclaw --skill proof-video",{"tool":64,"command":65},"pnpm","pnpm dlx skills add openclaw\u002Fopenclaw --skill proof-video","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fproof-video\u002FSKILL.md",true,[69],{"path":70,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":74},"references\u002Fannotations.md","REFERENCE","参考文档",5213,"https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fproof-video\u002Freferences\u002Fannotations.md",[76,82,105,122,144,166],{"skillNo":77,"name":78,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":41},"01M698VP84FNM6G9MR1HPX7MF7","lobster","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fextensions\u002Flobster\u002FSKILL.md",[],[78],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":41},"01M698YY8QGQ7S8TJNKJG6VTPH","xurl","xurl CLI for authenticated X posts, replies, reads\u002Fsearch, DMs, media upload, followers, auth status, or raw v2 API calls.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fskills\u002Fxurl\u002FSKILL.md",[],[84,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104],"for","api","calls","replies","posts","upload","tap","install","brew","node","Media","search","npm","status","auth","cli",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":111,"publishedAt":41},"01M698YWT1CJ0WK88WB909R9RT","weather","Current weather and forecasts with web_fetch, falling back to wttr.in curl for locations, rain, temperature, travel planning.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fskills\u002Fweather\u002FSKILL.md",[],[107,112,113,96,114,97,115,116,117,118,119,120,89,121,29],"travel planning","travel","fetch","curl","https","help","planning","web","back","temperature",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":133,"publishedAt":41},"01M698YV2Q0R0JJKAWGFS21K0N","visualize","Create inline visuals for code and explanations, or author persistent OpenClaw dashboard widgets with show_widget.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fskills\u002Fvisualize\u002FSKILL.md",[128],{"categoryNo":129,"categoryName":130,"taxonomyType":131,"taxonomyTypeDesc":132},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[124,134,135,136,137,89,29,138,139,140,141,142,9,143],"widgets","openclaw dashboard","author","inline","show","code","create","visuals","dashboard","widget",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":156,"publishedAt":41},"01M698YS2TRJH9ENG28HD9CD87","trello","Manage Trello boards, lists, and cards via the Trello REST API.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fskills\u002Ftrello\u002FSKILL.md",[150,153],{"categoryNo":151,"categoryName":152,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":154,"categoryName":155,"taxonomyType":131,"taxonomyTypeDesc":132},"01JBSEEDCAT000000000000030","开发工程师",[146,116,157,158,159,160,161,162,96,97,163,115,90,164,165],"cloud","manage","via","rest api","token","atlassian","jq","REST","developer",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":41},"01M698YQ9Q3M4W78EWV2KSCSVW","tmux","Control tmux sessions\u002Fpanes for interactive CLIs: list, capture output, send keys, paste text, monitor prompts.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw\u002Fblob\u002Fmain\u002Fskills\u002Ftmux\u002FSKILL.md",[],[168,96,173,174,89,175,176,177,178,179,180,181,97,36,182,183,184,185,186],"send","darwin","keys","paste","output","control","prompts","interactive","list","panes","text","monitor","sessions","linux"]