node-mac-recorder 2.16.24 โ†’ 2.16.26

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(FORCE_AVFOUNDATION=1 node -e \"\nconsole.log(''๐Ÿงช Testing external display recording WITH AUDIO - debug version...'');\nconst MacRecorder = require(''./index.js'');\nconst recorder = new MacRecorder();\n\nrecorder.startRecording(''/tmp/external-audio-debug.mov'', {\n displayId: 3, // External display\n includeMicrophone: true,\n includeSystemAudio: true,\n captureCursor: true\n})\n .then(success => {\n console.log(''Start result:'', success ? ''โœ… SUCCESS'' : ''โŒ FAILED'');\n if (success) {\n setTimeout(() => {\n console.log(''โน๏ธ Stopping recording...'');\n recorder.stopRecording().then(() => {\n console.log(''โœ… Recording stopped'');\n const fs = require(''fs'');\n if (fs.existsSync(''/tmp/external-audio-debug.mov'')) {\n const size = Math.round(fs.statSync(''/tmp/external-audio-debug.mov'').size/1024);\n console.log(''๐Ÿ“น File size:'', size + ''KB'');\n if (size > 100) {\n console.log(''๐ŸŽ‰ External display recording with audio SUCCESS!'');\n } else {\n console.log(''โš ๏ธ File too small, may have failed'');\n }\n } else {\n console.log(''โŒ No output file created'');\n }\n });\n }, 4000); // 4 seconds recording\n }\n })\n .catch(console.error);\n\")"
4
+ "Bash(FORCE_AVFOUNDATION=1 node test-sequential.js)"
5
5
  ],
6
6
  "deny": [],
7
7
  "ask": []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.16.24",
3
+ "version": "2.16.26",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -567,50 +567,24 @@ Napi::Value GetDisplays(const Napi::CallbackInfo& info) {
567
567
  Napi::Env env = info.Env();
568
568
 
569
569
  @try {
570
- // Get displays using NSScreen instead of ScreenCapture
571
- NSArray *screens = [NSScreen screens];
570
+ // Get active displays directly using CGDirectDisplayID
572
571
  NSMutableArray *displays = [NSMutableArray array];
573
-
574
- // Get real CGDirectDisplayIDs first
575
572
  CGDirectDisplayID activeDisplays[32];
576
573
  uint32_t displayCount;
577
574
  CGGetActiveDisplayList(32, activeDisplays, &displayCount);
578
575
 
579
- for (NSUInteger i = 0; i < [screens count]; i++) {
580
- NSScreen *screen = [screens objectAtIndex:i];
581
- NSRect frame = [screen frame];
582
-
583
- // Find matching CGDirectDisplayID
584
- CGDirectDisplayID displayID = 0;
585
- bool isPrimary = false;
586
-
587
- for (uint32_t j = 0; j < displayCount; j++) {
588
- CGDirectDisplayID candidateID = activeDisplays[j];
589
- CGRect displayBounds = CGDisplayBounds(candidateID);
590
-
591
- if (fabs(frame.origin.x - displayBounds.origin.x) < 1.0 &&
592
- fabs(frame.origin.y - displayBounds.origin.y) < 1.0 &&
593
- fabs(frame.size.width - displayBounds.size.width) < 1.0 &&
594
- fabs(frame.size.height - displayBounds.size.height) < 1.0) {
595
- displayID = candidateID;
596
- isPrimary = (candidateID == CGMainDisplayID());
597
- break;
598
- }
599
- }
600
-
601
- // Fallback if no match found
602
- if (displayID == 0 && i < displayCount) {
603
- displayID = activeDisplays[i];
604
- isPrimary = (displayID == CGMainDisplayID());
605
- }
576
+ for (uint32_t i = 0; i < displayCount; i++) {
577
+ CGDirectDisplayID displayID = activeDisplays[i];
578
+ CGRect displayBounds = CGDisplayBounds(displayID);
579
+ bool isPrimary = (displayID == CGMainDisplayID());
606
580
 
607
581
  NSDictionary *displayInfo = @{
608
- @"id": @(displayID), // Use real display ID
609
- @"name": [NSString stringWithFormat:@"Display %lu", (unsigned long)(i + 1)],
610
- @"width": @((int)frame.size.width),
611
- @"height": @((int)frame.size.height),
612
- @"x": @((int)frame.origin.x),
613
- @"y": @((int)frame.origin.y),
582
+ @"id": @(displayID), // Direct CGDirectDisplayID
583
+ @"name": [NSString stringWithFormat:@"Display %u", (unsigned int)(i + 1)],
584
+ @"width": @((int)displayBounds.size.width),
585
+ @"height": @((int)displayBounds.size.height),
586
+ @"x": @((int)displayBounds.origin.x),
587
+ @"y": @((int)displayBounds.origin.y),
614
588
  @"isPrimary": @(isPrimary)
615
589
  };
616
590
  [displays addObject:displayInfo];
@@ -329,7 +329,6 @@ static NSString *g_outputPath = nil;
329
329
  }
330
330
 
331
331
  NSLog(@"๐Ÿ›‘ Stopping pure ScreenCaptureKit recording");
332
- g_isCleaningUp = YES;
333
332
 
334
333
  // Store stream reference to prevent it from being deallocated
335
334
  SCStream *streamToStop = g_stream;
@@ -340,11 +339,12 @@ static NSString *g_outputPath = nil;
340
339
  }
341
340
  NSLog(@"โœ… Pure stream stopped");
342
341
 
342
+ // Immediately reset recording state to allow new recordings
343
+ g_isRecording = NO;
344
+
343
345
  // Finalize on main queue to prevent threading issues
344
346
  dispatch_async(dispatch_get_main_queue(), ^{
345
- if (g_isCleaningUp) { // Only finalize if we initiated cleanup
346
- [ScreenCaptureKitRecorder finalizeRecording];
347
- }
347
+ [ScreenCaptureKitRecorder cleanupVideoWriter];
348
348
  });
349
349
  }];
