node-mac-recorder 2.15.5 โ†’ 2.15.7

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.
@@ -35,7 +35,11 @@
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
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
+ "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\")",
39
+ "Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐Ÿงช Testing crash fix with null path protection'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function testCrashFix() {\n try {\n const outputPath = ''./test-output/crash-fix-test.mov'';\n console.log(''๐Ÿ“น Starting crash fix test...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\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(''โœ… Crash fix 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\ntestCrashFix();\n\")",
40
+ "Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐Ÿ Final stability test with all features'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function finalTest() {\n try {\n const outputPath = ''./test-output/final-stability-test.mov'';\n console.log(''๐Ÿ“น Starting final stability test...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\n includeMicrophone: true,\n includeSystemAudio: true,\n captureArea: {\n x: 200,\n y: 200,\n width: 600,\n height: 400\n }\n });\n \n if (success) {\n console.log(''โœ… Recording started - waiting 4 seconds'');\n await new Promise(resolve => setTimeout(resolve, 4000));\n \n console.log(''๐Ÿ›‘ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''๐ŸŽ‰ FINAL TEST COMPLETED SUCCESSFULLY - NO CRASH!'');\n } else {\n console.log(''โŒ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โŒ Error:'', error.message);\n }\n}\n\nfinalTest();\n\")",
41
+ "Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐ŸŽต Testing system audio only recording'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function testSystemAudio() {\n try {\n const outputPath = ''./test-output/system-audio-only.mov'';\n console.log(''๐Ÿ“น Starting system audio only recording...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: false,\n includeMicrophone: false, // Mikrophone DEVRE DIลžI \n includeSystemAudio: true, // Sadece sistem sesi Aร‡IK\n });\n \n if (success) {\n console.log(''โœ… System audio recording started - waiting 4 seconds'');\n await new Promise(resolve => setTimeout(resolve, 4000));\n \n console.log(''๐Ÿ›‘ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''โœ… System audio test completed!'');\n } else {\n console.log(''โŒ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โŒ Error:'', error.message);\n }\n}\n\ntestSystemAudio();\n\")",
42
+ "Bash(ELECTRON_RUN_AS_NODE=1 node -e \"\nconsole.log(''๐Ÿ Final stability test with all features'');\nconst MacRecorder = require(''./index'');\nconst recorder = new MacRecorder();\n\nasync function finalTest() {\n try {\n const outputPath = ''./test-output/final-stability-test.mov'';\n console.log(''๐Ÿ“น Starting final stability test...'');\n \n const success = await recorder.startRecording(outputPath, {\n captureCursor: true,\n includeMicrophone: false,\n includeSystemAudio: true,\n captureArea: {\n x: 200,\n y: 200,\n width: 600,\n height: 400\n }\n });\n \n if (success) {\n console.log(''โœ… Recording started - waiting 4 seconds'');\n await new Promise(resolve => setTimeout(resolve, 4000));\n \n console.log(''๐Ÿ›‘ Stopping recording...'');\n await recorder.stopRecording();\n console.log(''๐ŸŽ‰ FINAL TEST COMPLETED SUCCESSFULLY - NO CRASH!'');\n } else {\n console.log(''โŒ Recording failed to start'');\n }\n } catch (error) {\n console.log(''โŒ Error:'', error.message);\n }\n}\n\nfinalTest();\n\")"
39
43
  ],
40
44
  "deny": []
41
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.15.5",
3
+ "version": "2.15.7",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -58,7 +58,12 @@ static NSString *g_outputPath = nil;
58
58
  g_isCleaningUp = NO;
59
59
  }
60
60
 
61
- g_outputPath = config[@"outputPath"];
61
+ NSString *outputPath = config[@"outputPath"];
62
+ if (!outputPath || [outputPath length] == 0) {
63
+ NSLog(@"โŒ Invalid output path provided");
64
+ return NO;
65
+ }
66
+ g_outputPath = outputPath;
62
67
 
63
68
  // Extract configuration options
