npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@recordem/desktop-sdk

v0.1.2

Published

Record calls from your Electron or Node app: call detection, capture, local transcription and upload to Recordem

Readme

@recordem/desktop-sdk

Record calls from your Electron or Node app with Recordem. The SDK runs the Recordem engine next to your app: it notices calls (Google Meet, Zoom, Teams, Webex, in the browser or their apps), records the microphone and the call's audio apart, reads who is in the call and who speaks, transcribes on the computer, and sends everything to Recordem. Your backend gets the transcript, the audio and notes by webhook.

macOS on Apple silicon (14.4+). The engine is downloaded on install (bin/recordem-desktop), checked against the SHA-256 in engine.json.

How it fits

  1. Your backend creates the recording with its Recordem API key, and asks for an upload token: POST /v1/recordings with { id, ref: "interview:123", upload: true } (or @recordem/sdk). The token is good for that one recording, for 6 hours.
  2. Your desktop app gives the engine that token. It never sees your API key.
  3. Your backend hears transcript.final, recording.uploaded and notes.ready by webhook, and reads them with @recordem/sdk.

Electron

import { app } from "electron";
import sdk from "@recordem/desktop-sdk";

await sdk.init({ apiUrl: "https://api.recordem.app", dataDir: app.getPath("userData") });

sdk.addEventListener("meeting-detected", async ({ window }) => {
  // Ask your backend for a recording of this call (it creates it with upload: true).
  const { uploadToken } = await fetch("https://your.app/interviews/123/recording", { method: "POST" }).then((r) => r.json());
  await sdk.startRecording({ windowId: window.id, uploadToken });
});

sdk.addEventListener("realtime-event", ({ event, data }) => {
  if (event === "transcript.data") console.log(`${data.name ?? data.speaker}: ${data.text}`);
});

sdk.addEventListener("upload-status", ({ recordingId, status }) => console.log(recordingId, status));

The engine has to sit outside the asar archive: with electron-builder, asarUnpack: ["**/@recordem/desktop-sdk/bin/**"]. Sign it with your app (it records in your app's name: macOS asks your users for the microphone, system audio and accessibility permissions as your app). Your Info.plist needs NSMicrophoneUsageDescription and NSAudioCaptureUsageDescription.

API

| Method | | | --- | --- | | init({ apiUrl, dataDir, languages?, live?, micDevice?, … }) | starts the engine; resolves { modelsReady, pending } | | downloadModels() | the speech models, once (~575 MB); progress as model-download | | startRecording({ windowId, uploadToken }) | resolves the recording id | | startRecording({ windowId, recordingId }), then setUploadToken({ recordingId, uploadToken }) | start before your backend answers | | stopRecording, pauseRecording, resumeRecording ({ windowId }) | | | prepareDesktopAudioRecording() | a window to record with no call (in person) | | permissions(), requestPermission(p), openPermissionSettings(p) | microphone, system-audio, accessibility, automation | | setMuted(muted), listDevices(), pending(), configure(…), shutdown() | |

Events: meeting-detected, meeting-updated, meeting-closed, recording-started, recording-ended, upload-status (transcribing, uploading, done, failed, waiting for a token), realtime-event (transcript.data, participants.update, speaker.on), permission-status, mute-status, model-download, error, log, shutdown. If the engine exits on its own it is started again with the same init.

A recording that couldn't be sent stays on the computer and is resumed at the next init; one whose token expired comes back as upload-status waiting: get a fresh token (create the recording again with the same id) and call setUploadToken.

RECORDEM_DESKTOP_PATH points the SDK at an engine of your own (development), and skips the download.

The same engine has a Rust client for Tauri apps: the recordem-desktop crate.

MIT