Desktop SDK (Beta)

🚧

API under construction

This document refers to API endpoints which are not publicly listed in our API specification. We are working on this and they will be added soon. You can assume the examples below will work and the API's will updated with backwards-compatibility in mind.

The Desktop SDK allows for recording Zoom calls locally on Apple Silicon Macs, within an Electron application.

The lifecycle of a Desktop SDK recording is as follows:

  1. The Desktop SDK notifies your code that a Zoom meeting has started locally.
  2. Your code makes a request to your backend for an upload token.
  3. Your backend creates a new Desktop SDK Upload using the Recall.ai API, and returns the upload token to your desktop application.
  4. Your desktop code calls startRecording with the upload token.
  5. Once the meeting is over, call uploadRecording.
  6. Wait for the sdk_upload.completed webhook
  7. Run async transcription (optional)
  8. Download the recording video and transcription

That's it! Once the call finishes, a recording will be created on the Recall API and your backend will be notified via webhook.

Installation

npm install @recallai/desktop-sdk

Usage

init(config)

RecallAiSdk.init({
  api_url: "http://us-east-1.recall.ai"
});

Initialize the Desktop SDK. This should be called once at startup. Specify the api_url for your region.

addEventListener(eventType, listener)

RecallAiSdk.addEventListener("meeting-detected", async (evt) => {
  const {window: {id: id}} = evt;
});

RecallAiSdk.addEventListener("sdk-state-change", async (evt) => {
  const {sdk: {state: { code: code }}} = evt;
  // code is either "recording" or "idle"
});

RecallAiSdk.addEventListener('recording-ended', async (evt) => {
  const {window: {id: id}} = evt;
});

RecallAiSdk.addEventListener('meeting-closed', async (evt) => {
  const {window: {id: id}} = evt;
});

RecallAiSdk.addEventListener('upload-progress', async (evt) => {
  const {
    window: {id: id},
    progress: progress
  } = evt;
  // Progress is a number from 0-100 representing upload completion
});

Install an event listener for eventType events. eventType can be one of:

  • meeting-detected: Triggered when a Zoom meeting is found, either when a new one starts, or after the SDK initializes and there is a meeting already in progress.
  • sdk-state-change: Triggered when the in-progress recording changes state, either to "idle" to indicate that recording is over, or "recording" to indicate that a recording is in progress.
  • recording-ended: Triggered when a recording has stopped, due to the meeting ending, or calling stopRecording.
  • meeting-closed: Triggered when a detected meeting has ended.
  • upload-progress: Triggered to notify your code of the state of a video upload. progress is a number from 0 to 100 representing upload completion.

startRecording({windowId, uploadToken})

RecallAiSdk.startRecording({
  windowId: ...,
  uploadToken: ...
});

Begin recording. This function is usually called inside an event listener for meeting-detected. windowId is provided by the meeting-detected callback, and uploadToken is acquired by creating an SDK Upload on your backend.

stopRecording({windowId})

RecallAiSdk.stopRecording({
  windowId: ...,
});

Stop recording. This function can be called to end a recording before the meeting itself has naturally ended.

uploadRecording({windowId})

RecallAiSdk.uploadRecording({
  windowId: ...
});

Initiate the upload of a recording. This function should be called only after a recording has completed, usually in a recording-ended callback.

Creating an SDK upload

Endpoint

curl --request POST \
     --url https://us-east-1.recall.ai/api/v1/sdk-upload/ \
     --header 'Authorization: Token your-recall-api-token' \
     --header 'content-type: application/json' \
     --data '{ "artifacts": { "video_mixed_mp4": {} } }'

Response

{
   "id": "4abf29fc-36b5-4853-9f84-a9990b9e354b",
   "upload_token": "96472e47-a78c-4774-a9a2-93afad7d398d"
}

Example

An example demonstrating how to use these functions together could be:

RecallAiSdk.init({
  api_url: "http://us-east-1.recall.ai"
});

RecallSdk.addEventListener('meeting-detected', async (evt) => {
  const res = await Backend.fetch(`/api/create_sdk_recording`, AppState.client_token);
  const payload = await res.json();
	
  await RecallSdk.startRecording({
    windowId: evt.window.id,
    uploadToken: res.upload_token
  });
});

RecallSdk.addEventListener('sdk-state-change', async (evt) => {
  switch (evt.sdk.state.code) {
    case 'recording':
      console.log("SDK is recording");
      break;
    case 'idle':
      console.log("SDK is idle");
      break;
  }
});

RecallAiSdk.addEventListener('recording-ended', async (evt) => {
  RecallAiSdk.uploadRecording({ windowId: evt.window.id });
});

RecallAiSdk.addEventListener('upload-progress', async (evt) => {
  console.log(`Uploaded ${evt.progress}%`);
});

Webhooks

At points in the lifecycle of a Desktop SDK Upload, you will receive webhook notifications about the state of the upload.

sdk_upload.completed

This webhook is sent when an SDK Upload has finished successfully.

{
  "data": {
    "sdk_upload": {
      "created_at": "2024-10-18T15:12:01.032224Z",
      "id": "6a98c97a-3e6e-4acd-8684-0b2ddeeb8281",
      "recording_id": "71f4d556-4c8c-4627-a253-61344e8f22f7",,
      "status": {
        "code": "complete"
      }
    }
  },
  "event": "sdk_upload.completed"
}

sdk_upload.failed

This webhook is sent when an SDK Upload has finished unsuccessfully.

{
  "data": {
    "sdk_upload": {
      "created_at": "2024-10-18T15:12:01.032224Z",
      "id": "6a98c97a-3e6e-4acd-8684-0b2ddeeb8281",
      "recording_id": null,
      "status": {
        "code": "failed"
      }
    }
  },
  "event": "sdk_upload.failed"
}

Running transcription

After receiving the sdk_upload.completed webhook you can retrieve the recorded video file using create transcript artifact endpoint with the recording_id field from the webhook:

Endpoint

curl --request POST \
     --url https://us-east-1.recall.ai/api/v1/recording/71f4d556-4c8c-4627-a253-61344e8f22f7/create_transcript \
     --header 'Authorization: Token your-recall-api-token' \
     --header 'content-type: application/json' \
     --data '{
        "provider": {
            "assembly_ai_async": {
                "language_code": "en",
                "speaker_labels": True,
                "diarization": True
            }
        },
        "diarization": {
            "algorithm_priority": ["speaker_timeline"]
        }
    }'

Response

{
  "id": "642a12e1-c542-4c27-80be-ea67f41d3196,
  "status": {
    "code": "processing"
  }
}

Retrieve the recording & transcript

After receiving the sdk-upload.completed webhook you can retrieve the recorded video file using retrieve recording endpoint with the recording_id field from the webhook:

Endpoint

curl --request GET \
     --url https://us-east-1.recall.ai/api/v1/recording/71f4d556-4c8c-4627-a253-61344e8f22f7 \
     --header 'Authorization: Token your-recall-api-token' \
     --header 'content-type: application/json' 

Response

{
  "id": "71f4d556-4c8c-4627-a253-61344e8f22f7",
  "shortcuts": {
    "video_mixed": {
      "status": {
        "code": "done"
      },
      "data": {
        "download_url": "https://some-download-endpoint",
      }
    },
    "transcript": {
      "status": {
        "code": "done"
      },
      "data": {
        "download_url": "https://some-download-endpoint",
      }
    }
  }
}