64
69
  NSNumber *displayId = config[@"displayId"];
@@ -182,24 +187,60 @@ static NSString *g_outputPath = nil;
182
187
  NSLog(@"๐ŸŽฅ Pure ScreenCapture config: %ldx%ld @ 30fps, cursor=%d",
183
188
  recordingWidth, recordingHeight, shouldShowCursor);
184
189
 
185
- // AUDIO SUPPORT - Disabled for Electron stability
186
- NSLog(@"๐Ÿ”‡ Audio capture disabled for Electron compatibility");
187
- streamConfig.capturesAudio = NO;
190
+ // AUDIO SUPPORT - Enable only for system audio in Electron
191
+ BOOL shouldCaptureMic = includeMicrophone ? [includeMicrophone boolValue] : NO;
192
+ BOOL shouldCaptureSystemAudio = includeSystemAudio ? [includeSystemAudio boolValue] : NO;
193
+
194
+ // Only enable system audio, mic causes crashes in Electron
195
+ if (@available(macOS 13.0, *)) {
196
+ if (shouldCaptureSystemAudio && !shouldCaptureMic) {
197
+ streamConfig.capturesAudio = YES;
198
+ streamConfig.sampleRate = 44100;
199
+ streamConfig.channelCount = 2;
200
+ NSLog(@"๐ŸŽต System audio only enabled (safe for Electron)");
201
+ } else if (shouldCaptureMic) {
202
+ NSLog(@"๐Ÿšซ Microphone audio disabled in Electron for stability");
203
+ streamConfig.capturesAudio = NO;
204
+ } else {
205
+ streamConfig.capturesAudio = NO;
206
+ NSLog(@"๐Ÿ”‡ Audio disabled");
207
+ }
208
+ } else {
209
+ streamConfig.capturesAudio = NO;
210
+ NSLog(@"๐Ÿ”‡ Audio disabled (macOS < 13.0)");
211
+ }
188
212
 
189
213
  // Create pure ScreenCaptureKit recording output
190
- NSURL *outputURL = [NSURL fileURLWithPath:g_outputPath];
214
+ // Use local copy to prevent race conditions
215
+ NSString *safeOutputPath = outputPath; // Local variable from outer scope
216
+ if (!safeOutputPath || [safeOutputPath length] == 0) {
217
+ NSLog(@"โŒ Output path is nil or empty");
218
+ return;
219
+ }
220
+
221
+ NSURL *outputURL = [NSURL fileURLWithPath:safeOutputPath];
222
+ if (!outputURL) {
223
+ NSLog(@"โŒ Failed to create output URL from path: %@", safeOutputPath);
224
+ return;
225
+ }
226
+
191
227
  if (@available(macOS 15.0, *)) {
192
228
  // Create recording output configuration
193
229
  SCRecordingOutputConfiguration *recordingConfig = [[SCRecordingOutputConfiguration alloc] init];
194
230
  recordingConfig.outputURL = outputURL;
195
231
  recordingConfig.videoCodecType = AVVideoCodecTypeH264;
196
232
 
197
- // Audio disabled for Electron stability
233
+ // Audio configuration - using available properties
234
+ // Note: Specific audio routing handled by ScreenCaptureKit automatically
198
235
 
199
236
  // Create recording output with correct initializer
200
237
  g_recordingOutput = [[SCRecordingOutput alloc] initWithConfiguration:recordingConfig
201
238
  delegate:nil];
202
- NSLog(@"๐Ÿ”ง Created SCRecordingOutput (audio disabled for Electron)");
239
+ if (shouldCaptureSystemAudio && !shouldCaptureMic) {
240
+ NSLog(@"๐Ÿ”ง Created SCRecordingOutput with system audio only");
241
+ } else {
242
+ NSLog(@"๐Ÿ”ง Created SCRecordingOutput (audio disabled)");
243
+ }
203
244
  }
204
245
 
205
246
  if (!g_recordingOutput) {