Skip to content

feat(web-integration): use WebP for browser screenshot producers - #2858

Closed
quanruzhuoxiu wants to merge 5 commits into
feat/webp-report-consumersfrom
feat/webp-browser-producers-v2
Closed

feat(web-integration): use WebP for browser screenshot producers#2858
quanruzhuoxiu wants to merge 5 commits into
feat/webp-report-consumersfrom
feat/webp-browser-producers-v2

Conversation

@quanruzhuoxiu

@quanruzhuoxiu quanruzhuoxiu commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • use native WebP capture APIs where the browser runtime supports them
  • disable CDP WebP capture for a Playwright page after its first failure, avoiding repeated failures and timeouts
  • route PNG fallback captures through the shared canonical WebP encoder
  • preserve each screenshot's real format in Chrome Recorder ZIP and Markdown exports
  • add unit and runtime-backed browser coverage for real WebP captures and report export
  • capture the exact image bytes passed to chat.completions.create() and verify that Markdown exports the same WebP bytes, without depending on the independent model-input recorder PR

The reusable PNG/JPEG-to-WebP implementation lives in packages/shared/src/img/transform.ts: canonicalizeScreenshotBase64() calls convertImgBufferToWebp(), which uses Sharp in Node and the browser encoder for RGBA pixels. This PR wires browser producers to native WebP capture where possible and uses that shared encoder only for fallback paths.

WebP generation paths

Scenario Where WebP is generated Encoding path
Chrome extension page packages/web-integration/src/chrome-extension/screenshot.ts Native CDP Page.captureScreenshot({ format: 'webp', quality: 90 })
Puppeteer packages/web-integration/src/puppeteer/base-page.ts Native page.screenshot({ type: 'webp', quality: 90 })
Playwright on Chromium packages/web-integration/src/puppeteer/base-page.ts Native CDP WebP capture; the first CDP failure disables this optimization for the current Midscene page
Playwright after CDP is disabled packages/web-integration/src/puppeteer/base-page.ts and packages/shared/src/img/transform.ts Capture PNG, then canonicalizeScreenshotBase64() encodes WebP with Sharp
Chrome Recorder apps/chrome-extension/src/utils/screenshot.ts captureVisibleTab() produces PNG, then OffscreenCanvas.convertToBlob({ type: 'image/webp', quality: 0.9 }) encodes WebP
Recorder ZIP and Markdown export apps/chrome-extension/src/extension/recorder/screenshot-export.ts No encoding; detect the actual bytes and preserve the correct extension and MIME type

Stack

Validation

  • pnpm --filter chrome-extension test (10 files, 40 tests passed)
  • pnpm --filter @midscene/playground test (19 files, 274 tests passed)
  • pnpm --filter @midscene/web test (50 files, 412 passed, 1 skipped)
  • pnpm exec vitest --run tests/unit-test/base-page-screenshot.test.ts from packages/web-integration (5 tests passed)
  • pnpm exec playwright test tests/ai/web/playwright/screenshot-cdp-webp.spec.ts --config=tests/playwright.config.ts from packages/web-integration (1 test passed)
  • pnpm exec nx test:ai @midscene/web --skip-nx-cache -- tests/ai/web/puppeteer/webp-report.test.ts (4 consecutive runs passed)
  • pnpm exec nx build @midscene/web
  • pnpm exec nx run-many -t build -p chrome-extension @midscene/playground @midscene/web
  • pnpm run type-check:tests
  • pnpm run lint

@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-report-consumers branch from 88e097e to 675a785 Compare July 23, 2026 09:50
@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-browser-producers-v2 branch from d84b795 to 3fde745 Compare July 23, 2026 09:50
@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-report-consumers branch from 675a785 to 92530ad Compare July 23, 2026 11:56
@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-browser-producers-v2 branch from 3fde745 to 9e844d2 Compare July 23, 2026 11:56
@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-report-consumers branch from 92530ad to ebfa101 Compare July 24, 2026 07:45
@quanruzhuoxiu
quanruzhuoxiu force-pushed the feat/webp-browser-producers-v2 branch from cf0b274 to c31d6c4 Compare July 24, 2026 07:46
@quanru
quanru marked this pull request as ready for review July 28, 2026 02:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c31d6c41a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +458 to +459
void canonicalizeRecorderScreenshot(dataUrl).then(
(webpDataUrl) => sendResponse(webpDataUrl),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep WebP encoding within the recorder's one-second budget

On high-resolution displays or slower machines, decoding the full PNG and completing OffscreenCanvas.convertToBlob() can take more than the fixed 1,000 ms timeout in event-recorder-bridge.ts:78-97. Because the response is now delayed until this conversion completes, the bridge times out and records the event without its screenshot even when captureVisibleTab succeeded; extend the capture budget or move conversion off the response-critical path.

Useful? React with 👍 / 👎.

Comment on lines +460 to +465
(error) => {
console.error(
'[ServiceWorker] Failed to encode recorder screenshot as WebP:',
error,
);
sendResponse(null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the PNG when WebP encoding fails

If createImageBitmap, the canvas context, or WebP encoding fails, this converts a successfully captured PNG into a null response; the recorder interprets that as no screenshot and silently omits the before/after image. Return the original PNG as a fallback or propagate an explicit failure instead of discarding valid capture data.

AGENTS.md reference: AGENTS.md:L6-L8

Useful? React with 👍 / 👎.

@quanruzhuoxiu

Copy link
Copy Markdown
Collaborator Author

Closing this superseded WebP stack PR. The replacement stack is #3012#3013#3014 and incorporates the latest main branch plus the follow-up architecture, format-validation, and CI fixes. PR #2856 remains open because it is an independent model-input evidence change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant