///
import { Recorder, RecorderSchemaItem } from "./Recorder.js";
import type { SystemAudioBackend, RecorderSettings, Size } from "./Recorder.js";
import { EventEmitter } from "events";
/**
* Entry point for the RecordKit SDK, an instance is available as `recordkit` that can be imported from the module. Do not instantiate this class directly.
*
* @groupDescription Discovery
* Discover the windows and devices that are available to record.
*
* @groupDescription Permissions
* Check and request the apps permission to access the recording devices.
*
* @groupDescription Logging
* Log what's going on to the console for easy debugging and troubleshooting. See the [Logging and Error Handling guide](https://recordkit.dev/guides/logging-and-errors) for more information.
*
* @groupDescription Preferred Devices
* Read and update the user's preferred devices, so you can pre-select sensible defaults in your UI.
*
* @groupDescription Window Control
* Move, resize, center and maximize windows of other applications (requires Accessibility Control permission).
*
* @groupDescription Device Control
* Configure capture devices, such as selecting a camera's active format or fetching an application's icon.
*/
export declare class RecordKit extends EventEmitter {
private ipcRecordKit;
/** @ignore */
constructor();
/**
* Initialize the RecordKit SDK.
*
* ⚠️ Must be called before calling any other RecordKit method.
*
* @param args
*/
initialize(args: {
/**
* Path to the `recordkit-rpc` binary, most of the time this should be set to `path.join(process.resourcesPath, 'recordkit-rpc')`.
*/
rpcBinaryPath: string;
/**
* Whether to fallback to the RPC binary from `node_modules` if the given path does not exist. When enabled an extra check to see if the given path exists is performed. Most of the time this should be set to `!app.isPackaged`.
*/
fallbackToNodeModules?: boolean;
/**
* Set the global log level. Defaults to `debug`.
*
* This is the same as calling `setLogLevel` right after initialization.
*/
logLevel?: LogLevel;
/** @ignore */
logRpcMessages?: boolean;
}): Promise;
/**
* Set the global log level. Defaults to `debug`.
*
* Messages with a lower level than this will be ignored and not passed to any log handlers.
*
* @group Logging
*/
setLogLevel(logLevel: LogLevel): Promise;
/**
* Overrides the global log level for a specific category. Defaults to the global log level.
*
* Messages in the given category with a lower level than this will be ignored and not passed to any log handlers.
*
* @group Logging
*/
setCategoryLogLevel(params: {
category: string;
logLevel?: LogLevel;
}): Promise;
/**
* A list of Mac displays that can be used for screen recording.
*
* @group Discovery
*/
getDisplays(): Promise;
/**
* A list of macOS windows that can be used for screen recording.
*
* @group Discovery
*/
getWindows(): Promise;
/**
* A list of cameras that are connected to the system.
*
* @param params.includeDeskView - Whether to include Desk View cameras in the results
* @group Discovery
*/
getCameras(params?: {
includeDeskView?: boolean;
}): Promise;
/**
* A list of microphones that are connected to the system.
*
* @group Discovery
*/
getMicrophones(): Promise;
/**
* A list of iOS devices that are connected to the system.
*
* @group Discovery
*/
getAppleDevices(): Promise;
/**
* A list of currently running applications that can be used for screen or audio recording.
*
* @group Discovery
*/
getRunningApplications(): Promise;
/**
* The user's preferred devices for each source type, ordered most-preferred first.
*
* RecordKit remembers which devices the user last recorded with (unless disabled via the recorder's
* `updatesUserPreferred` setting). Use this to pre-select a sensible default device in your UI.
*
* @group Preferred Devices
*/
getUserPreferred(): Promise;
/**
* Records the given microphone as the user's most-preferred microphone.
*
* Call this whenever the user manually selects a microphone, so it can be pre-selected later via
* {@link getUserPreferred}. The selection moves to the front of {@link UserPreferred.microphoneIDs}.
*
* @param microphone - The microphone to prefer, either a {@link Microphone} or its {@link Microphone.id}.
* @group Preferred Devices
*/
updatePreferredMicrophone(microphone: Microphone | string): Promise;
/**
* Records the given camera as the user's most-preferred camera.
*
* Call this whenever the user manually selects a camera, so it can be pre-selected later via
* {@link getUserPreferred}. The selection moves to the front of {@link UserPreferred.cameraIDs}.
*
* @param camera - The camera to prefer, either a {@link Camera} or its {@link Camera.id}.
* @group Preferred Devices
*/
updatePreferredCamera(camera: Camera | string): Promise;
/**
* Records the given display as the user's most-preferred display.
*
* Call this whenever the user manually selects a display, so it can be pre-selected later via
* {@link getUserPreferred}. The selection moves to the front of {@link UserPreferred.displayIDs}.
*
* @param display - The display to prefer, either a {@link Display} or its {@link Display.id}.
* @group Preferred Devices
*/
updatePreferredDisplay(display: Display | number): Promise;
/**
* Records the given Apple device as the user's most-preferred Apple device.
*
* Call this whenever the user manually selects an Apple device, so it can be pre-selected later via
* {@link getUserPreferred}. The selection moves to the front of {@link UserPreferred.appleDeviceIDs}.
*
* @param device - The Apple device to prefer, either an {@link AppleDevice} or its {@link AppleDevice.id}.
* @group Preferred Devices
*/
updatePreferredAppleDevice(device: AppleDevice | string): Promise;
/**
* Maximizes the given window, resizing it to fill the display's visible area (excluding the menu bar and Dock)
* and centering it on that display.
*
* Requires Accessibility Control permission (see {@link getAccessibilityControlAccess}).
*
* @remarks
* Rejects if the window cannot be maximized — typically because Accessibility permission is missing,
* the target display cannot be found, or the window is minimized or closed.
*
* @param window - The window to maximize, either a {@link Window} or its {@link Window.id}.
* @param options.display - The display to maximize onto, either a {@link Display} or its {@link Display.id}. Defaults to the window's current display.
* @group Window Control
*/
maximizeWindow(window: Window | number, options?: {
display?: Display | number;
}): Promise;
/**
* Resizes the given window to the given size (in points), keeping it centered on its display.
*
* Requires Accessibility Control permission (see {@link getAccessibilityControlAccess}).
*
* @remarks
* The requested size is clipped to the display's visible frame if it would be larger. After resizing,
* the window is re-centered so that a window which could not shrink/grow to the requested size still
* ends up centered. Rejects if Accessibility permission is missing, the target display cannot be found,
* or the window is minimized, closed, or does not support resizing.
*
* @param window - The window to resize, either a {@link Window} or its {@link Window.id}.
* @param size - The new size in points.
* @param options.display - The display to center on, either a {@link Display} or its {@link Display.id}. Defaults to the window's current display.
* @group Window Control
*/
resizeWindow(window: Window | number, size: Size, options?: {
display?: Display | number;
}): Promise;
/**
* Centers the given window within the visible area (excluding the menu bar and Dock) of its display,
* keeping its current size.
*
* Requires Accessibility Control permission (see {@link getAccessibilityControlAccess}).
*
* @remarks
* Rejects if Accessibility permission is missing, the target display cannot be found, or the window is
* minimized, closed, or does not support moving.
*
* @param window - The window to center, either a {@link Window} or its {@link Window.id}.
* @param options.display - The display to center on, either a {@link Display} or its {@link Display.id}. Defaults to the window's current display.
* @group Window Control
*/
centerWindow(window: Window | number, options?: {
display?: Display | number;
}): Promise;
/**
* Moves the given window so its top-left corner is at the given position (in points, top-left origin).
*
* Requires Accessibility Control permission (see {@link getAccessibilityControlAccess}).
*
* @remarks
* Rejects if Accessibility permission is missing, or the window is minimized, closed, or does not
* support moving.
*
* @param window - The window to move, either a {@link Window} or its {@link Window.id}.
* @param position - The new top-left origin for the window, in points (top-left coordinate space).
* @group Window Control
*/
moveWindow(window: Window | number, position: {
x: number;
y: number;
}): Promise;
/**
* Selects the camera's active capture format that best matches the given dimensions (in pixels).
*
* Use this when you want the camera to deliver a specific resolution — typically before recording or
* before showing a live preview, so the preview renders at the intended resolution. The format stays
* in effect until something else changes it.
*
* The chosen format is the smallest format whose dimensions are ≥ the target, preferring biplanar YUV
* pixel formats, and falling back to the largest available format if nothing meets the target.
*
* @remarks
* Rejects if the camera is unavailable, has no usable video format, or its configuration is locked by
* another process.
*
* @param camera - The camera to configure, either a {@link Camera} or its {@link Camera.id}.
* @param dimensions - Target dimensions in pixels.
* @group Device Control
*/
setCameraActiveFormat(camera: Camera | string, dimensions: Size): Promise;
/**
* Returns the camera capture format that {@link setCameraActiveFormat} would select for the given
* dimensions (in pixels), without applying it. Returns `undefined` if the camera has no suitable format.
*
* @group Device Control
*/
getCameraBestFormat(camera: Camera | string, dimensions: Size): Promise;
/**
* Returns the icon of the given running application as a `data:image/png;base64,...` URL,
* usable directly as the `src` of an HTML `
` tag.
*
* @group Device Control
*/
getApplicationIcon(application: RunningApplication | number): Promise;
/**
* Indicates if camera can be used.
*
* Authorization status that indicates whether the user grants the app permission to capture video.
*
* @group Permissions
*/
getCameraAuthorizationStatus(): Promise;
/**
* Indicates if microphone can be used.
*
* Authorization status that indicates whether the user grants the app permission to capture audio.
*
* @group Permissions
*/
getMicrophoneAuthorizationStatus(): Promise;
/**
* Indicates if screen can be recorded.
*
* @group Permissions
*/
getScreenRecordingAccess(): Promise;
/**
* Indicates if system audio can be recorded.
*
* @group Permissions
*/
getSystemAudioRecordingAccess(options?: {
backend?: SystemAudioPermissionBackend;
}): Promise;
/**
* Probes whether system audio can actually be recorded with the given backend by attempting a short silent capture.
*
* Unlike {@link getSystemAudioRecordingAccess}, which reads the recorded permission state, this verifies the
* permission is truly usable, immediately detecting cases where the OS reports a permission as granted but
* capture would still fail (e.g. after the user revokes it).
*
* @remarks If the permission state is still undetermined, this may trigger the system audio permission prompt.
* @group Permissions
*/
probeSystemAudioRecordingAccess(options?: {
backend?: SystemAudioPermissionBackend;
}): Promise;
/**
* Indicates if keystroke events of other apps can be recorded via Input Monitoring.
*
* @group Permissions
*/
getInputMonitoringAccess(): Promise;
/**
* Indicates if other apps can be controlled via Accessibility.
*
* @group Permissions
*/
getAccessibilityControlAccess(): Promise;
/**
* Requests the user's permission to allow the app to capture the camera.
*
* Prompts the users if this is the first time requesting access, otherwise immediately returns.
*
* @returns Boolean value that indicates whether the user granted or denied access to your app.
* @group Permissions
*/
requestCameraAccess(): Promise;
/**
* Requests the user's permission to allow the app to capture the microphone.
*
* Prompts the users if this is the first time requesting access, otherwise immediately returns.
*
* @returns Boolean value that indicates whether the user granted or denied access to your app.
* @group Permissions
*/
requestMicrophoneAccess(): Promise;
/**
* Requests the user's permission to allow the app to capture the screen.
*
* Afterwards, the users needs to restart this app, for the permission to become active in the app.
*
* @group Permissions
*/
requestScreenRecordingAccess(): Promise;
/**
* Requests the user's permission to allow the app to capture system audio.
*
* Permission path depends on the selected backend:
* - `default` and `coreAudio`: system audio capture permission
* - `screenCaptureKit`: Screen Recording permission
* - `_beta_coreAudio`: deprecated alias for `coreAudio`
*
* For the `screenCaptureKit` backend the user must restart the app before the granted permission
* becomes active. The `default` and `coreAudio` backends return the live granted/denied result
* with no restart required (macOS 14.2+).
*
* @returns Boolean value that indicates whether the user granted or denied access to your app.
* @group Permissions
*/
requestSystemAudioRecordingAccess(options?: {
backend?: SystemAudioPermissionBackend;
}): Promise;
/**
* Requests the users's permission to monitor keystrokes of other apps via Input Monitoring.
*
* If this is the first time requesting access, this shows dialog that lets th users open System Settings.
* In System Settings, the user can allow the app permission to monitor other apps.
*
* Afterwards, the users needs to restart this app, for the permission to become active in the app.
*
* @group Permissions
*/
requestInputMonitoringAccess(): Promise;
/**
* Requests the users's permission to control other apps via Accessibility permissions.
*
* If this is the first time requesting access, this shows dialog that lets th users open System Settings.
* In System Settings, the user can allow the app permission to control apps.
*
* Afterwards, the users needs to restart this app, for the permission to become active in the app.
*
* @group Permissions
*/
requestAccessibilityControlAccess(): Promise;
/**
* Creates a {@link Recorder} for the given schema.
*
* The schema describes what to record (its `items`, e.g. a webcam, display, microphone or system audio),
* where to write the resulting RecordKit bundle (`output_directory`), and optional session-wide
* {@link RecorderSettings}. Call {@link Recorder.prepare} then {@link Recorder.start} on the returned recorder.
*
* @remarks The given `schema` is consumed: device/window objects in its `items` are replaced by their IDs and
* any callbacks are registered internally. Pass a fresh schema object per call rather than reusing one.
*
* @group Recording
*/
createRecorder(schema: {
output_directory?: string;
items: RecorderSchemaItem[];
settings?: RecorderSettings;
}): Promise;
}
/**
* Typed event overloads for {@link RecordKit}. Declaration-merges with the class so that
* `recordkit.on('log', message => …)` receives a typed {@link LogMessage} instead of `any`.
*
* @group Logging
*/
export interface RecordKit {
/** Fires for every log message emitted by RecordKit. See {@link LogMessage}. */
on(event: 'log', listener: (message: LogMessage) => void): this;
/** @see {@link RecordKit.on} */
once(event: 'log', listener: (message: LogMessage) => void): this;
/** @see {@link RecordKit.on} */
off(event: 'log', listener: (message: LogMessage) => void): this;
}
/** @ignore */
export declare let recordkit: RecordKit;
/**
* @group Permissions
*
* @remarks
* Describes the apps permission to access a recording device.
*
* - `notDetermined` The user has not yet made a choice.
* - `restricted` The user cannot change the client's status, possibly due to active restrictions such as parental controls being in place.
* - `denied` The user explicitly denied access to the hardware supporting a media type for the client.
* - `authorized` Application is authorized to access the hardware.
*/
export type AuthorizationStatus = 'notDetermined' | 'restricted' | 'denied' | 'authorized';
/**
* Backend selector used for backend-aware system audio permission checks and requests.
*
* @group Permissions
*/
export type SystemAudioPermissionBackend = 'default' | SystemAudioBackend;
/**
* An external iOS device that can be used for screen recording.
*
* @group Discovery
*/
export interface AppleDevice {
/** An identifier that uniquely identifies the device. */
id: string;
/** A localized device name for display in the user interface. */
name: string;
/** The model of this device. */
model_id?: string;
/**
* The current availability state of this device.
*
* - `available`: Device can be recorded
* - `notPaired`: Device cannot be recorded because it is connected but not paired (recovery: "Tap 'Trust' on iPhone")
* - `notConnected`: Device cannot be recorded because it is currently not connected (recovery: "Connect via cable")
* - `pairedNeedsConnect`: Device cannot be recorded because it is paired but currently not connected (recovery: "(Re-)connect via cable")
* - `pairedNeedsReconnect`: Device cannot be recorded because it needs to be reconnected (recovery: "Unplug cable, and reconnect again")
*/
availability: 'available' | 'notPaired' | 'notConnected' | 'pairedNeedsConnect' | 'pairedNeedsReconnect';
}
/**
* A running macOS application of which windows or audio can be recorded.
*
* @group Discovery
*/
export interface RunningApplication {
/** Identifier for this application (process id). */
id: number;
/** Display name of the application. */
name?: string;
/** Bundle identifier of the application (e.g., "com.apple.Safari"). */
bundle_identifier?: string;
/**
* The current availability state of this application.
*
* - `available`: Application can be recorded
* - `notRunning`: Application cannot be recorded because it is not (or no longer) running
*/
availability: 'available' | 'notRunning';
}
/**
* A camera whose video can be recorded.
*
* @group Discovery
*/
export interface Camera {
/** An identifier that uniquely identifies the camera. */
id: string;
/** Indicates whether this is a virtual camera (e.g. provided by software rather than physical hardware). */
isVirtual: boolean;
/** A localized camera name for display in the user interface. */
name: string;
/** The model ID of this camera. */
model_id: string;
/** The manufacturer of this camera. */
manufacturer: string;
/**
* The current availability state of this camera.
*
* - `available`: Camera can be recorded
* - `lidClosed`: Camera cannot be recorded because the MacBook lid is closed (recovery: "Open MacBook lid")
* - `unknownSuspended`: Camera cannot be recorded because it is suspended for some unknown reason (recovery: "Unsuspend camera")
* - `notConnected`: Camera cannot be recorded because it is currently not connected (recovery: "Connect camera")
*/
availability: 'available' | 'lidClosed' | 'unknownSuspended' | 'notConnected';
/**
* This URL can be used in a `img` tag to display a live preview of the camera feed in your user interface.
*
* @remarks
* The preview URL should be available for every camera under normal conditions. If you observe a camera without a preview URL please report it as a bug.
*/
preview_url?: string;
}
/**
* A camera capture format, as returned by {@link RecordKit.getCameraBestFormat}.
*
* @group Discovery
*/
export interface CameraFormat {
/** Width of the format, in pixels. */
width: number;
/** Height of the format, in pixels. */
height: number;
/** Highest frame rate supported by this format, in frames per second. */
maxFrameRate: number;
}
/**
* A microphone whose audio can be recorded.
*
* @group Discovery
*/
export interface Microphone {
/** An identifier that uniquely identifies the microphone. */
id: string;
/** Indicates whether this is a virtual microphone (e.g. provided by software rather than physical hardware). */
isVirtual: boolean;
/** A localized microphone name for display in the user interface. */
name: string;
/** The model ID of this microphone. */
model_id: string;
/** The manufacturer of this microphone. */
manufacturer: string;
/**
* The current availability state of this microphone.
*
* - `available`: Microphone can be recorded
* - `lidClosed`: Microphone cannot be recorded because the MacBook lid is closed (recovery: "Open MacBook lid")
* - `unknownSuspended`: Microphone cannot be recorded because it is suspended for some unknown reason (recovery: "Unsuspend microphone")
* - `notConnected`: Microphone cannot be recorded because it is currently not connected (recovery: "Connect microphone")
*/
availability: 'available' | 'lidClosed' | 'unknownSuspended' | 'notConnected';
}
/**
* A Mac display that can be used for screen recording.
*
* @group Discovery
*/
export interface Display {
/** An identifier that uniquely identifies this Mac display (CGDirectDisplayID). */
id: number;
/** Name of this display. */
localizedName?: string;
/** SF Symbol name representing this display (e.g. `laptopcomputer`, `display`), suitable for use in the UI. */
symbolName: string;
/** Frame of the display, relative to the main display. Uses top-left coordinate space. */
frame: Bounds;
/** Visible frame of the display (excluding the menu bar and Dock), relative to the main display. Top-left coordinate space. */
visibleFrame?: Bounds;
/** Indicates if this is the main display. */
isMain: boolean;
/**
* The current availability state of this display.
*
* - `available`: A display can be recorded
* - `lidClosed`: A display cannot be recorded, because the MacBook lid is closed (recovery: "Open MacBook lid")
* - `notConnected`: A display cannot be screen recorded, because it is currently not connected (recovery: "Connect display")
*/
availability: 'available' | 'lidClosed' | 'notConnected';
}
/**
* A macOS window that can be used for screen recording.
*
* @group Discovery
*/
export interface Window {
/** An identifier that uniquely identifies this macOS window (CGWindowID). */
id: number;
/** Title of the window. */
title?: string;
/** Frame of the window, relative to the main display. Uses top-left coordinate space. */
frame: Bounds;
/**
* The level of the window relative to other windows.
*/
level: number;
/** Process ID of the application that owns this window. */
application_process_id?: number;
/** Name of the application that owns this window. */
application_name?: string;
}
/**
* @group Utilities
*/
export interface Bounds {
x: number;
y: number;
width: number;
height: number;
}
/**
* The user's preferred device IDs for each source type, ordered most-preferred first.
*
* @group Preferred Devices
*/
export interface UserPreferred {
/** Preferred microphone IDs (matching {@link Microphone.id}), most-preferred first. */
microphoneIDs: string[];
/** Preferred camera IDs (matching {@link Camera.id}), most-preferred first. */
cameraIDs: string[];
/** Preferred display IDs (matching {@link Display.id}), most-preferred first. */
displayIDs: number[];
/** Preferred Apple device IDs (matching {@link AppleDevice.id}), most-preferred first. */
appleDeviceIDs: string[];
}
/**
* @group Logging
*/
export type LogLevel = 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'critical';
/**
* A structured log message emitted by RecordKit, delivered as the payload of the `'log'` event.
*
* @example
* ```ts
* recordkit.on('log', (message) => {
* if (message.level === 'error') myLogger.error(message.category, message.message, message.metadata)
* })
* ```
*
* @group Logging
*/
export interface LogMessage {
/** Time the message was logged, in milliseconds since the Unix epoch. Use `new Date(timestamp)` to get a `Date`. */
timestamp: number;
/** Severity level of the message. */
level: LogLevel;
/** Category the message belongs to (e.g. the subsystem that emitted it). */
category: string;
/** The log message text. */
message: string;
/** Additional structured key/value metadata attached to the message. */
metadata: Record;
/** Pre-formatted, human-readable representation of the message (timestamp, level, category, message and metadata). */
formattedMessage: string;
}