{"_id":"@recappi/sdk","_rev":"4-ef969e28cad438a04f27a8a1ffdbd627","name":"@recappi/sdk","dist-tags":{"latest":"1.2.0"},"versions":{"0.0.0":{"name":"@recappi/sdk","version":"0.0.0","keywords":["napi-rs","audio","recording"],"license":"MIT","_id":"@recappi/sdk@0.0.0","maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"homepage":"https://github.com/Recappi/sdk#readme","bugs":{"url":"https://github.com/Recappi/sdk/issues"},"ava":{"timeout":"2m","extensions":{"ts":"module"},"nodeArguments":["--import","@oxc-node/core/register"],"workerThreads":false,"environmentVariables":{"OXC_TSCONFIG_PATH":"./__test__/tsconfig.json"}},"dist":{"shasum":"b5874cc5b7534044074339eb608f082da5deefcc","tarball":"https://registry.npmjs.org/@recappi/sdk/-/sdk-0.0.0.tgz","fileCount":6,"integrity":"sha512-SoniI9x8L7bOB26/LtteQqEEhEitxiS0xOnwkQ8+SGywpD+tRwmt2sTYTQYl7tqjg6xe6+YikBPmjAbYw6jFGg==","signatures":[{"sig":"MEYCIQDNPJ8d2nCIdYk198oHAVw65jVWQkV3+ECZDVHaT5wbhQIhAKr0Z1w/GNbwwBNZ208n92pKr1JSKI/0aRRV2dM8HdRk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31270},"main":"index.cjs","napi":{"targets":["aarch64-apple-darwin","x86_64-apple-darwin","x86_64-pc-windows-msvc","i686-pc-windows-msvc","aarch64-pc-windows-msvc"],"binaryName":"recording"},"type":"module","types":"./index.d.cts","engines":{"node":">= 10"},"exports":{".":"./index.cjs","./encode-wav":{"types":"./dist/encode-wav.d.ts","default":"./dist/encode-wav.js"}},"gitHead":"a4b581c2ef350984b30ce6d796a5f230bc9b6660","scripts":{"lint":"oxlint .","test":"ava","bench":"node --import @oxc-node/core/register benchmark/bench.ts","build":"napi build --platform --release --js index.cjs --dts index.d.cts","format":"run-p format:js format:rs format:toml","prepare":"husky","version":"napi version","build:ts":"tsc","artifacts":"napi artifacts","format:js":"oxfmt .","format:rs":"cargo fmt","preversion":"napi build --platform && git add .","build:debug":"napi build --platform --js index.cjs --dts index.d.cts","format:toml":"taplo format","prepublishOnly":"napi prepublish -t npm"},"_npmUser":{"name":"broooooklyn","email":"lynweklm@gmail.com"},"repository":{"url":"git+ssh://git@github.com/Recappi/sdk.git","type":"git"},"workspaces":["./playground"],"_npmVersion":"11.6.0","description":"Cross platform audio capture SDK","directories":{},"lint-staged":{"*.toml":["taplo format"],"*.@(js|ts|tsx)":["oxlint --fix"],"*.@(js|ts|tsx|yml|yaml|md|json)":["prettier --write"]},"_nodeVersion":"24.10.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"yarn@4.11.0","devDependencies":{"ava":"^6.4.1","husky":"^9.1.7","oxfmt":"^0.13.0","oxlint":"^1.28.0","tinybench":"^5.1.0","@taplo/cli":"^0.7.0","typescript":"^5.9.3","@types/node":"^24.10.1","lint-staged":"^16.2.6","@napi-rs/cli":"^3.4.1","npm-run-all2":"^8.0.4","@oxc-node/core":"^0.0.34"},"optionalDependencies":{"@recappi/sdk-darwin-x64":"0.0.0","@recappi/sdk-darwin-arm64":"0.0.0","@recappi/sdk-win32-x64-msvc":"0.0.0","@recappi/sdk-win32-ia32-msvc":"0.0.0","@recappi/sdk-win32-arm64-msvc":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.0.0_1763048960005_0.36318115377043303","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@recappi/sdk","version":"1.0.0","keywords":["napi-rs","audio","recording"],"license":"MIT","_id":"@recappi/sdk@1.0.0","maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"homepage":"https://github.com/Recappi/sdk#readme","bugs":{"url":"https://github.com/Recappi/sdk/issues"},"ava":{"timeout":"2m","extensions":{"ts":"module"},"nodeArguments":["--import","@oxc-node/core/register"],"workerThreads":false,"environmentVariables":{"OXC_TSCONFIG_PATH":"./__test__/tsconfig.json"}},"dist":{"shasum":"0dfa6c02c5c90cb5a36508d7a6a6ed09fed9a51c","tarball":"https://registry.npmjs.org/@recappi/sdk/-/sdk-1.0.0.tgz","fileCount":4,"integrity":"sha512-ud7k5y+dQ0FNphs7wM3tMBTZNCVMtnph3GSXZC+YXDyACO60TNA697Fp6hanB+etxl5q6w6VMm/XevUTUuV4MQ==","signatures":[{"sig":"MEUCIQDn3d/IOXJNAHSyw9BnrXWRrHUZGgop1IoiL1K+FJgslQIgdOSQZhEpNWZm+uBVCieXxxRQKi43LT/ZQ5BrUofJa08=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@recappi%2fsdk@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":32283},"main":"index.cjs","napi":{"targets":["aarch64-apple-darwin","x86_64-apple-darwin","x86_64-pc-windows-msvc","i686-pc-windows-msvc","aarch64-pc-windows-msvc"],"binaryName":"recording"},"type":"module","types":"./index.d.cts","engines":{"node":">= 10"},"exports":{".":"./index.cjs","./encode-wav":{"types":"./dist/encode-wav.d.ts","default":"./dist/encode-wav.js"}},"gitHead":"4012aaabea4e1acda30d095d575a431f0008b835","scripts":{"lint":"oxlint .","test":"ava","bench":"node --import @oxc-node/core/register benchmark/bench.ts","build":"napi build --platform --release --js index.cjs --dts index.d.cts","format":"run-p format:js format:rs format:toml","prepare":"husky","version":"napi version","build:ts":"tsc","artifacts":"napi artifacts","format:js":"oxfmt .","format:rs":"cargo fmt","preversion":"napi build --platform && git add .","build:debug":"napi build --platform --js index.cjs --dts index.d.cts","format:toml":"taplo format","prepublishOnly":"napi prepublish -t npm"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ed2cbbc0-f129-48b6-9384-f546e0447c6a"}},"repository":{"url":"git+ssh://git@github.com/Recappi/sdk.git","type":"git"},"workspaces":["./playground"],"_npmVersion":"11.6.2","description":"Cross platform audio capture SDK","directories":{},"lint-staged":{"*.toml":["taplo format"],"*.@(js|ts|tsx)":["oxlint --fix","oxfmt"],"*.@(yml|yaml|md|json)":["prettier --write"]},"_nodeVersion":"24.11.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"yarn@4.11.0","devDependencies":{"ava":"^6.4.1","husky":"^9.1.7","oxfmt":"^0.13.0","oxlint":"^1.28.0","prettier":"^3.6.2","tinybench":"^5.1.0","@taplo/cli":"^0.7.0","typescript":"^5.9.3","@types/node":"^24.10.1","lint-staged":"^16.2.6","@napi-rs/cli":"^3.4.1","npm-run-all2":"^8.0.4","@oxc-node/core":"^0.0.34"},"optionalDependencies":{"@recappi/sdk-darwin-x64":"1.0.0","@recappi/sdk-darwin-arm64":"1.0.0","@recappi/sdk-win32-x64-msvc":"1.0.0","@recappi/sdk-win32-ia32-msvc":"1.0.0","@recappi/sdk-win32-arm64-msvc":"1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.0_1763050538361_0.9853061347127692","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@recappi/sdk","version":"1.1.0","keywords":["audio","napi-rs","recording"],"license":"MIT","_id":"@recappi/sdk@1.1.0","maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"homepage":"https://github.com/Recappi/sdk#readme","bugs":{"url":"https://github.com/Recappi/sdk/issues"},"ava":{"timeout":"2m","extensions":{"ts":"module"},"nodeArguments":["--import","@oxc-node/core/register"],"workerThreads":false,"environmentVariables":{"OXC_TSCONFIG_PATH":"./__test__/tsconfig.json"}},"dist":{"shasum":"47fc9e43768e83e5eeb370111a4e6c430851b704","tarball":"https://registry.npmjs.org/@recappi/sdk/-/sdk-1.1.0.tgz","fileCount":4,"integrity":"sha512-cb9qIT1RSSJQuns6OoJG2bhee6Zgrgx+A0dWim7s42oD0waT5FFqPdezOJHJ0VbqyQwljENaKIf2Ew8uODLerA==","signatures":[{"sig":"MEQCIDNxW6cz+Rkx5yETBM77tSA4452Z2eIfxO3U//aqv+jLAiA97WJbB4I3OlhCop52NWCQSxixeYJmEP56CNnHt7prCQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@recappi%2fsdk@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":30451},"main":"index.cjs","napi":{"targets":["aarch64-apple-darwin","x86_64-apple-darwin","x86_64-pc-windows-msvc","i686-pc-windows-msvc","aarch64-pc-windows-msvc"],"binaryName":"recording"},"type":"module","types":"./index.d.cts","engines":{"node":">= 20.19.0"},"exports":{".":"./index.cjs","./encode-wav":{"types":"./dist/encode-wav.d.ts","default":"./dist/encode-wav.js"}},"gitHead":"fcfb1661a8dd9f46468eee2ce6cfe3bb9f4bf35d","scripts":{"lint":"vp lint .","test":"ava","bench":"node --import @oxc-node/core/register benchmark/bench.ts","build":"napi build --platform --release --js index.cjs --dts index.d.cts","format":"run-p format:js format:rs format:toml","prepare":"vp config","version":"napi version","build:ts":"tsc","artifacts":"napi artifacts","format:js":"vp fmt .","format:rs":"cargo fmt","preversion":"yarn build:debug && git add .","build:debug":"napi build --platform --js index.cjs --dts index.d.cts","format:toml":"taplo format","prepublishOnly":"napi prepublish -t npm"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ed2cbbc0-f129-48b6-9384-f546e0447c6a"}},"repository":{"url":"git+ssh://git@github.com/Recappi/sdk.git","type":"git"},"workspaces":["./playground"],"_npmVersion":"11.11.1","description":"Cross platform audio capture SDK","directories":{},"resolutions":{"vite":"npm:@voidzero-dev/vite-plus-core@latest","vitest":"npm:@voidzero-dev/vite-plus-test@latest"},"_nodeVersion":"24.14.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"yarn@4.12.0","devDependencies":{"ava":"^7.0.0","prettier":"^3.8.1","tinybench":"^6.0.0","vite-plus":"catalog:","typescript":"^5.9.3","@types/node":"^25.5.0","@napi-rs/cli":"^3.5.1","npm-run-all2":"^8.0.4","@oxc-node/core":"^0.0.35","oxlint-tsgolint":"^0.17.0"},"optionalDependencies":{"@recappi/sdk-darwin-x64":"1.1.0","@recappi/sdk-darwin-arm64":"1.1.0","@recappi/sdk-win32-x64-msvc":"1.1.0","@recappi/sdk-win32-ia32-msvc":"1.1.0","@recappi/sdk-win32-arm64-msvc":"1.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.1.0_1773845912647_0.19773385019993306","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@recappi/sdk","version":"1.2.0","description":"Cross platform audio capture SDK","keywords":["audio","napi-rs","recording"],"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/Recappi/sdk.git"},"workspaces":["./playground"],"type":"module","main":"index.cjs","types":"./index.d.cts","exports":{".":"./index.cjs","./encode-wav":{"default":"./dist/encode-wav.js","types":"./dist/encode-wav.d.ts"}},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"artifacts":"napi artifacts","bench":"node --import @oxc-node/core/register benchmark/bench.ts","build":"napi build --platform --release --js index.cjs --dts index.d.cts","build:debug":"napi build --platform --js index.cjs --dts index.d.cts","build:ts":"tsc","format":"run-p format:js format:rs format:toml","format:js":"vp fmt .","format:toml":"taplo format","format:rs":"cargo fmt","lint":"vp lint .","prepublishOnly":"napi prepublish -t npm","test":"ava","preversion":"yarn build:debug && git add .","version":"napi version","prepare":"vp config"},"devDependencies":{"@napi-rs/cli":"^3.5.1","@oxc-node/core":"^0.0.35","@types/node":"^25.5.0","ava":"^7.0.0","npm-run-all2":"^8.0.4","oxlint-tsgolint":"^0.18.0","prettier":"^3.8.1","tinybench":"^6.0.0","typescript":"^6.0.0","vite-plus":"catalog:"},"resolutions":{"vite":"npm:@voidzero-dev/vite-plus-core@latest","vitest":"npm:@voidzero-dev/vite-plus-test@latest"},"napi":{"binaryName":"recording","targets":["aarch64-apple-darwin","x86_64-apple-darwin","x86_64-pc-windows-msvc","i686-pc-windows-msvc","aarch64-pc-windows-msvc","x86_64-unknown-linux-gnu"]},"ava":{"environmentVariables":{"OXC_TSCONFIG_PATH":"./__test__/tsconfig.json"},"extensions":{"ts":"module"},"nodeArguments":["--import","@oxc-node/core/register"],"timeout":"2m","workerThreads":false},"engines":{"node":">= 20.19.0"},"packageManager":"yarn@4.13.0","optionalDependencies":{"@recappi/sdk-darwin-arm64":"1.2.0","@recappi/sdk-darwin-x64":"1.2.0","@recappi/sdk-win32-x64-msvc":"1.2.0","@recappi/sdk-win32-ia32-msvc":"1.2.0","@recappi/sdk-win32-arm64-msvc":"1.2.0","@recappi/sdk-linux-x64-gnu":"1.2.0"},"gitHead":"cfc14f31a12367f3a1b7dc0c020df56f2d7235ef","_id":"@recappi/sdk@1.2.0","bugs":{"url":"https://github.com/Recappi/sdk/issues"},"homepage":"https://github.com/Recappi/sdk#readme","_nodeVersion":"24.14.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-i7zvcpFrBM0UtHQps2WummGLqtCRF6Q1c4cb10TGnN6ZzcsIIyj0/8aQ7eOm6w4SWJvpnrZRbbvUjwM++GOt9g==","shasum":"829ada94e49bd65caf1f445ce75577d0bed701da","tarball":"https://registry.npmjs.org/@recappi/sdk/-/sdk-1.2.0.tgz","fileCount":5,"unpackedSize":35755,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@recappi%2fsdk@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDAQ5g1o3oQNcb45sLcaegFuqaXP2gGeeQPvoT+4SY/lAiEA8vrL0wixD392m/mS7FoIcClQt+lscSfMxoxcBxje9Mk="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ed2cbbc0-f129-48b6-9384-f546e0447c6a"}},"directories":{},"maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_1.2.0_1774949511215_0.46842835828192797"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-13T15:49:19.914Z","modified":"2026-03-31T09:31:51.669Z","0.0.0":"2025-11-13T15:49:20.189Z","1.0.0":"2025-11-13T16:15:38.543Z","1.1.0":"2026-03-18T14:58:32.806Z","1.2.0":"2026-03-31T09:31:51.354Z"},"bugs":{"url":"https://github.com/Recappi/sdk/issues"},"license":"MIT","homepage":"https://github.com/Recappi/sdk#readme","keywords":["audio","napi-rs","recording"],"repository":{"type":"git","url":"git+ssh://git@github.com/Recappi/sdk.git"},"description":"Cross platform audio capture SDK","maintainers":[{"name":"broooooklyn","email":"lynweklm@gmail.com"}],"readme":"# `@recappi/sdk`\n\n[![CI](https://github.com/Recappi/sdk/actions/workflows/CI.yml/badge.svg)](https://github.com/Recappi/sdk/actions/workflows/CI.yml)\n\n## Platform support\n\n| Feature                                       | macOS | Windows | Linux (x64 GNU)                    |\n| --------------------------------------------- | ----- | ------- | ---------------------------------- |\n| `decodeAudio` / `decodeAudioSync`             | Yes   | Yes     | Yes                                |\n| `ShareableContent.applications()`             | Yes   | Yes     | Yes                                |\n| `ShareableContent.applicationWithProcessId()` | Yes   | Yes     | Yes                                |\n| `ShareableContent.onApplicationListChanged()` | Yes   | Yes     | Yes (polling)                      |\n| `ShareableContent.isUsingMicrophone()`        | Yes   | Yes     | Yes (PulseAudio)                   |\n| `ShareableContent.onAppStateChanged()`        | Yes   | Yes     | Yes (polling)                      |\n| `ShareableContent.tapGlobalAudio()`           | Yes   | Yes     | Yes (PulseAudio monitor)           |\n| `ShareableContent.tapAudio()`                 | Yes   | Yes     | Yes (dedicated Pulse sink reroute) |\n\nPublished Linux artifacts currently target `x86_64-unknown-linux-gnu`. The\nLinux implementation ships the same top-level `ShareableContent` surface as\nmacOS and Windows, but it uses a PulseAudio-compatible userspace and shells out\nto `pactl` / `ffmpeg`, so capture requires those tools to be available at\nruntime.\n\nIf your application needs to choose a Linux fallback backend dynamically, use\n`getPlatformCapabilities()` instead of hard-coding platform checks. On Linux,\nthose booleans reflect the currently reachable runtime prerequisites for each\ncapture path, not just whether the functions are exported.\n\n```typescript\nimport { getPlatformCapabilities } from '@recappi/sdk'\n\nconst capabilities = getPlatformCapabilities()\n\nif (capabilities.tapGlobalAudio) {\n  console.log('Use Recappi for realtime capture')\n} else {\n  console.log('Use your Linux-specific fallback backend')\n}\n```\n\n## Usage\n\n### Recording system audio\n\n> Available on macOS, Windows, and Linux. Linux capture requires a\n> PulseAudio-compatible server plus `pactl` and `ffmpeg`.\n\nBoth input and output devices are recording, mixed into a single audio stream.\n\n```typescript\nimport { writeFile } from 'node:fs/promises'\nimport { setTimeout } from 'node:timers/promises'\n\nimport { ShareableContent } from '@recappi/sdk'\nimport { createWavBuffer } from '@recappi/sdk/encode-wav'\n\nconst WavBuffers = []\n\nlet totalLength = 0\n\nconst session = ShareableContent.tapGlobalAudio([], (err, samples) => {\n  if (err) {\n    console.error('Error capturing audio:', err)\n    return\n  }\n  WavBuffers.push(samples)\n  totalLength += samples.length\n})\n\nconsole.info('Recording audio for 5 seconds...')\n\nawait setTimeout(5000) // Record for 5 seconds\n\nsession.stop()\n\nconsole.info(`Recording stopped. Writing ${totalLength} samples to output.wav...`)\n\nconst { buf: contactedBuffer } = WavBuffers.reduce(\n  ({ buf, offset }, cur) => {\n    buf.set(cur, offset)\n    return {\n      buf,\n      offset: offset + cur.length,\n    }\n  },\n  {\n    buf: new Float32Array(totalLength),\n    offset: 0,\n  },\n)\n\nconsole.log(`Creating WAV buffer ...`)\n\nconst wavBuffer = Buffer.from(\n  createWavBuffer(contactedBuffer, {\n    sampleRate: session.sampleRate,\n    numChannels: session.channels,\n  }),\n)\n\nawait writeFile('output.wav', wavBuffer)\n```\n\n### Listing running applications\n\n> Available on macOS, Windows, and Linux.\n\n```typescript\nimport { ShareableContent } from '@recappi/sdk'\n\nconst apps = ShareableContent.applications()\n\nfor (const app of apps) {\n  console.log(`Name: ${app.name}, PID: ${app.processId}`)\n}\n```\n\n### Recording specific application\n\n> Available on macOS, Windows, and Linux.\n> On Windows, `tapAudio()` currently uses the same capture backend as\n> `tapGlobalAudio()` and does not isolate a single process stream yet.\n> On Linux, `tapAudio()` reroutes matching Pulse sink-inputs into a dedicated\n> capture sink and records that sink's monitor. This is best-effort and depends\n> on the target application exposing movable Pulse streams.\n\n```typescript\nimport { ShareableContent } from '@recappi/sdk'\n\nconst apps = ShareableContent.applications()\nconst musicApp = apps.find((app) => app.name === 'Music')\n\nif (musicApp) {\n  const session = ShareableContent.tapAudio(musicApp.processId, (err, samples) => {\n    if (err) {\n      console.error('Error capturing audio:', err)\n      return\n    }\n    // Process samples...\n  })\n\n  // Stop recording after 5 seconds\n  setTimeout(() => {\n    session.stop()\n  }, 5000)\n}\n```\n\n## Playground\n\n```sh\nyarn install\nyarn build\nyarn workspace playground dev:server\nyarn workspace playground dev:web\n```\n\n## Local Linux Iteration From macOS\n\nUse the bundled Docker environment to exercise the Linux backend locally from a\nmacOS workstation.\n\n```sh\nbash ./scripts/test-linux-docker.sh\n```\n\nIf you want an interactive shell inside the same Linux image:\n\n```sh\nbash ./scripts/docker-linux.sh bash\n```\n\nThe Docker image installs Rust, Node.js, PulseAudio, `pactl`, and `ffmpeg`, so\nthe Linux binding tests can run without depending on the host machine.\n","readmeFilename":"README.md"}