350
350
  }
@@ -360,13 +360,10 @@ static NSString *g_outputPath = nil;
360
360
 
361
361
  + (void)finalizeRecording {
362
362
  @synchronized([ScreenCaptureKitRecorder class]) {
363
- if (g_isCleaningUp && g_isRecording == NO) {
364
- NSLog(@"โš ๏ธ Already finalizing, skipping duplicate call");
365
- return;
366
- }
367
-
368
363
  NSLog(@"๐ŸŽฌ Finalizing pure ScreenCaptureKit recording");
369
364
 
365
+ // Set cleanup flag now that we're actually cleaning up
366
+ g_isCleaningUp = YES;
370
367
  g_isRecording = NO;
371
368
 
372
369
  if (g_recordingOutput) {
@@ -2360,33 +2360,35 @@ Napi::Value GetSelectedWindowInfo(const Napi::CallbackInfo& info) {
2360
2360
  windowScreen = mainScreen;
2361
2361
  }
2362
2362
 
2363
- // CRITICAL FIX: Add screen information using real CGDirectDisplayID
2363
+ // Convert NSScreen to CGDirectDisplayID properly
2364
2364
  NSRect screenFrame = [windowScreen frame];
2365
+ NSNumber *screenNumber = [windowScreen deviceDescription][@"NSScreenNumber"];
2365
2366
 
2366
- // Find real CGDirectDisplayID for this screen (matching GetDisplays logic)
2367
- CGDirectDisplayID realDisplayID = 0;
2367
+ // Find the actual CGDirectDisplayID that matches this screen's frame
2368
+ CGDirectDisplayID displayID = 0;
2368
2369
  CGDirectDisplayID activeDisplays[32];
2369
2370
  uint32_t displayCount;
2370
2371
  CGGetActiveDisplayList(32, activeDisplays, &displayCount);
2371
2372
 
2372
- for (uint32_t j = 0; j < displayCount; j++) {
2373
- CGDirectDisplayID candidateID = activeDisplays[j];
2373
+ for (uint32_t i = 0; i < displayCount; i++) {
2374
+ CGDirectDisplayID candidateID = activeDisplays[i];
2374
2375
  CGRect displayBounds = CGDisplayBounds(candidateID);
2375
2376
 
2377
+ // Match by screen frame coordinates
2376
2378
  if (fabs(screenFrame.origin.x - displayBounds.origin.x) < 1.0 &&
2377
2379
  fabs(screenFrame.origin.y - displayBounds.origin.y) < 1.0 &&
2378
2380
  fabs(screenFrame.size.width - displayBounds.size.width) < 1.0 &&
2379
2381
  fabs(screenFrame.size.height - displayBounds.size.height) < 1.0) {
2380
- realDisplayID = candidateID;
2382
+ displayID = candidateID;
2381
2383
  break;
2382
2384
  }
2383
2385
  }
2384
2386
 
2385
- NSLog(@"๐Ÿ” Window screen mapping: Frame=(%.0f,%.0f,%.0fx%.0f) โ†’ CGDirectDisplayID=%u",
2387
+ NSLog(@"๐Ÿ” Window screen: Frame=(%.0f,%.0f,%.0fx%.0f) NSScreenNumber=%@ โ†’ CGDirectDisplayID=%u",
2386
2388
  screenFrame.origin.x, screenFrame.origin.y,
2387
- screenFrame.size.width, screenFrame.size.height, realDisplayID);
2389
+ screenFrame.size.width, screenFrame.size.height, screenNumber, displayID);
2388
2390
 
2389
- result.Set("screenId", Napi::Number::New(env, realDisplayID));
2391
+ result.Set("screenId", Napi::Number::New(env, displayID));
2390
2392
  result.Set("screenX", Napi::Number::New(env, (int)screenFrame.origin.x));
2391
2393
  result.Set("screenY", Napi::Number::New(env, (int)screenFrame.origin.y));
2392
2394
  result.Set("screenWidth", Napi::Number::New(env, (int)screenFrame.size.width));