node-mac-recorder 2.15.11 → 2.15.12
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/package.json +1 -1
- package/src/mac_recorder.mm +19 -11
- package/src/screen_capture_kit.mm +10 -0
- package/test-display-id-debug.js +42 -0
- package/test-electron-env.js +38 -0
package/package.json
CHANGED
package/src/mac_recorder.mm
CHANGED
|
@@ -168,9 +168,14 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
|
|
|
168
168
|
if (@available(macOS 12.3, *)) {
|
|
169
169
|
NSLog(@"✅ macOS 12.3+ detected - ScreenCaptureKit should be available");
|
|
170
170
|
|
|
171
|
-
//
|
|
171
|
+
// Check if running in Electron environment
|
|
172
|
+
BOOL isElectron = (getenv("ELECTRON_RUN_AS_NODE") != NULL ||
|
|
173
|
+
[[NSProcessInfo processInfo].processName containsString:@"Electron"] ||
|
|
174
|
+
[[NSBundle mainBundle].bundleIdentifier containsString:@"electron"]);
|
|
175
|
+
|
|
176
|
+
// Try ScreenCaptureKit with extensive safety measures (skip in Electron due to compatibility issues)
|
|
172
177
|
@try {
|
|
173
|
-
if ([ScreenCaptureKitRecorder isScreenCaptureKitAvailable]) {
|
|
178
|
+
if (!isElectron && [ScreenCaptureKitRecorder isScreenCaptureKitAvailable]) {
|
|
174
179
|
NSLog(@"✅ ScreenCaptureKit availability check passed");
|
|
175
180
|
NSLog(@"🎯 Using ScreenCaptureKit - overlay windows will be automatically excluded");
|
|
176
181
|
|
|
@@ -229,22 +234,25 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
|
|
|
229
234
|
}
|
|
230
235
|
|
|
231
236
|
NSLog(@"❌ ScreenCaptureKit failed or unsafe");
|
|
232
|
-
|
|
237
|
+
// Fall through to AVFoundation
|
|
233
238
|
} else {
|
|
234
|
-
NSLog(@"❌ ScreenCaptureKit
|
|
235
|
-
NSLog(@"❌ ScreenCaptureKit not available");
|
|
239
|
+
NSLog(@"❌ ScreenCaptureKit not available - falling back to AVFoundation");
|
|
236
240
|
}
|
|
237
241
|
} @catch (NSException *availabilityException) {
|
|
238
|
-
NSLog(@"
|
|
239
|
-
|
|
242
|
+
NSLog(@"⚠️ Exception during ScreenCaptureKit check: %@", availabilityException.reason);
|
|
243
|
+
if (isElectron) {
|
|
244
|
+
NSLog(@"🔄 Expected in Electron - using AVFoundation fallback");
|
|
245
|
+
} else {
|
|
246
|
+
NSLog(@"🔄 Falling back to AVFoundation");
|
|
247
|
+
}
|
|
240
248
|
}
|
|
241
249
|
} else {
|
|
242
|
-
NSLog(@"
|
|
243
|
-
return Napi::Boolean::New(env, false);
|
|
250
|
+
NSLog(@"⚠️ macOS version < 12.3 - ScreenCaptureKit not available, falling back to AVFoundation");
|
|
244
251
|
}
|
|
245
252
|
|
|
246
|
-
// If we get here, ScreenCaptureKit failed
|
|
247
|
-
NSLog(@"
|
|
253
|
+
// If we get here, ScreenCaptureKit failed - use AVFoundation fallback
|
|
254
|
+
NSLog(@"🔄 ScreenCaptureKit failed - using AVFoundation fallback");
|
|
255
|
+
NSLog(@"❌ AVFoundation recording not implemented in this version");
|
|
248
256
|
return Napi::Boolean::New(env, false);
|
|
249
257
|
|
|
250
258
|
} @catch (NSException *exception) {
|
|
@@ -121,15 +121,25 @@ static NSString *g_outputPath = nil;
|
|
|
121
121
|
|
|
122
122
|
if (displayId && [displayId integerValue] != 0) {
|
|
123
123
|
// Find specific display
|
|
124
|
+
NSLog(@"🔍 Looking for display ID: %@", displayId);
|
|
125
|
+
NSLog(@"📋 Available displays:");
|
|
124
126
|
for (SCDisplay *display in content.displays) {
|
|
127
|
+
NSLog(@" - Display %u: %dx%d", display.displayID, (int)display.width, (int)display.height);
|
|
125
128
|
if (display.displayID == [displayId unsignedIntValue]) {
|
|
126
129
|
targetDisplay = display;
|
|
130
|
+
NSLog(@"✅ Found matching display %u", display.displayID);
|
|
127
131
|
break;
|
|
128
132
|
}
|
|
129
133
|
}
|
|
134
|
+
|
|
135
|
+
if (!targetDisplay) {
|
|
136
|
+
NSLog(@"❌ Display ID %@ not found in ScreenCaptureKit displays", displayId);
|
|
137
|
+
NSLog(@"🔧 Available IDs: %@", [content.displays valueForKey:@"displayID"]);
|
|
138
|
+
}
|
|
130
139
|
} else {
|
|
131
140
|
// Use first display
|
|
132
141
|
targetDisplay = content.displays.firstObject;
|
|
142
|
+
NSLog(@"📺 Using first available display: %u", targetDisplay.displayID);
|
|
133
143
|
}
|
|
134
144
|
|
|
135
145
|
if (!targetDisplay) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const MacRecorder = require('./index');
|
|
2
|
+
|
|
3
|
+
async function testDisplayIdDebug() {
|
|
4
|
+
console.log('🔍 Testing display ID debugging...');
|
|
5
|
+
|
|
6
|
+
const recorder = new MacRecorder();
|
|
7
|
+
const displays = await recorder.getDisplays();
|
|
8
|
+
|
|
9
|
+
console.log('📊 JavaScript display IDs:');
|
|
10
|
+
displays.forEach(display => {
|
|
11
|
+
console.log(` ${display.name}: ID=${display.id} ${display.isPrimary ? '[PRIMARY]' : ''}`);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Test recording on secondary display to trigger the debug logs
|
|
15
|
+
const secondaryDisplay = displays.find(d => !d.isPrimary);
|
|
16
|
+
if (secondaryDisplay) {
|
|
17
|
+
console.log(`\n🎯 Testing recording on ${secondaryDisplay.name} (ID: ${secondaryDisplay.id})`);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await recorder.startRecording('./test-output/display-id-debug.mov', {
|
|
21
|
+
displayId: secondaryDisplay.id,
|
|
22
|
+
captureCursor: true,
|
|
23
|
+
includeMicrophone: false,
|
|
24
|
+
includeSystemAudio: false
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log('✅ Recording started - check native logs for display ID matching');
|
|
28
|
+
|
|
29
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
30
|
+
|
|
31
|
+
await recorder.stopRecording();
|
|
32
|
+
console.log('✅ Recording completed');
|
|
33
|
+
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.log(`❌ Recording failed: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
console.log('⚠️ No secondary display found');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
testDisplayIdDebug();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const MacRecorder = require('./index');
|
|
2
|
+
|
|
3
|
+
// Simulate Electron environment
|
|
4
|
+
process.env.ELECTRON_RUN_AS_NODE = '1';
|
|
5
|
+
|
|
6
|
+
async function testElectronFallback() {
|
|
7
|
+
console.log('🔋 Testing Electron environment fallback...');
|
|
8
|
+
console.log('Environment variables:');
|
|
9
|
+
console.log(' ELECTRON_RUN_AS_NODE:', process.env.ELECTRON_RUN_AS_NODE);
|
|
10
|
+
|
|
11
|
+
const recorder = new MacRecorder();
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
console.log('\n🎯 Attempting to start recording in simulated Electron environment...');
|
|
15
|
+
|
|
16
|
+
await recorder.startRecording('./test-output/electron-fallback-test.mov', {
|
|
17
|
+
displayId: 1,
|
|
18
|
+
captureCursor: true,
|
|
19
|
+
includeMicrophone: false,
|
|
20
|
+
includeSystemAudio: false
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
console.log('✅ Recording started (unexpected - should have failed)');
|
|
24
|
+
|
|
25
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
26
|
+
|
|
27
|
+
await recorder.stopRecording();
|
|
28
|
+
console.log('✅ Recording completed');
|
|
29
|
+
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.log(`❌ Recording failed as expected in Electron: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
testElectronFallback().finally(() => {
|
|
36
|
+
// Clean up
|
|
37
|
+
delete process.env.ELECTRON_RUN_AS_NODE;
|
|
38
|
+
});
|