node-mac-recorder 1.0.0
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/LICENSE +21 -0
- package/README.md +492 -0
- package/binding.gyp +39 -0
- package/index.js +372 -0
- package/package.json +45 -0
- package/src/audio_capture.mm +116 -0
- package/src/mac_recorder.mm +472 -0
- package/src/screen_capture.mm +141 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 node-mac-recorder
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
# node-mac-recorder
|
|
2
|
+
|
|
3
|
+
A powerful native macOS screen recording Node.js package with advanced window selection, multi-display support, and granular audio controls. Built with AVFoundation for optimal performance.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✨ **Advanced Recording Capabilities**
|
|
8
|
+
|
|
9
|
+
- 🖥️ **Full Screen Recording** - Capture entire displays
|
|
10
|
+
- 🪟 **Window-Specific Recording** - Record individual application windows
|
|
11
|
+
- 🎯 **Area Selection** - Record custom screen regions
|
|
12
|
+
- 🖱️ **Multi-Display Support** - Automatic display detection and selection
|
|
13
|
+
- 🎨 **Cursor Control** - Toggle cursor visibility in recordings
|
|
14
|
+
|
|
15
|
+
🎵 **Granular Audio Controls**
|
|
16
|
+
|
|
17
|
+
- 🎤 **Microphone Audio** - Separate microphone control (default: off)
|
|
18
|
+
- 🔊 **System Audio** - System audio capture (default: on)
|
|
19
|
+
- 📻 **Audio Device Listing** - Enumerate available audio devices
|
|
20
|
+
- 🎛️ **Device Selection** - Choose specific audio input devices
|
|
21
|
+
|
|
22
|
+
🔧 **Smart Window Management**
|
|
23
|
+
|
|
24
|
+
- 📋 **Window Discovery** - List all visible application windows
|
|
25
|
+
- 🎯 **Automatic Coordinate Conversion** - Handle multi-display coordinate systems
|
|
26
|
+
- 📐 **Display ID Detection** - Automatically select correct display for window recording
|
|
27
|
+
- 🖼️ **Window Filtering** - Smart filtering of recordable windows
|
|
28
|
+
|
|
29
|
+
⚙️ **Customization Options**
|
|
30
|
+
|
|
31
|
+
- 🎬 **Quality Control** - Adjustable recording quality presets
|
|
32
|
+
- 🎞️ **Frame Rate Control** - Custom frame rate settings
|
|
33
|
+
- 📁 **Flexible Output** - Custom output paths and formats
|
|
34
|
+
- 🔐 **Permission Management** - Built-in permission checking
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install node-mac-recorder
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Requirements
|
|
43
|
+
|
|
44
|
+
- **macOS 10.15+** (Catalina or later)
|
|
45
|
+
- **Node.js 14+**
|
|
46
|
+
- **Xcode Command Line Tools**
|
|
47
|
+
- **Screen Recording Permission** (automatically requested)
|
|
48
|
+
|
|
49
|
+
### Build Requirements
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Install Xcode Command Line Tools
|
|
53
|
+
xcode-select --install
|
|
54
|
+
|
|
55
|
+
# The package will automatically build native modules during installation
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const MacRecorder = require("node-mac-recorder");
|
|
62
|
+
|
|
63
|
+
const recorder = new MacRecorder();
|
|
64
|
+
|
|
65
|
+
// Simple full-screen recording
|
|
66
|
+
await recorder.startRecording("./output.mov");
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, 5000)); // Record for 5 seconds
|
|
68
|
+
await recorder.stopRecording();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## API Reference
|
|
72
|
+
|
|
73
|
+
### Constructor
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const recorder = new MacRecorder();
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Methods
|
|
80
|
+
|
|
81
|
+
#### `startRecording(outputPath, options?)`
|
|
82
|
+
|
|
83
|
+
Starts screen recording with the specified options.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
await recorder.startRecording("./recording.mov", {
|
|
87
|
+
// Audio Controls
|
|
88
|
+
includeMicrophone: false, // Enable microphone (default: false)
|
|
89
|
+
includeSystemAudio: true, // Enable system audio (default: true)
|
|
90
|
+
|
|
91
|
+
// Display & Window Selection
|
|
92
|
+
displayId: 0, // Display index (null = main display)
|
|
93
|
+
windowId: 12345, // Specific window ID
|
|
94
|
+
captureArea: {
|
|
95
|
+
// Custom area selection
|
|
96
|
+
x: 100,
|
|
97
|
+
y: 100,
|
|
98
|
+
width: 800,
|
|
99
|
+
height: 600,
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// Recording Options
|
|
103
|
+
quality: "high", // 'low', 'medium', 'high'
|
|
104
|
+
frameRate: 30, // FPS (15, 30, 60)
|
|
105
|
+
captureCursor: false, // Show cursor (default: false)
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### `stopRecording()`
|
|
110
|
+
|
|
111
|
+
Stops the current recording.
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
const result = await recorder.stopRecording();
|
|
115
|
+
console.log("Recording saved to:", result.outputPath);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### `getWindows()`
|
|
119
|
+
|
|
120
|
+
Returns a list of all recordable windows.
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const windows = await recorder.getWindows();
|
|
124
|
+
console.log(windows);
|
|
125
|
+
// [
|
|
126
|
+
// {
|
|
127
|
+
// id: 12345,
|
|
128
|
+
// name: "My App Window",
|
|
129
|
+
// appName: "MyApp",
|
|
130
|
+
// x: 100, y: 200,
|
|
131
|
+
// width: 800, height: 600
|
|
132
|
+
// },
|
|
133
|
+
// ...
|
|
134
|
+
// ]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### `getDisplays()`
|
|
138
|
+
|
|
139
|
+
Returns information about all available displays.
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
const displays = await recorder.getDisplays();
|
|
143
|
+
console.log(displays);
|
|
144
|
+
// [
|
|
145
|
+
// {
|
|
146
|
+
// id: 69733504,
|
|
147
|
+
// name: "Display 1",
|
|
148
|
+
// resolution: "2048x1330",
|
|
149
|
+
// x: 0, y: 0
|
|
150
|
+
// },
|
|
151
|
+
// ...
|
|
152
|
+
// ]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### `getAudioDevices()`
|
|
156
|
+
|
|
157
|
+
Lists all available audio input devices.
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const devices = await recorder.getAudioDevices();
|
|
161
|
+
console.log(devices);
|
|
162
|
+
// [
|
|
163
|
+
// {
|
|
164
|
+
// id: "device-id-123",
|
|
165
|
+
// name: "Built-in Microphone",
|
|
166
|
+
// manufacturer: "Apple Inc.",
|
|
167
|
+
// isDefault: true
|
|
168
|
+
// },
|
|
169
|
+
// ...
|
|
170
|
+
// ]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### `checkPermissions()`
|
|
174
|
+
|
|
175
|
+
Checks macOS recording permissions.
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
const permissions = await recorder.checkPermissions();
|
|
179
|
+
console.log(permissions);
|
|
180
|
+
// {
|
|
181
|
+
// screenRecording: true,
|
|
182
|
+
// microphone: true,
|
|
183
|
+
// accessibility: true
|
|
184
|
+
// }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### `getStatus()`
|
|
188
|
+
|
|
189
|
+
Returns current recording status and options.
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
const status = recorder.getStatus();
|
|
193
|
+
console.log(status);
|
|
194
|
+
// {
|
|
195
|
+
// isRecording: true,
|
|
196
|
+
// outputPath: "./recording.mov",
|
|
197
|
+
// options: { ... },
|
|
198
|
+
// recordingTime: 15
|
|
199
|
+
// }
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Usage Examples
|
|
203
|
+
|
|
204
|
+
### Window-Specific Recording
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
const recorder = new MacRecorder();
|
|
208
|
+
|
|
209
|
+
// List available windows
|
|
210
|
+
const windows = await recorder.getWindows();
|
|
211
|
+
console.log("Available windows:");
|
|
212
|
+
windows.forEach((win, i) => {
|
|
213
|
+
console.log(`${i + 1}. ${win.appName} - ${win.name}`);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Record a specific window
|
|
217
|
+
const targetWindow = windows.find((w) => w.appName === "Safari");
|
|
218
|
+
await recorder.startRecording("./safari-recording.mov", {
|
|
219
|
+
windowId: targetWindow.id,
|
|
220
|
+
includeSystemAudio: false,
|
|
221
|
+
includeMicrophone: true,
|
|
222
|
+
captureCursor: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
await new Promise((resolve) => setTimeout(resolve, 10000)); // 10 seconds
|
|
226
|
+
await recorder.stopRecording();
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Multi-Display Recording
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
const recorder = new MacRecorder();
|
|
233
|
+
|
|
234
|
+
// List available displays
|
|
235
|
+
const displays = await recorder.getDisplays();
|
|
236
|
+
console.log("Available displays:");
|
|
237
|
+
displays.forEach((display, i) => {
|
|
238
|
+
console.log(`${i}: ${display.resolution} at (${display.x}, ${display.y})`);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Record from second display
|
|
242
|
+
await recorder.startRecording("./second-display.mov", {
|
|
243
|
+
displayId: 1, // Second display
|
|
244
|
+
quality: "high",
|
|
245
|
+
frameRate: 60,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
249
|
+
await recorder.stopRecording();
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Custom Area Recording
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
const recorder = new MacRecorder();
|
|
256
|
+
|
|
257
|
+
// Record specific screen area
|
|
258
|
+
await recorder.startRecording("./area-recording.mov", {
|
|
259
|
+
captureArea: {
|
|
260
|
+
x: 200,
|
|
261
|
+
y: 100,
|
|
262
|
+
width: 1200,
|
|
263
|
+
height: 800,
|
|
264
|
+
},
|
|
265
|
+
quality: "medium",
|
|
266
|
+
captureCursor: false,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
await new Promise((resolve) => setTimeout(resolve, 8000));
|
|
270
|
+
await recorder.stopRecording();
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Audio-Only System Recording
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
const recorder = new MacRecorder();
|
|
277
|
+
|
|
278
|
+
// Record system audio without microphone
|
|
279
|
+
await recorder.startRecording("./system-audio.mov", {
|
|
280
|
+
includeMicrophone: false,
|
|
281
|
+
includeSystemAudio: true,
|
|
282
|
+
captureArea: { x: 0, y: 0, width: 1, height: 1 }, // Minimal video
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Event-Driven Recording
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
const recorder = new MacRecorder();
|
|
290
|
+
|
|
291
|
+
// Listen to recording events
|
|
292
|
+
recorder.on("started", (outputPath) => {
|
|
293
|
+
console.log("Recording started:", outputPath);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
recorder.on("stopped", (result) => {
|
|
297
|
+
console.log("Recording stopped:", result);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
recorder.on("timeUpdate", (seconds) => {
|
|
301
|
+
console.log(`Recording time: ${seconds}s`);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
recorder.on("completed", (outputPath) => {
|
|
305
|
+
console.log("Recording completed:", outputPath);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
await recorder.startRecording("./event-recording.mov");
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Integration Examples
|
|
312
|
+
|
|
313
|
+
### Electron Integration
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
// In main process
|
|
317
|
+
const { ipcMain } = require("electron");
|
|
318
|
+
const MacRecorder = require("node-mac-recorder");
|
|
319
|
+
|
|
320
|
+
const recorder = new MacRecorder();
|
|
321
|
+
|
|
322
|
+
ipcMain.handle("start-recording", async (event, options) => {
|
|
323
|
+
try {
|
|
324
|
+
await recorder.startRecording("./recording.mov", options);
|
|
325
|
+
return { success: true };
|
|
326
|
+
} catch (error) {
|
|
327
|
+
return { success: false, error: error.message };
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
ipcMain.handle("stop-recording", async () => {
|
|
332
|
+
const result = await recorder.stopRecording();
|
|
333
|
+
return result;
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
ipcMain.handle("get-windows", async () => {
|
|
337
|
+
return await recorder.getWindows();
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Express.js API
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
const express = require("express");
|
|
345
|
+
const MacRecorder = require("node-mac-recorder");
|
|
346
|
+
|
|
347
|
+
const app = express();
|
|
348
|
+
const recorder = new MacRecorder();
|
|
349
|
+
|
|
350
|
+
app.post("/start-recording", async (req, res) => {
|
|
351
|
+
try {
|
|
352
|
+
const { windowId, duration } = req.body;
|
|
353
|
+
await recorder.startRecording("./api-recording.mov", { windowId });
|
|
354
|
+
|
|
355
|
+
setTimeout(async () => {
|
|
356
|
+
await recorder.stopRecording();
|
|
357
|
+
}, duration * 1000);
|
|
358
|
+
|
|
359
|
+
res.json({ status: "started" });
|
|
360
|
+
} catch (error) {
|
|
361
|
+
res.status(500).json({ error: error.message });
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
app.get("/windows", async (req, res) => {
|
|
366
|
+
const windows = await recorder.getWindows();
|
|
367
|
+
res.json(windows);
|
|
368
|
+
});
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Advanced Features
|
|
372
|
+
|
|
373
|
+
### Automatic Display Detection
|
|
374
|
+
|
|
375
|
+
When recording windows, the package automatically:
|
|
376
|
+
|
|
377
|
+
1. **Detects Window Location** - Determines which display contains the window
|
|
378
|
+
2. **Converts Coordinates** - Translates global coordinates to display-relative coordinates
|
|
379
|
+
3. **Sets Display ID** - Automatically selects the correct display for recording
|
|
380
|
+
4. **Handles Multi-Monitor** - Works seamlessly across multiple displays
|
|
381
|
+
|
|
382
|
+
```javascript
|
|
383
|
+
// Window at (-2000, 100) on second display
|
|
384
|
+
// Automatically converts to (440, 100) on display 1
|
|
385
|
+
await recorder.startRecording("./auto-display.mov", {
|
|
386
|
+
windowId: 12345, // Package handles display detection automatically
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Smart Window Filtering
|
|
391
|
+
|
|
392
|
+
The `getWindows()` method automatically filters out:
|
|
393
|
+
|
|
394
|
+
- System windows (Dock, Menu Bar)
|
|
395
|
+
- Hidden windows
|
|
396
|
+
- Very small windows (< 50x50 pixels)
|
|
397
|
+
- Windows without names
|
|
398
|
+
|
|
399
|
+
### Performance Optimization
|
|
400
|
+
|
|
401
|
+
- **Native Implementation** - Uses AVFoundation for optimal performance
|
|
402
|
+
- **Minimal Overhead** - Low CPU usage during recording
|
|
403
|
+
- **Memory Efficient** - Proper memory management in native layer
|
|
404
|
+
- **Quality Presets** - Balanced quality/performance options
|
|
405
|
+
|
|
406
|
+
## Troubleshooting
|
|
407
|
+
|
|
408
|
+
### Permission Issues
|
|
409
|
+
|
|
410
|
+
If recording fails, check macOS permissions:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
# Open System Preferences > Security & Privacy > Screen Recording
|
|
414
|
+
# Ensure your app/terminal has permission
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Build Errors
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
# Reinstall with verbose output
|
|
421
|
+
npm install node-mac-recorder --verbose
|
|
422
|
+
|
|
423
|
+
# Clear npm cache
|
|
424
|
+
npm cache clean --force
|
|
425
|
+
|
|
426
|
+
# Ensure Xcode tools are installed
|
|
427
|
+
xcode-select --install
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Recording Issues
|
|
431
|
+
|
|
432
|
+
1. **Empty/Black Video**: Check screen recording permissions
|
|
433
|
+
2. **No Audio**: Verify audio permissions and device availability
|
|
434
|
+
3. **Window Not Found**: Ensure target window is visible and not minimized
|
|
435
|
+
4. **Coordinate Issues**: Window may be on different display (handled automatically)
|
|
436
|
+
|
|
437
|
+
### Debug Information
|
|
438
|
+
|
|
439
|
+
```javascript
|
|
440
|
+
// Get module information
|
|
441
|
+
const info = recorder.getModuleInfo();
|
|
442
|
+
console.log("Module info:", info);
|
|
443
|
+
|
|
444
|
+
// Check recording status
|
|
445
|
+
const status = recorder.getStatus();
|
|
446
|
+
console.log("Recording status:", status);
|
|
447
|
+
|
|
448
|
+
// Verify permissions
|
|
449
|
+
const permissions = await recorder.checkPermissions();
|
|
450
|
+
console.log("Permissions:", permissions);
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
## Performance Considerations
|
|
454
|
+
|
|
455
|
+
- **Recording Quality**: Higher quality increases file size and CPU usage
|
|
456
|
+
- **Frame Rate**: 30fps recommended for most use cases, 60fps for smooth motion
|
|
457
|
+
- **Audio**: System audio capture adds minimal overhead
|
|
458
|
+
- **Window Recording**: Slightly more efficient than full-screen recording
|
|
459
|
+
- **Multi-Display**: No significant performance impact
|
|
460
|
+
|
|
461
|
+
## File Formats
|
|
462
|
+
|
|
463
|
+
- **Output Format**: MOV (QuickTime)
|
|
464
|
+
- **Video Codec**: H.264
|
|
465
|
+
- **Audio Codec**: AAC
|
|
466
|
+
- **Container**: QuickTime compatible
|
|
467
|
+
|
|
468
|
+
## Contributing
|
|
469
|
+
|
|
470
|
+
1. Fork the repository
|
|
471
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
472
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
473
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
474
|
+
5. Open a Pull Request
|
|
475
|
+
|
|
476
|
+
## License
|
|
477
|
+
|
|
478
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
479
|
+
|
|
480
|
+
## Changelog
|
|
481
|
+
|
|
482
|
+
### Latest Updates
|
|
483
|
+
|
|
484
|
+
- ✅ **Window Recording**: Automatic coordinate conversion for multi-display setups
|
|
485
|
+
- ✅ **Audio Controls**: Separate microphone and system audio controls
|
|
486
|
+
- ✅ **Display Selection**: Multi-monitor support with automatic detection
|
|
487
|
+
- ✅ **Smart Filtering**: Improved window detection and filtering
|
|
488
|
+
- ✅ **Performance**: Optimized native implementation
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
**Made for macOS** 🍎 | **Built with AVFoundation** 📹 | **Node.js Ready** 🚀
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "mac_recorder",
|
|
5
|
+
"sources": [
|
|
6
|
+
"src/mac_recorder.mm",
|
|
7
|
+
"src/screen_capture.mm",
|
|
8
|
+
"src/audio_capture.mm"
|
|
9
|
+
],
|
|
10
|
+
"include_dirs": [
|
|
11
|
+
"<!@(node -p \"require('node-addon-api').include\")"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": [
|
|
14
|
+
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
15
|
+
],
|
|
16
|
+
"cflags!": [ "-fno-exceptions" ],
|
|
17
|
+
"cflags_cc!": [ "-fno-exceptions" ],
|
|
18
|
+
"xcode_settings": {
|
|
19
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
20
|
+
"CLANG_CXX_LIBRARY": "libc++",
|
|
21
|
+
"MACOSX_DEPLOYMENT_TARGET": "10.14",
|
|
22
|
+
"OTHER_CFLAGS": [
|
|
23
|
+
"-ObjC++"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"link_settings": {
|
|
27
|
+
"libraries": [
|
|
28
|
+
"-framework AVFoundation",
|
|
29
|
+
"-framework CoreMedia",
|
|
30
|
+
"-framework CoreVideo",
|
|
31
|
+
"-framework Foundation",
|
|
32
|
+
"-framework AppKit",
|
|
33
|
+
"-framework ScreenCaptureKit"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|