node-mac-recorder 2.15.3 โ 2.15.5
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/.claude/settings.local.json +2 -1
- package/package.json +1 -1
- package/src/mac_recorder.mm +31 -4
- package/src/screen_capture_kit.mm +5 -19
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''''๐ Debugging frame writing...'''');\nconst MacRecorder = require(''''./index'''');\nconst recorder = new MacRecorder();\n\nasync function debugFrameWriting() {\n try {\n const outputPath = ''''./test-output/frame-debug.mov'''';\n console.log(''''๐น Starting debug test...'''');\n \n const success = await recorder.startRecording(outputPath);\n \n if (success) {\n console.log(''''โฑ๏ธ Recording for 2 seconds...'''');\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(''''๐ Stopping...'''');\n await recorder.stopRecording();\n \n // Wait for finalization\n await new Promise(resolve => setTimeout(resolve, 1000));\n \n } else {\n console.log(''''โ Failed to start'''');\n }\n } catch (error) {\n console.log(''''โ Error:'''', error);\n }\n}\n\ndebugFrameWriting();\n\")",
|
|
35
35
|
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐ Testing with proper permissions and Electron env'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function test() {\n try {\n const outputPath = ''./test-output/crash-test.mov'';\n console.log(''๐น Starting recording...'');\n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\n includeMicrophone: false,\n includeSystemAudio: false\n });\n \n if (success) {\n console.log(''โ
Recording started - waiting 3 seconds'');\n await new Promise(resolve => setTimeout(resolve, 3000));\n console.log(''๐ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''โ
Test completed without crash'');\n } else {\n console.log(''โ Recording start failed'');\n }\n } catch (error) {\n console.log(''โ Error:'', error.message);\n console.log(''Stack:'', error.stack);\n }\n}\n\ntest();\n\")",
|
|
36
36
|
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐ Debugging frame writing...'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function debugFrameWriting() {\n try {\n const outputPath = ''./test-output/frame-debug.mov'';\n console.log(''๐น Starting debug test...'');\n \n const success = await recorder.startRecording(outputPath);\n \n if (success) {\n console.log(''โฑ๏ธ Recording for 2 seconds...'');\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(''๐ Stopping...'');\n await recorder.stopRecording();\n \n // Wait for finalization\n await new Promise(resolve => setTimeout(resolve, 1000));\n \n } else {\n console.log(''โ Failed to start'');\n }\n } catch (error) {\n console.log(''โ Error:'', error);\n }\n}\n\ndebugFrameWriting();\n\")",
|
|
37
|
-
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐งช Testing without AVFoundation - Pure ScreenCaptureKit'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function testPureScreenCaptureKit() {\n try {\n const outputPath = ''./test-output/pure-sck.mov'';\n console.log(''๐น Starting pure ScreenCaptureKit test...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\n includeMicrophone: false,\n includeSystemAudio: false\n });\n \n if (success) {\n console.log(''โ
Recording started - waiting 2 seconds'');\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(''๐ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''โ
Pure ScreenCaptureKit test completed successfully!'');\n } else {\n console.log(''โ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โ Error:'', error.message);\n console.log(''Stack:'', error.stack);\n }\n}\n\ntestPureScreenCaptureKit();\n\")"
|
|
37
|
+
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐งช Testing without AVFoundation - Pure ScreenCaptureKit'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function testPureScreenCaptureKit() {\n try {\n const outputPath = ''./test-output/pure-sck.mov'';\n console.log(''๐น Starting pure ScreenCaptureKit test...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\n includeMicrophone: false,\n includeSystemAudio: false\n });\n \n if (success) {\n console.log(''โ
Recording started - waiting 2 seconds'');\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(''๐ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''โ
Pure ScreenCaptureKit test completed successfully!'');\n } else {\n console.log(''โ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โ Error:'', error.message);\n console.log(''Stack:'', error.stack);\n }\n}\n\ntestPureScreenCaptureKit();\n\")",
|
|
38
|
+
"Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐ต Testing audio + crop area recording'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function testAudioCropRecording() {\n try {\n const outputPath = ''./test-output/audio-crop-test.mov'';\n console.log(''๐น Starting recording with audio and crop area...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: false,\n includeMicrophone: true,\n includeSystemAudio: true,\n captureArea: {\n x: 100, \n y: 100,\n width: 800,\n height: 600\n }\n });\n \n if (success) {\n console.log(''โ
Recording started - waiting 3 seconds'');\n await new Promise(resolve => setTimeout(resolve, 3000));\n \n console.log(''๐ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''โ
Audio + crop test completed successfully!'');\n } else {\n console.log(''โ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โ Error:'', error.message);\n }\n}\n\ntestAudioCropRecording();\n\")"
|
|
38
39
|
],
|
|
39
40
|
"deny": []
|
|
40
41
|
}
|
package/package.json
CHANGED
package/src/mac_recorder.mm
CHANGED
|
@@ -401,10 +401,37 @@ Napi::Value GetAudioDevices(const Napi::CallbackInfo& info) {
|
|
|
401
401
|
for (NSUInteger i = 0; i < devices.count; i++) {
|
|
402
402
|
NSDictionary *device = devices[i];
|
|
403
403
|
Napi::Object deviceObj = Napi::Object::New(env);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
404
|
+
|
|
405
|
+
// Safe string conversion with null checks
|
|
406
|
+
NSString *deviceId = device[@"id"];
|
|
407
|
+
NSString *deviceName = device[@"name"];
|
|
408
|
+
NSString *deviceManufacturer = device[@"manufacturer"];
|
|
409
|
+
NSNumber *isDefault = device[@"isDefault"];
|
|
410
|
+
|
|
411
|
+
if (deviceId && [deviceId isKindOfClass:[NSString class]]) {
|
|
412
|
+
deviceObj.Set("id", Napi::String::New(env, [deviceId UTF8String]));
|
|
413
|
+
} else {
|
|
414
|
+
deviceObj.Set("id", Napi::String::New(env, "default"));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (deviceName && [deviceName isKindOfClass:[NSString class]]) {
|
|
418
|
+
deviceObj.Set("name", Napi::String::New(env, [deviceName UTF8String]));
|
|
419
|
+
} else {
|
|
420
|
+
deviceObj.Set("name", Napi::String::New(env, "Default Audio Device"));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (deviceManufacturer && [deviceManufacturer isKindOfClass:[NSString class]]) {
|
|
424
|
+
deviceObj.Set("manufacturer", Napi::String::New(env, [deviceManufacturer UTF8String]));
|
|
425
|
+
} else {
|
|
426
|
+
deviceObj.Set("manufacturer", Napi::String::New(env, "System"));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (isDefault && [isDefault isKindOfClass:[NSNumber class]]) {
|
|
430
|
+
deviceObj.Set("isDefault", Napi::Boolean::New(env, [isDefault boolValue]));
|
|
431
|
+
} else {
|
|
432
|
+
deviceObj.Set("isDefault", Napi::Boolean::New(env, true));
|
|
433
|
+
}
|
|
434
|
+
|
|
408
435
|
result[i] = deviceObj;
|
|
409
436
|
}
|
|
410
437
|
|
|
@@ -182,21 +182,9 @@ static NSString *g_outputPath = nil;
|
|
|
182
182
|
NSLog(@"๐ฅ Pure ScreenCapture config: %ldx%ld @ 30fps, cursor=%d",
|
|
183
183
|
recordingWidth, recordingHeight, shouldShowCursor);
|
|
184
184
|
|
|
185
|
-
// AUDIO SUPPORT -
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (@available(macOS 13.0, *)) {
|
|
190
|
-
if (shouldCaptureMic || shouldCaptureSystemAudio) {
|
|
191
|
-
streamConfig.capturesAudio = YES;
|
|
192
|
-
streamConfig.sampleRate = 44100;
|
|
193
|
-
streamConfig.channelCount = 2;
|
|
194
|
-
NSLog(@"๐ต Audio enabled: mic=%d system=%d", shouldCaptureMic, shouldCaptureSystemAudio);
|
|
195
|
-
} else {
|
|
196
|
-
streamConfig.capturesAudio = NO;
|
|
197
|
-
NSLog(@"๐ Audio disabled");
|
|
198
|
-
}
|
|
199
|
-
}
|
|
185
|
+
// AUDIO SUPPORT - Disabled for Electron stability
|
|
186
|
+
NSLog(@"๐ Audio capture disabled for Electron compatibility");
|
|
187
|
+
streamConfig.capturesAudio = NO;
|
|
200
188
|
|
|
201
189
|
// Create pure ScreenCaptureKit recording output
|
|
202
190
|
NSURL *outputURL = [NSURL fileURLWithPath:g_outputPath];
|
|
@@ -206,14 +194,12 @@ static NSString *g_outputPath = nil;
|
|
|
206
194
|
recordingConfig.outputURL = outputURL;
|
|
207
195
|
recordingConfig.videoCodecType = AVVideoCodecTypeH264;
|
|
208
196
|
|
|
209
|
-
// Audio
|
|
210
|
-
// Note: Specific audio routing handled by ScreenCaptureKit automatically
|
|
197
|
+
// Audio disabled for Electron stability
|
|
211
198
|
|
|
212
199
|
// Create recording output with correct initializer
|
|
213
200
|
g_recordingOutput = [[SCRecordingOutput alloc] initWithConfiguration:recordingConfig
|
|
214
201
|
delegate:nil];
|
|
215
|
-
NSLog(@"๐ง Created SCRecordingOutput
|
|
216
|
-
shouldCaptureMic, shouldCaptureSystemAudio);
|
|
202
|
+
NSLog(@"๐ง Created SCRecordingOutput (audio disabled for Electron)");
|
|
217
203
|
}
|
|
218
204
|
|
|
219
205
|
if (!g_recordingOutput) {
|