A ToDesktop plugin that integrates with Recall.ai's Desktop Recording SDK to enable automatic meeting recording for Zoom, Google Meet, and Microsoft Teams.
This plugin provides a complete integration between ToDesktop and the Recall.ai Desktop Recording SDK, offering:
- Automatic meeting detection for Zoom, Google Meet, Microsoft Teams, and Slack
- Recording management with start, stop, pause, and resume functionality
- Desktop audio recording for non-meeting scenarios
- Real-time events including transcription and participant data
- Permission management for accessibility, screen capture, and microphone access
- Upload progress tracking and webhook integration
- Type-safe client library for web applications
Check out the tutorial for a step-by-step guide on how to use the Recall desktop plugin and client SDK.
- Recall.ai Account: Sign up at recall.ai and get your API key
- ToDesktop Builder App: Create a ToDesktop application
- Backend Integration: Set up webhook endpoints and upload token generation
npm install @todesktop/client-recall- Open ToDesktop Builder
- Install the recall desktop sdk plugin
In ToDesktop Builder, configure the following preferences:
- API URL: Your Recall.ai region URL (e.g.,
https://us-east-1.recall.ai) - Enable Plugin: Toggle to enable/disable recording functionality
- Request permissions on startup: Automatically request required permissions
import { recallDesktop } from "@todesktop/client-recall";
// Initialize the SDK
await recallDesktop.initSdk();
// Listen for meeting detection
const stopMeetingListener = recallDesktop.addEventListener(
"meeting-detected",
async ({ window }) => {
console.log("Meeting detected:", window);
// Get upload token from your backend
const uploadToken = await getUploadTokenFromBackend();
// Start recording
const result = await recallDesktop.startRecording(window.id, uploadToken);
if (result.success) {
console.log("Recording started successfully");
}
}
);
// Listen for recording events
const stopStateListener = recallDesktop.addEventListener(
"sdk-state-change",
({ sdk }) => {
console.log("Recording state:", sdk.state.code);
}
);
const stopUploadListener = recallDesktop.addEventListener(
"upload-progress",
({ progress }) => {
console.log(`Upload progress: ${progress}%`);
}
);
// Handle recording completion
const stopRecordingListener = recallDesktop.addEventListener(
"recording-ended",
async ({ window }) => {
console.log("Recording ended for window:", window.id);
// Upload the recording
await recallDesktop.uploadRecording(window.id);
}
);
// Later, remove listeners when no longer needed
stopMeetingListener();
stopStateListener();
stopUploadListener();
stopRecordingListener();For capturing audio from applications other than supported meeting platforms:
// Prepare desktop audio recording
const { data } = await recallDesktop.prepareDesktopAudioRecording();
const { windowId } = data;
// Get upload token and start recording
const uploadToken = await getUploadTokenFromBackend();
await recallDesktop.startRecording(windowId, uploadToken);
// Stop when done
await recallDesktop.stopRecording(windowId);
await recallDesktop.uploadRecording(windowId);// Check permission status
const status = await recallDesktop.getStatus();
console.log("Permissions:", status.permissions);
// Request specific permission
await recallDesktop.requestPermission("screen-capture");
// Listen for permission changes
const removePermissionListener = recallDesktop.addEventListener(
"permission-status",
({ permission, status }) => {
console.log(`Permission ${permission}: ${status}`);
}
);
// Remove the listener when you no longer need updates
removePermissionListener();A minimal Express backend lives in packages/backend for demos. It exposes:
POST /api/create-sdk-upload– calls the Recall API and returns{ id, upload_token, recording_id }POST /webhooks/recall– logs Recall webhook payloads for inspectionGET /health– health check
Run it with your Recall token (replace the example value with the token for your workspace):
RECALL_API_TOKEN="c5a6aaff378e5dc5a7e28b3e2853eff832ce4bde" \
npm start --workspace=packages/backendThe server defaults to https://us-west-2.recall.ai; override via RECALL_API_BASE if you use another region. Set CORS_ORIGIN to restrict cross-origin access (defaults to *).
Your backend needs to create upload tokens using the Recall.ai API:
// Example backend endpoint
app.post("/api/create-upload-token", async (req, res) => {
const response = await fetch(`${RECALL_API_URL}/api/v1/sdk-upload/`, {
method: "POST",
headers: {
Authorization: `Token ${RECALL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
transcript: {
provider: {
assembly_ai_streaming: {},
},
},
}),
});
const data = await response.json();
res.json({ uploadToken: data.upload_token });
});Set up webhooks to handle recording completion:
app.post("/webhooks/recall", (req, res) => {
const { event, data } = req.body;
switch (event) {
case "sdk_upload.complete":
console.log("Recording completed:", data.recording.id);
// Process completed recording
break;
case "sdk_upload.failed":
console.log("Recording failed:", data);
// Handle failure
break;
case "sdk_upload.uploading":
console.log("Recording uploading:", data);
// Track upload progress
break;
}
res.status(200).send("OK");
});initSdk()- Initialize the Recall SDKshutdownSdk()- Shutdown the SDK and cleanupgetStatus()- Get plugin and SDK statusstartRecording(windowId, uploadToken)- Start recording a meetingstopRecording(windowId)- Stop recordingpauseRecording(windowId)- Pause recordingresumeRecording(windowId)- Resume recordinguploadRecording(windowId)- Upload completed recordingprepareDesktopAudioRecording()- Prepare desktop audio capture
Use recallDesktop.addEventListener(eventType, callback) to subscribe. Available event types include:
meeting-detected,meeting-updated,meeting-closedrecording-started,recording-ended,sdk-state-changeupload-progress,realtime-event,errorpermissions-granted,permission-statusmedia-capture-status,participant-capture-status,shutdown
setConfig(config)- Update plugin configurationgetConfig()- Get current configurationrequestPermission(permission)- Request specific permission
npm run build- Build all packagesnpm run dev- Development mode with watchnpm run test- Run testsnpm run typecheck- TypeScript type checkingnpm run clean- Clean build artifacts
-
The Electron plugin uses
@recallai/desktop-sdkdirectly; no mock setup is required. -
Before building or type-checking the client package, the
sync-sdk-typesscript copies the SDK's TypeScript declarations intopackages/client/src/generated. This runs automatically vianpm run build --workspace=@todesktop/client-recallandnpm run typecheck --workspace=@todesktop/client-recall, but you can invoke it manually with:npm run sync-sdk-types --workspace=@todesktop/client-recall