{"_id":"@danecodes/roku-screenshot","name":"@danecodes/roku-screenshot","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@danecodes/roku-screenshot","version":"0.1.0","description":"Capture, diff, and process screenshots from Roku devices","type":"module","bin":{"roku-screenshot":"bin/roku-screenshot"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"engines":{"node":">=18"},"scripts":{"build":"tsc","dev":"tsx src/cli.ts","test":"vitest run","test:watch":"vitest","prepublishOnly":"npm test && npm run build"},"keywords":["roku","screenshot","visual-regression","diff","testing","sharp"],"license":"MIT","author":{"name":"Dane Hesseldahl"},"repository":{"type":"git","url":"git+https://github.com/danecodes/roku-screenshot.git"},"dependencies":{"@danecodes/roku-ecp":"^0.2.0","sharp":"^0.33.5"},"devDependencies":{"@types/node":"^22.15.0","tsx":"^4.21.0","typescript":"^5.8.0","vitest":"^4.1.2"},"gitHead":"bb5491f174d12944eb35994fb7ba02ed19e0f298","_id":"@danecodes/roku-screenshot@0.1.0","bugs":{"url":"https://github.com/danecodes/roku-screenshot/issues"},"homepage":"https://github.com/danecodes/roku-screenshot#readme","_nodeVersion":"25.8.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-T+WrzO4o9XOJO5oiGtVtgj7Nq5iHB4Q5DVoUG+xTCbX9rzia9dn8QOnlkxjI4FyBxBTgOIk7vFZ/xb6zMV6r6Q==","shasum":"7b700d81326b96575496ec52a5d11c4042469f0c","tarball":"https://registry.npmjs.org/@danecodes/roku-screenshot/-/roku-screenshot-0.1.0.tgz","fileCount":13,"unpackedSize":27568,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICS05o9vaOV9AIB2CDEP93nbSAaZlpUiXnbz4Iv87HTXAiALBoBdh0V+xCeLYFYzWeMyq512DzJVoa8S0knQASlPNQ=="}]},"_npmUser":{"name":"danecodes","email":"danehesseldahl@gmail.com"},"directories":{},"maintainers":[{"name":"danecodes","email":"danehesseldahl@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/roku-screenshot_0.1.0_1775281143006_0.9877046470726947"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-04T05:39:02.872Z","0.1.0":"2026-04-04T05:39:03.171Z","modified":"2026-04-04T05:39:03.405Z"},"maintainers":[{"name":"danecodes","email":"danehesseldahl@gmail.com"}],"description":"Capture, diff, and process screenshots from Roku devices","homepage":"https://github.com/danecodes/roku-screenshot#readme","keywords":["roku","screenshot","visual-regression","diff","testing","sharp"],"repository":{"type":"git","url":"git+https://github.com/danecodes/roku-screenshot.git"},"author":{"name":"Dane Hesseldahl"},"bugs":{"url":"https://github.com/danecodes/roku-screenshot/issues"},"license":"MIT","readme":"# roku-screenshot\n\n[![npm version](https://img.shields.io/npm/v/@danecodes/roku-screenshot)](https://www.npmjs.com/package/@danecodes/roku-screenshot)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nCapture, diff, and process screenshots from Roku devices. Built on [@danecodes/roku-ecp](https://github.com/danecodes/roku-ecp) and [sharp](https://sharp.pixelplumbing.com/).\n\n## Install\n\n```bash\nnpm install @danecodes/roku-screenshot\n```\n\n## CLI\n\n```bash\n# Basic capture\nroku-screenshot -d 192.168.0.30 -o screen.png\n\n# Auto-discover device on network\nroku-screenshot -o screen.png\n\n# Resize to 50%\nroku-screenshot -d 192.168.0.30 --resize 50 -o thumb.png\n\n# Resize to specific width\nroku-screenshot -d 192.168.0.30 --resize 960 -o half.png\n\n# Crop a region (left, top, width, height)\nroku-screenshot -d 192.168.0.30 --crop 0,0,960,540 -o top-left.png\n\n# Convert to JPEG\nroku-screenshot -d 192.168.0.30 -o screen.jpg\n\n# Visual regression diff\nroku-screenshot -d 192.168.0.30 --diff baseline.png -o changes.png\n# exits 0 if identical, 1 if changed\n\n# Watch mode — capture every 5 seconds\nroku-screenshot -d 192.168.0.30 --watch 5 -o captures/screen.png\n# creates captures/screen-001.png, screen-002.png, ...\n```\n\nSet `ROKU_IP` environment variable to skip `--device` every time.\n\n## Library\n\n```typescript\nimport { capture, diff, processImage, watch } from '@danecodes/roku-screenshot';\nimport { EcpClient } from '@danecodes/roku-ecp';\n\nconst roku = new EcpClient('192.168.0.30');\n\n// Basic capture\nconst png = await capture(roku);\n\n// Capture with processing\nconst thumb = await capture(roku, {\n  resize: 50,        // 50% scale\n  format: 'jpeg',\n  quality: 85,\n});\n\n// Crop\nconst cropped = await capture(roku, {\n  crop: { left: 0, top: 0, width: 960, height: 540 },\n});\n\n// Visual regression diff\nconst before = await capture(roku);\n// ... do something on the Roku ...\nconst after = await capture(roku);\n\nconst result = await diff(before, after);\nconsole.log(result.identical);      // false\nconsole.log(result.changePercent);  // 12.5\nconsole.log(result.changedPixels);  // 259200\n\n// Save the diff image (changed pixels highlighted in red)\nawait writeFile('diff.png', result.image);\n\n// Watch mode\nconst ac = new AbortController();\nawait watch(roku, 5000, async (image, seq) => {\n  await writeFile(`frame-${seq}.png`, image);\n}, { signal: ac.signal });\n```\n\n## API\n\n### `capture(client, options?)`\n\nCapture a screenshot and optionally process it. Returns a `Buffer`.\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `resize` | `number` | Percentage (1-100) or pixel width (>100) |\n| `crop` | `{ left, top, width, height }` | Crop region |\n| `format` | `'png' \\| 'jpeg' \\| 'webp'` | Output format (default: png) |\n| `quality` | `number` | JPEG/WebP quality 1-100 (default: 90) |\n\n### `diff(imageA, imageB, options?)`\n\nPixel diff two images. Returns a `DiffResult`.\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `threshold` | `number` | Per-channel tolerance 0-255 (default: 25) |\n| `highlightColor` | `[r, g, b, a]` | Color for changed pixels (default: red) |\n\n```typescript\ninterface DiffResult {\n  image: Buffer;          // PNG with changes highlighted\n  changedPixels: number;\n  totalPixels: number;\n  changePercent: number;  // 0-100\n  identical: boolean;\n}\n```\n\n### `watch(client, intervalMs, callback, options?)`\n\nCapture screenshots on a loop. Supports `AbortSignal` for cancellation.\n\n### `processImage(buffer, options?)`\n\nProcess an existing image buffer (same options as `capture`).\n\n## Requirements\n\n- Roku device in developer mode with a sideloaded channel\n- Node.js 18+\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-f7e7f9f2aebe337f2b7641da21e4e4e8"}