# QuokkaPix Video browser-agent guide

QuokkaPix Video processes one video locally in the user's browser. Never attempt to pass a local path in the URL or call a server processing endpoint; neither workflow exists.

It is the Video surface of the shared QuokkaPix service. Read the additive service-level contract at `https://quokkapix.com/agent-manifest.json`; Image compatibility remains under `window.QuokkaPixAgent`, while this surface uses `window.QuokkaPixVideoAgent` and `quokkapix.video.*` WebMCP tools.

## Agent payments

Upload the local video first, then call `window.QuokkaPixVideoAgent.getPaymentQuote()`. Duration comes from the decoded local media metadata, not from agent-supplied settings. Editing is free through 5 minutes; over 5-15 minutes costs `0.01 USDC`, over 15-30 costs `0.02 USDC`, and over 30 costs `0.03 USDC`. Transcription/SRT/VTT generation is free through 5 minutes; its paid tiers are `0.02`, `0.04` and `0.06 USDC` for over 5-15, over 15-30 and over 30-45 minutes. Burning existing transcript segments uses the normal editing tier; transcription plus an included subtitle burn is charged once at the transcription tier.

If the quote is paid, request its product-specific `/api/agent-unlock/coinbase-x402/{productId}` endpoint, call `setUnlockToken()`, optionally call `verifyUnlockToken()`, and retry `start()`. Verification without consumption happens after local measurement; consumption happens only immediately before real processing begins. WebMCP, local MCP, Remote MCP and Bridge use this same quote and add no channel fee.

For image resizing, background removal, watermarking, metadata, PDF and batch workflows, route to `https://quokkapix.com/#agent=1` and read `https://quokkapix.com/agents.html`. Local `quokkapix-mcp` version 0.5.0 and newer supports both surfaces; unified paid and remote processing requires version 0.7.0 or newer.

Stable automation must prefer `data-agent`, `data-agent-action`, `data-agent-setting`, `data-agent-output`, `data-agent-status` and `data-process-status`. Visible labels and CSS classes are not stable API.

Sourced social-video profiles are published at `/rules/index.json`. Official YouTube, TikTok Ads and Meta Reels sources are kept with each profile, and requirements are separated from recommendations.

Rule discovery is available through `listRuleProfiles()` and `getRuleProfile(id)`, with matching experimental WebMCP tools `quokkapix.video.list_rule_profiles` and `quokkapix.video.get_rule_profile`.

Browser support is documented at `/browser-compatibility/`. Reproducible performance methodology and the machine-readable profile are at `/browser-video-processing-benchmark/` and `/benchmarks/profile.json`.

## Local MCP runner

`quokkapix-mcp` exposes `process_video` for official recipes and `process_video_with_settings` for direct settings. Both accept one `inputFile`, optional `musicFile`, an `outputDir`, and optional browser/timeout settings. Local stdio accepts local paths; remote MCP accepts paths relative to the bridge roots. Version 0.7.0+ relays the same Video tools and payment quote flow through `https://quokkapix.com/mcp` with OAuth and `bridge:execute`. Chromium runs locally, saves the deliverable and writes `quokkapix-video-result.json`; no media bytes pass through the control plane.

## Stable workflow

```js
await page.goto("https://video.quokkapix.com/#agent=1");
await page.evaluate(() => window.QuokkaPixVideoAgent.applyRecipe("vertical_9_16"));
await page.locator('[data-agent="file-picker"]').setInputFiles(localVideoPath);
await page.locator('.page-shell[data-agent-status="ready"]').waitFor();
await page.evaluate(() => window.QuokkaPixVideoAgent.start());
await page.locator('.page-shell[data-agent-status="done"], .page-shell[data-agent-status="error"], .page-shell[data-agent-status="cancelled"]').waitFor();
const result = await page.evaluate(() => window.QuokkaPixVideoAgent.getResultManifest());
```

Treat `result.qa.ok` and `result.qa.checks[]` as the machine-readable post-run verification surface. Checks cover local-only execution and measurable output metadata; they do not claim semantic inspection of media content.

## Ready-to-upload URLs

An agent can configure the complete editor before choosing a file. `buildUrl(payload)` serializes the full UTF-8 settings object into the base64url `settings` parameter:

```js
const url = window.QuokkaPixVideoAgent.buildUrl({
  tool: "crop",
  crop: { preset: "custom", width: 1080, height: 1920, fit: "cover", zoom: 1.15 },
  convert: { format: "mp4" }
});
// Open the returned URL; only the local file upload remains.
```

Simple settings may also be written directly in the hash:

```text
/#agent=1&tool=crop&width=1080&height=1920&fit=cover
/#agent=1&tool=compress&quality=medium&resolution=720&target-mb=25
/#agent=1&tool=transcribe&transcript-language=auto&transcript-format=srt&burn-subtitles=1
```

Use encoded `settings` for non-destructive `segments[]`, speed-curve points, complete audio mixing, supplied transcript segments and subtitle styling. Local source and music files must still be uploaded through their browser inputs.

For Cut, prefer `segments: [{ sourceStart, sourceEnd, enabled, speed, speedCurve, audioEnabled, audioVolume }]` after the source duration is known. Speed-curve points use normalized `position` values from `0` to `1` and speeds from `0.25` to `4`. Speed changes retime the source audio and change its pitch naturally. The legacy `selection.start`, `selection.end` and `selection.action` payload remains supported. For Transcribe, select a language or use `auto`; the current maximum is 45 minutes. Inspect live capabilities before choosing a codec. Browser RAM is the hard processing limit.

For burned subtitles, apply `burn_subtitles` and call `start()` once to transcribe. Review or edit the returned segments, then call `start()` again to render them permanently into MP4. If transcript segments are supplied through `applySettings`, only the export start is needed.

For interactive crop/transform, set `crop.width`, `crop.height`, `crop.fit`, `crop.zoom`, `crop.offsetX`, `crop.offsetY`, `crop.rotation`, `crop.flipX` and `crop.flipY`. Zoom is `0.5` to `4`, offsets are percentages from `-100` to `100`, and rotation is `0`, `90`, `180` or `270`. The canvas at `[data-agent-output="crop-preview"]` is a live human preview; its values are also exposed in `getState().settings.crop` and the result manifest.

For Audio v2, use `audio.mode: "mix"` to combine the source track with local music or `audio.mode: "replace"` to replace it. Upload the additional file through `[data-agent="music-file-picker"]`; local paths cannot be sent in settings. Configure source/music volume, start offset, trim bounds, fades and looping through `audio`, wait for `settings.audio.musicLoaded`, then call `start()`. The result manifest includes the applied `audioMix` settings.

Stable errors: `unsupported_format`, `unsupported_codec`, `no_video_track`, `no_audio_track`, `no_active_segments`, `memory_risk_high`, `browser_export_unavailable`, `transcription_failed`, `processing_cancelled`, `processing_failed`.
