meeting-record 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,17 @@
1
1
  # meeting-record for Node.js
2
2
 
3
- System-audio and microphone capture with meeting detection for macOS and Windows.
3
+ [![npm](https://img.shields.io/npm/v/meeting-record)](https://www.npmjs.com/package/meeting-record)
4
4
 
5
- ## Install
5
+ System-audio and microphone capture with meeting detection for macOS, Windows, and Linux.
6
+ See the [project README](https://github.com/hoangvvo/meeting-record#readme) for requirements, permissions, and supported apps.
6
7
 
7
8
  ```sh
8
9
  npm install meeting-record
9
10
  ```
10
11
 
11
- - Requires Node.js 22.13+ (22.x) or 24+.
12
- - See the [platform requirements and permissions](https://github.com/hoangvvo/meeting-record#requirements) for app configuration.
12
+ ## Usage
13
13
 
14
- ## Capture
14
+ Capture system audio for ten seconds.
15
15
 
16
16
  ```ts
17
17
  import { setTimeout as delay } from "node:timers/promises";
@@ -19,131 +19,54 @@ import { capture, permissions, Permission } from "meeting-record";
19
19
 
20
20
  await permissions.request(Permission.SystemAudio);
21
21
  const recording = await capture.start({ type: "system" });
22
-
23
- // Stop after ten seconds; keep reading until the stream ends.
24
22
  const stopped = delay(10_000).then(() => recording.stopRecording());
23
+
25
24
  for await (const chunk of recording.systemAudio) {
26
- // Raw float32 PCM, with the format and capture time of this packet.
27
25
  console.log(chunk.pcm, chunk.hostTimeNs, chunk.sampleRate, chunk.channels);
28
26
  }
29
27
  await stopped;
30
28
  ```
31
29
 
32
- | Target | Value passed to `capture.start()` |
33
- | ----------------------------- | --------------------------------- |
34
- | System audio | `{ type: "system" }` |
35
- | One app and its audio helpers | `{ type: "process", pid }` |
36
-
37
- - **App picker:** `meetings.audioApps()` lists available apps. Use the selected entry's `pid`; no meeting scan is required.
38
- - **Meeting capture:** a detected meeting's `pid` is also a process target.
39
- - **Permissions:** `permissions.request()` returns a `PermissionStatus`; `permissions.status()` checks the current status without prompting.
40
- - **Sessions:** one recording at a time per process.
41
-
42
- ### Add a microphone
43
-
44
- Request microphone permission, then pass `microphone` in the capture options:
30
+ Select an app and include its microphone and a 24 kHz mix.
45
31
 
46
32
  ```ts
47
- import { MicrophoneSource } from "meeting-record";
33
+ import { meetings, MicrophoneSource } from "meeting-record";
48
34
 
49
35
  await permissions.request(Permission.Microphone);
50
- const recording = await capture.start(
51
- { type: "system" },
52
- {
53
- mono: false, // Stereo system audio; defaults to mono. The mic stays mono.
54
- microphone: MicrophoneSource.Default,
55
- },
56
- );
57
- ```
58
-
59
- - `MicrophoneSource.Default` follows the OS input device.
60
- - `MicrophoneSource.Auto` prefers the captured app's mic on Windows, then the communications default. On macOS, it uses the default input.
61
- - Without `microphone`, only system audio is captured.
62
-
63
- ## Audio output
64
-
65
- | Output | Access | Data |
66
- | ------------ | ----------------------- | ---------------------------------------------------------------------------- |
67
- | System audio | `recording.systemAudio` | Object-mode stream of `AudioChunk` packets |
68
- | Microphone | `recording.microphone` | Same packet type; present when requested |
69
- | Mixed audio | `recording.mixedAudio` | Byte stream of mono signed 16-bit little-endian PCM; present when configured |
70
-
71
- - **Raw samples:** `chunk.pcm` contains interleaved float32 PCM.
72
- - **Packet metadata:** `hostTimeNs`, `frameCount`, `sampleRate`, `channels`, and `droppedSamples`.
73
- - **Reading:** use `data` listeners or `for await...of` on each raw track. Use each packet's format; it can change during capture.
74
- - **Slow readers:** raw tracks report discarded samples through `drop` events and `droppedSamples`.
75
- - See [capture formats and channels](https://github.com/hoangvvo/meeting-record#capture) for sample rates and platform behavior.
36
+ const [app] = meetings.audioApps();
37
+ if (!app) throw new Error("No audio apps");
76
38
 
77
- ### Mixed audio
78
-
79
- After requesting the audio and microphone permissions, start with `mix` to add a combined stream:
80
-
81
- ```ts
82
- const recording = await capture.start(
83
- { type: "system" },
84
- {
85
- microphone: MicrophoneSource.Default,
86
- mix: { sampleRate: 24_000 }, // Combined mono s16le at 24 kHz.
87
- },
39
+ const appRecording = await capture.start(
40
+ { type: "process", pid: app.pid },
41
+ { microphone: MicrophoneSource.Auto, mix: { sampleRate: 24_000 } },
88
42
  );
89
-
90
- recording.mixedAudio.on("data", (pcm) => console.log(pcm.byteLength));
91
- recording.mixedAudio.setMicrophoneMuted(true); // Affects the mix only.
92
43
  ```
93
44
 
94
- - Mixed audio is a standard byte stream: it can also be piped to a writable.
95
- - Raw tracks remain available alongside the mix.
96
-
97
- ## Controls and events
98
-
99
- | Action | API |
100
- | ------------------------- | -------------------------------------------------------------- |
101
- | Pause / resume | `recording.pauseRecording()` / `recording.resumeRecording()` |
102
- | Stop | `await recording.stopRecording()`; safe to call more than once |
103
- | Check recording state | `recording.state` |
104
- | Check source availability | `track.availability` |
105
- | Cancel start or recording | Pass an `AbortSignal` as `CaptureOptions.signal` |
106
-
107
- - **Pause:** affects the whole recording; paused time is omitted.
108
- - **Stop:** keep reading each output until `end` to drain queued audio.
109
- - **Source loss:** the session stays alive. Track availability is `live`, `degraded`, or `interrupted`.
110
- - **App exit:** system audio stops when all captured apps exit; the microphone and session stay alive. Start a new session for a relaunched app.
111
-
112
- Attach source-event listeners immediately after awaiting `capture.start()`:
45
+ Read the mix and pause, resume, or stop the recording.
113
46
 
114
47
  ```ts
115
- recording.systemAudio.on("interrupted", (reason, message) => console.log(reason, message));
116
- recording.systemAudio.on("degraded", (reason, message) => console.log(reason, message));
117
- recording.systemAudio.on("resumed", () => console.log("System audio resumed"));
118
- recording.microphone?.on("devicechange", (name) => console.log("Microphone:", name));
48
+ appRecording.mixedAudio.on("data", (pcm) => console.log(pcm.byteLength));
49
+ appRecording.pauseRecording();
50
+ appRecording.resumeRecording();
51
+ await delay(10_000);
52
+ await appRecording.stopRecording();
119
53
  ```
120
54
 
121
- ## Meetings
55
+ Scan for meetings or watch for changes.
122
56
 
123
57
  ```ts
124
- import { meetings } from "meeting-record";
125
-
126
58
  const active = (await meetings.scan()).filter((meeting) => meeting.shouldRecord);
127
59
 
128
60
  meetings.on("started", (meeting) => console.log("Started:", meeting));
129
61
  meetings.on("updated", (meeting) => console.log("Updated:", meeting));
130
- meetings.on("ended", (meeting) => console.log("Ended:", meeting));
62
+ meetings.on("ended", ({ platform, pid }) => console.log("Ended:", platform, pid));
131
63
  meetings.watch();
132
64
 
133
- // Later: meetings.unwatch();
65
+ await delay(10_000);
66
+ meetings.unwatch();
134
67
  ```
135
68
 
136
- - Use `shouldRecord` to decide whether a meeting is ready to record.
137
- - Request `Permission.Accessibility` on macOS for titles and URLs; relaunch after granting it.
138
- - See [supported services and detection behavior](https://github.com/hoangvvo/meeting-record#detection).
139
-
140
- ## Types and errors
141
-
142
- - **Constants:** `Platform`, `Permission`, `PermissionStatus`, `MicrophoneSource`, `CaptureState`, `TrackAvailability`, and `TrackInterruptionReason` have matching union types.
143
- - **Events:** names and callback arguments are checked by TypeScript, including chained `on`, `once`, and `off` calls.
144
- - **Library failures:** capture, permissions, and enumeration use `MeetingRecordError` subclasses, with a numeric `code`.
145
- - **Invalid arguments:** throw `TypeError`.
146
- - **Cancellation:** aborting rejects pending work with the signal's reason and stops an active recording.
69
+ On `ended`, use `platform` and `pid` to remove the meeting. Other payload fields, including `shouldRecord`, may contain the last active observation. Meeting events do not stop capture; call `stopRecording()` and drain the tracks when you want the recording to end.
147
70
 
148
71
  ## License
149
72
 
@@ -0,0 +1,265 @@
1
+ SpeexDSP 1.2.1 and bundled KISS FFT
2
+
3
+ Copyright 2002-2008 Xiph.org Foundation
4
+ Copyright 2002-2008 Jean-Marc Valin
5
+ Copyright 2005-2007 Analog Devices Inc.
6
+ Copyright 2005-2008 Commonwealth Scientific and Industrial Research
7
+ Organisation (CSIRO)
8
+ Copyright 1993, 2002, 2006 David Rowe
9
+ Copyright 2003 EpicGames
10
+ Copyright 1992-1994 Jutta Degener, Carsten Bormann
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions
14
+ are met:
15
+
16
+ - Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+
19
+ - Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in the
21
+ documentation and/or other materials provided with the distribution.
22
+
23
+ - Neither the name of the Xiph.org Foundation nor the names of its
24
+ contributors may be used to endorse or promote products derived from
25
+ this software without specific prior written permission.
26
+
27
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
31
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+
39
+
40
+ Additional source notices
41
+
42
+ /* Copyright (C) Jean-Marc Valin */
43
+
44
+ /* Copyright (C) 2003 Epic Games
45
+ Written by Jean-Marc Valin */
46
+
47
+ /********************************************************************
48
+ * *
49
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
50
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
51
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
52
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
53
+ * *
54
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
55
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
56
+ * *
57
+ ********************************************************************
58
+
59
+ function: #ifdef jail to whip a few platforms into the UNIX ideal.
60
+ last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $
61
+
62
+ ********************************************************************/
63
+
64
+ /*
65
+ Copyright (c) 2003-2004, Mark Borgerding
66
+
67
+ All rights reserved.
68
+
69
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
70
+
71
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
72
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
73
+ * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
74
+
75
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76
+ */
77
+
78
+ /* Copyright (C) 2003 Jean-Marc Valin */
79
+
80
+ /* Copyright (C) 2005-2006 Jean-Marc Valin
81
+ File: fftwrap.c
82
+
83
+ Wrapper for various FFTs
84
+
85
+ Redistribution and use in source and binary forms, with or without
86
+ modification, are permitted provided that the following conditions
87
+ are met:
88
+
89
+ - Redistributions of source code must retain the above copyright
90
+ notice, this list of conditions and the following disclaimer.
91
+
92
+ - Redistributions in binary form must reproduce the above copyright
93
+ notice, this list of conditions and the following disclaimer in the
94
+ documentation and/or other materials provided with the distribution.
95
+
96
+ - Neither the name of the Xiph.org Foundation nor the names of its
97
+ contributors may be used to endorse or promote products derived from
98
+ this software without specific prior written permission.
99
+
100
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
101
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
102
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
103
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
104
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
105
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
106
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
107
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
108
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
109
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
110
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
111
+
112
+ */
113
+
114
+ /* Copyright (C) 2005 Jean-Marc Valin
115
+ File: fftwrap.h
116
+
117
+ Wrapper for various FFTs
118
+
119
+ Redistribution and use in source and binary forms, with or without
120
+ modification, are permitted provided that the following conditions
121
+ are met:
122
+
123
+ - Redistributions of source code must retain the above copyright
124
+ notice, this list of conditions and the following disclaimer.
125
+
126
+ - Redistributions in binary form must reproduce the above copyright
127
+ notice, this list of conditions and the following disclaimer in the
128
+ documentation and/or other materials provided with the distribution.
129
+
130
+ - Neither the name of the Xiph.org Foundation nor the names of its
131
+ contributors may be used to endorse or promote products derived from
132
+ this software without specific prior written permission.
133
+
134
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
138
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
139
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
140
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
141
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
142
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
143
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
144
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
+
146
+ */
147
+
148
+ /* Copyright (C) 2006 Jean-Marc Valin */
149
+
150
+ /*
151
+ Copyright (c) 2003-2004, Mark Borgerding
152
+ Copyright (c) 2005-2007, Jean-Marc Valin
153
+
154
+ All rights reserved.
155
+
156
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
157
+
158
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
159
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
160
+ * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
161
+
162
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
163
+ */
164
+
165
+ /* Copyright (C) 2002 Jean-Marc Valin */
166
+
167
+ /* Copyright (C) 2003-2008 Jean-Marc Valin
168
+
169
+ File: mdf.c
170
+ Echo canceller based on the MDF algorithm (see below)
171
+
172
+ Redistribution and use in source and binary forms, with or without
173
+ modification, are permitted provided that the following conditions are
174
+ met:
175
+
176
+ 1. Redistributions of source code must retain the above copyright notice,
177
+ this list of conditions and the following disclaimer.
178
+
179
+ 2. Redistributions in binary form must reproduce the above copyright
180
+ notice, this list of conditions and the following disclaimer in the
181
+ documentation and/or other materials provided with the distribution.
182
+
183
+ 3. The name of the author may not be used to endorse or promote products
184
+ derived from this software without specific prior written permission.
185
+
186
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
187
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
188
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
189
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
190
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
191
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
192
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
193
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
194
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
195
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
196
+ POSSIBILITY OF SUCH DAMAGE.
197
+ */
198
+
199
+ /* Copyright (C) 2007 Jean-Marc Valin
200
+
201
+ File: os_support.h
202
+ This is the (tiny) OS abstraction layer. Aside from math.h, this is the
203
+ only place where system headers are allowed.
204
+
205
+ Redistribution and use in source and binary forms, with or without
206
+ modification, are permitted provided that the following conditions are
207
+ met:
208
+
209
+ 1. Redistributions of source code must retain the above copyright notice,
210
+ this list of conditions and the following disclaimer.
211
+
212
+ 2. Redistributions in binary form must reproduce the above copyright
213
+ notice, this list of conditions and the following disclaimer in the
214
+ documentation and/or other materials provided with the distribution.
215
+
216
+ 3. The name of the author may not be used to endorse or promote products
217
+ derived from this software without specific prior written permission.
218
+
219
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
220
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
221
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
222
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
223
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
224
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
225
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
227
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
228
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
229
+ POSSIBILITY OF SUCH DAMAGE.
230
+ */
231
+
232
+ /* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin)
233
+ Copyright (C) 2004-2006 Epic Games
234
+
235
+ File: preprocess.c
236
+ Preprocessor with denoising based on the algorithm by Ephraim and Malah
237
+
238
+ Redistribution and use in source and binary forms, with or without
239
+ modification, are permitted provided that the following conditions are
240
+ met:
241
+
242
+ 1. Redistributions of source code must retain the above copyright notice,
243
+ this list of conditions and the following disclaimer.
244
+
245
+ 2. Redistributions in binary form must reproduce the above copyright
246
+ notice, this list of conditions and the following disclaimer in the
247
+ documentation and/or other materials provided with the distribution.
248
+
249
+ 3. The name of the author may not be used to endorse or promote products
250
+ derived from this software without specific prior written permission.
251
+
252
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
253
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
254
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
255
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
256
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
257
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
258
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
260
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
261
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
262
+ POSSIBILITY OF SUCH DAMAGE.
263
+ */
264
+
265
+ /* Copyright (C) 2005 Jean-Marc Valin */
package/dist/index.d.ts CHANGED
@@ -29,6 +29,32 @@ export declare const Platform: {
29
29
  readonly Discord: "discord";
30
30
  /** A browser tab on a recognised call URL. */
31
31
  readonly Browser: "browser";
32
+ readonly GoTo: "goto";
33
+ readonly Dialpad: "dialpad";
34
+ readonly WhatsApp: "whatsapp";
35
+ readonly Aircall: "aircall";
36
+ readonly RingCentral: "ringcentral";
37
+ readonly EightByEight: "8x8";
38
+ readonly VooV: "voov";
39
+ readonly Tuple: "tuple";
40
+ readonly Gather: "gather";
41
+ readonly Lark: "lark";
42
+ readonly Roam: "roam";
43
+ readonly ClickUp: "clickup";
44
+ readonly Telemost: "telemost";
45
+ readonly Telegram: "telegram";
46
+ readonly Signal: "signal";
47
+ readonly Viber: "viber";
48
+ readonly Line: "line";
49
+ readonly WeChat: "wechat";
50
+ readonly Zalo: "zalo";
51
+ readonly Jitsi: "jitsi";
52
+ readonly Element: "element";
53
+ readonly Mattermost: "mattermost";
54
+ readonly NextcloudTalk: "nextcloud-talk";
55
+ readonly Jami: "jami";
56
+ readonly TencentMeeting: "tencent-meeting";
57
+ readonly WeCom: "wecom";
32
58
  readonly Unknown: "unknown";
33
59
  };
34
60
  export type Platform = (typeof Platform)[keyof typeof Platform];
@@ -69,41 +95,70 @@ export type CaptureTarget = {
69
95
  export declare const MicrophoneSource: {
70
96
  /** Follow the OS default input device. */
71
97
  readonly Default: "default";
72
- /** Prefer the captured app's mic on Windows, then its communications default. Use the OS default on macOS. */
98
+ /** Prefer the captured app's mic, then the default (communications default on Windows). Ambiguous app inputs use the default on macOS. */
73
99
  readonly Auto: "auto";
74
100
  };
75
101
  export type MicrophoneSource = (typeof MicrophoneSource)[keyof typeof MicrophoneSource];
102
+ /** Optional microphone effects for input rates from 8 to 192 kHz. All default off. */
103
+ export interface MicrophoneProcessing {
104
+ /** Cancel echo using the captured system track as the playback reference. */
105
+ echoCancellation?: boolean;
106
+ /** Suppress background noise in the microphone track. */
107
+ noiseSuppression?: boolean;
108
+ /** Adjust microphone gain automatically. */
109
+ autoGainControl?: boolean;
110
+ }
76
111
  export interface CaptureOptions {
77
112
  /** Mono mixdown for system audio only; the microphone keeps its format. Default true. */
78
113
  mono?: boolean;
79
- /** Capture a microphone as a separate track. Default off. */
114
+ /** Capture a separate microphone track. Default off; unavailable devices recover while system capture continues. */
80
115
  microphone?: MicrophoneSource;
116
+ /** Optional microphone effects. All default off; requires microphone. */
117
+ microphoneProcessing?: MicrophoneProcessing;
81
118
  /** Additional mono s16le output, aligned and resampled to the requested rate. */
82
119
  mix?: MixedAudioOptions;
83
120
  /** Aborting stops capture, including a pending start. */
84
121
  signal?: AbortSignal;
85
122
  }
123
+ /** Base class for library errors with a native status code. */
86
124
  export declare class MeetingRecordError extends Error {
125
+ /** Native status code. */
87
126
  readonly code: number;
88
- constructor(message: string, code: number);
127
+ constructor(message: string,
128
+ /** Native status code. */
129
+ code: number);
89
130
  }
131
+ /** The OS, architecture, or OS version is unsupported. */
90
132
  export declare class UnsupportedOsError extends MeetingRecordError {
91
133
  }
134
+ /** Required system-audio or microphone access has not been granted. */
92
135
  export declare class PermissionError extends MeetingRecordError {
93
136
  }
137
+ /** A process-wide recording or watcher is already active. */
94
138
  export declare class AlreadyRunningError extends MeetingRecordError {
95
139
  }
140
+ /** An audio capture operation failed. */
96
141
  export declare class CaptureError extends MeetingRecordError {
97
142
  }
143
+ /** Native initialization or another internal operation failed. */
98
144
  export declare class InternalError extends MeetingRecordError {
99
145
  }
100
146
  export declare const permissions: {
147
+ /**
148
+ * Check the current permission without prompting.
149
+ * @throws {TypeError} If the permission is unknown.
150
+ * @throws {UnsupportedOsError} If the platform is unsupported.
151
+ */
101
152
  status(permission: Permission): PermissionStatus;
102
153
  /**
103
154
  * Show the permission prompt and resolve once the user answers.
104
155
  *
105
156
  * Accessibility opens System Settings and needs an app relaunch, so it resolves
106
157
  * as soon as Settings is open.
158
+ * Returns the current status if the timeout expires.
159
+ * @throws {TypeError} If the permission is unknown.
160
+ * @throws {MeetingRecordError} If the platform cannot start the permission request.
161
+ * @throws If the request is aborted.
107
162
  */
108
163
  request(permission: Permission, { timeoutMs, signal }?: {
109
164
  timeoutMs?: number;
@@ -113,22 +168,35 @@ export declare const permissions: {
113
168
  export interface MeetingEvents extends EmitterEvents {
114
169
  started: (meeting: Meeting) => void;
115
170
  updated: (meeting: Meeting) => void;
171
+ /** Only platform and pid identify the ended meeting; other fields may be stale. Does not stop capture. */
116
172
  ended: (meeting: Meeting) => void;
117
173
  }
118
174
  declare class Meetings extends EventEmitter<{
119
175
  [Event in keyof MeetingEvents]: Parameters<MeetingEvents[Event]>;
120
176
  }> {
121
- /** Point-in-time scan, highest confidence first. */
177
+ /**
178
+ * Point-in-time scan, highest confidence first. Use `shouldRecord` to select calls.
179
+ * @throws {MeetingRecordError} If the platform or audio service cannot be queried.
180
+ */
122
181
  scan(): Promise<Meeting[]>;
123
- /** Begin emitting `started` / `updated` / `ended`. */
182
+ /**
183
+ * Begin emitting `started` / `updated` / `ended`. Repeated calls are harmless.
184
+ * @throws {MeetingRecordError} If the watcher cannot start.
185
+ */
124
186
  watch(): void;
187
+ /** Stop meeting events; safe to call when already stopped. */
125
188
  unwatch(): void;
189
+ /** Whether meeting events are currently being watched. */
126
190
  get watching(): boolean;
127
- /** Every process doing audio IO. */
191
+ /**
192
+ * Every process doing audio IO.
193
+ * @throws {MeetingRecordError} If audio processes cannot be enumerated.
194
+ */
128
195
  audioProcesses(): AudioProcess[];
129
196
  /**
130
197
  * Applications doing audio IO, grouped by owning PID, including helpers.
131
198
  * Pass `pid` as a process target; no meeting scan or Accessibility grant is needed.
199
+ * @throws {MeetingRecordError} If audio applications cannot be enumerated.
132
200
  */
133
201
  audioApps(): AudioProcess[];
134
202
  }
@@ -150,6 +218,7 @@ export declare const TrackInterruptionReason: {
150
218
  };
151
219
  export type TrackInterruptionReason = (typeof TrackInterruptionReason)[keyof typeof TrackInterruptionReason];
152
220
  export interface AudioFormat {
221
+ /** May be zero while the requested microphone has no available device. */
153
222
  readonly sampleRate: number;
154
223
  readonly channels: number;
155
224
  }
@@ -157,10 +226,14 @@ export interface AudioFormat {
157
226
  export interface AudioChunk {
158
227
  /** Interleaved float32 PCM. Packet boundaries and metadata survive iteration. */
159
228
  readonly pcm: Buffer;
229
+ /** First frame's monotonic timestamp in nanoseconds, shared across tracks. */
160
230
  readonly hostTimeNs: bigint;
231
+ /** Number of frames per channel in this packet. */
161
232
  readonly frameCount: number;
233
+ /** This packet's rate; it may change after device recovery. */
162
234
  readonly sampleRate: number;
163
235
  readonly channels: number;
236
+ /** Interleaved samples lost before this packet because the input queue was full. */
164
237
  readonly droppedSamples: number;
165
238
  }
166
239
  export declare const TrackAvailability: {
@@ -201,20 +274,47 @@ export interface CaptureSession {
201
274
  readonly microphone?: AudioTrack;
202
275
  readonly mixedAudio?: MixedAudio;
203
276
  readonly state: CaptureState;
277
+ /** Pause all tracks. Paused time is omitted from mixed output. */
204
278
  pauseRecording(): void;
279
+ /** Resume all tracks after a pause. */
205
280
  resumeRecording(): void;
281
+ /**
282
+ * Stop once, then read outputs until `end` to drain their final audio.
283
+ * Repeated calls share the same promise.
284
+ * @throws {Error} If native capture teardown fails.
285
+ */
206
286
  stopRecording(): Promise<void>;
207
287
  }
208
288
  export interface MixedCaptureSession extends CaptureSession {
209
289
  readonly mixedAudio: MixedAudio;
210
290
  }
211
- /** Attach source-event listeners immediately after awaiting start; startup notifications are delivered on the next turn. */
291
+ /**
292
+ * Start a process-wide recording. Attach source-event listeners after awaiting startup.
293
+ * @throws {TypeError} If the target or capture options are invalid.
294
+ * @throws {AlreadyRunningError} If another recording is active or starting.
295
+ * @throws {PermissionError} If required capture permissions are missing.
296
+ * @throws {CaptureError} If the target or system audio cannot be opened.
297
+ * @throws {UnsupportedOsError} If the platform is unsupported.
298
+ * @throws {InternalError} If native initialization fails.
299
+ * @throws The signal's reason if startup is aborted.
300
+ */
212
301
  declare function startCapture(target: CaptureTarget, options: CaptureOptions & {
213
302
  mix: MixedAudioOptions;
214
303
  }): Promise<MixedCaptureSession>;
304
+ /**
305
+ * Start a process-wide recording. Attach source-event listeners after awaiting startup.
306
+ * @throws {TypeError} If the target or capture options are invalid.
307
+ * @throws {AlreadyRunningError} If another recording is active or starting.
308
+ * @throws {PermissionError} If required capture permissions are missing.
309
+ * @throws {CaptureError} If the target or system audio cannot be opened.
310
+ * @throws {UnsupportedOsError} If the platform is unsupported.
311
+ * @throws {InternalError} If native initialization fails.
312
+ * @throws The signal's reason if startup is aborted.
313
+ */
215
314
  declare function startCapture(target: CaptureTarget, options?: CaptureOptions): Promise<CaptureSession>;
216
315
  export declare const capture: {
217
316
  start: typeof startCapture;
317
+ /** Whether a recording is starting or active, including while paused. */
218
318
  readonly running: boolean;
219
319
  };
220
320
  //# sourceMappingURL=index.d.ts.map