meeting-record 0.3.0 → 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 +24 -102
- package/THIRD_PARTY_NOTICES +265 -0
- package/dist/index.d.ts +107 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -14
- package/dist/index.js.map +1 -1
- package/dist/mixed-audio.d.ts +14 -1
- package/dist/mixed-audio.d.ts.map +1 -1
- package/dist/mixed-audio.js +35 -23
- package/dist/mixed-audio.js.map +1 -1
- package/package.json +4 -3
- package/prebuilds/darwin-x64+arm64/meeting-record.node +0 -0
- package/prebuilds/linux-arm64/meeting-record.glibc.node +0 -0
- package/prebuilds/linux-x64/meeting-record.glibc.node +0 -0
- package/prebuilds/win32-arm64/meeting-record.node +0 -0
- package/prebuilds/win32-x64/meeting-record.node +0 -0
- package/dist/mono-resampler.d.ts +0 -14
- package/dist/mono-resampler.d.ts.map +0 -1
- package/dist/mono-resampler.js +0 -108
- package/dist/mono-resampler.js.map +0 -1
- package/dist/pcm-mixer.d.ts +0 -15
- package/dist/pcm-mixer.d.ts.map +0 -1
- package/dist/pcm-mixer.js +0 -126
- package/dist/pcm-mixer.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# meeting-record for Node.js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/meeting-record)
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
12
|
-
- See the [platform requirements and permissions](https://github.com/hoangvvo/meeting-record#requirements) for app configuration.
|
|
12
|
+
## Usage
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Capture system audio for ten seconds.
|
|
15
15
|
|
|
16
16
|
```ts
|
|
17
17
|
import { setTimeout as delay } from "node:timers/promises";
|
|
@@ -19,132 +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
|
-
|
|
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
|
|
51
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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", (
|
|
62
|
+
meetings.on("ended", ({ platform, pid }) => console.log("Ended:", platform, pid));
|
|
131
63
|
meetings.watch();
|
|
132
64
|
|
|
133
|
-
|
|
65
|
+
await delay(10_000);
|
|
66
|
+
meetings.unwatch();
|
|
134
67
|
```
|
|
135
68
|
|
|
136
|
-
|
|
137
|
-
- The library incorporates call controls and audio signals into `confidence` and `shouldRecord`; no consumer-side call-state logic is required.
|
|
138
|
-
- Request `Permission.Accessibility` on macOS for call-state checks, browser detection, titles, and URLs; relaunch after granting it.
|
|
139
|
-
- See [supported services and detection behavior](https://github.com/hoangvvo/meeting-record#detection).
|
|
140
|
-
|
|
141
|
-
## Types and errors
|
|
142
|
-
|
|
143
|
-
- **Constants:** `Platform`, `Permission`, `PermissionStatus`, `MicrophoneSource`, `CaptureState`, `TrackAvailability`, and `TrackInterruptionReason` have matching union types.
|
|
144
|
-
- **Events:** names and callback arguments are checked by TypeScript, including chained `on`, `once`, and `off` calls.
|
|
145
|
-
- **Library failures:** capture, permissions, and enumeration use `MeetingRecordError` subclasses, with a numeric `code`.
|
|
146
|
-
- **Invalid arguments:** throw `TypeError`.
|
|
147
|
-
- **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.
|
|
148
70
|
|
|
149
71
|
## License
|
|
150
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
|
|
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
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|