node-mac-recorder 2.16.14 โ†’ 2.16.16

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 AVFoundation area recording...'');\nconst MacRecorder = require(''./index.js'');\nconst recorder = new MacRecorder();\n\n// Test specific area recording (top-left 500x500)\nconst options = {\n captureArea: {\n x: 100,\n y: 100, \n width: 500,\n height: 500\n }\n};\n\nrecorder.startRecording(''/tmp/area-test.mov'', options)\n .then(success => {\n console.log(''Area recording:'', success ? ''โœ… SUCCESS'' : ''โŒ FAILED'');\n if (success) {\n setTimeout(() => {\n recorder.stopRecording().then(() => {\n console.log(''โœ… Area recording complete'');\n const fs = require(''fs'');\n if (fs.existsSync(''/tmp/area-test.mov'')) {\n const size = Math.round(fs.statSync(''/tmp/area-test.mov'').size/1024);\n console.log(''๐Ÿ“น File size:'', size + ''KB'');\n }\n });\n }, 2000);\n }\n })\n .catch(console.error);\n\")"
4
+ "Bash(FORCE_AVFOUNDATION=1 node -e \"\nconsole.log(''๐Ÿงช Testing CRITICAL AVFoundation scaling fix...'');\nconst MacRecorder = require(''./index.js'');\nconst recorder = new MacRecorder();\n\nrecorder.startRecording(''/tmp/critical-scaling-test.mov'')\n .then(success => {\n console.log(''Start:'', success ? ''โœ… SUCCESS'' : ''โŒ FAILED'');\n if (success) {\n setTimeout(() => {\n recorder.stopRecording().then(() => {\n console.log(''โœ… Test complete'');\n const fs = require(''fs'');\n if (fs.existsSync(''/tmp/critical-scaling-test.mov'')) {\n const size = Math.round(fs.statSync(''/tmp/critical-scaling-test.mov'').size/1024);\n console.log(''๐Ÿ“น File size:'', size + ''KB'');\n }\n });\n }, 3000);\n }\n })\n .catch(console.error);\n\")"
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.14",
3
+ "version": "2.16.16",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -53,14 +53,42 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
53
53
  return false;
54
54
  }
55
55
 
56
- // Get display dimensions - use width/height directly to avoid coordinate issues
56
+ // Get display dimensions with proper scaling for macOS 14/13 compatibility
57
57
  CGRect displayBounds = CGDisplayBounds(displayID);
58
- CGSize displaySize = CGSizeMake(CGDisplayPixelsWide(displayID), CGDisplayPixelsHigh(displayID));
59
- CGSize recordingSize = captureRect.size.width > 0 ? captureRect.size : displaySize;
60
58
 
61
- NSLog(@"๐Ÿ–ฅ๏ธ Display bounds: %.0f,%.0f %.0fx%.0f", displayBounds.origin.x, displayBounds.origin.y, displayBounds.size.width, displayBounds.size.height);
62
- NSLog(@"๐Ÿ–ฅ๏ธ Display pixels: %.0fx%.0f", displaySize.width, displaySize.height);
63
- NSLog(@"๐ŸŽฏ Recording size: %.0fx%.0f", recordingSize.width, recordingSize.height);
59
+ // Get both logical (bounds) and physical (pixels) dimensions
60
+ CGSize logicalSize = displayBounds.size;
61
+ CGSize physicalSize = CGSizeMake(CGDisplayPixelsWide(displayID), CGDisplayPixelsHigh(displayID));
62
+
63
+ // Calculate scale factor
64
+ CGFloat scaleX = physicalSize.width / logicalSize.width;
65
+ CGFloat scaleY = physicalSize.height / logicalSize.height;
66
+ CGFloat scaleFactor = MAX(scaleX, scaleY); // Use max to handle non-uniform scaling
67
+
68
+ // CRITICAL FIX: Use actual captured image dimensions, not logical size
69
+ // CGDisplayCreateImage may return higher resolution on Retina displays
70
+ CGImageRef testImage = CGDisplayCreateImage(displayID);
71
+ CGSize actualImageSize = CGSizeMake(CGImageGetWidth(testImage), CGImageGetHeight(testImage));
72
+ CGImageRelease(testImage);
73
+
74
+ // For AVFoundation, use actual image size that CGDisplayCreateImage returns
75
+ CGSize recordingSize = captureRect.size.width > 0 ? captureRect.size : actualImageSize;
76
+
77
+ NSLog(@"๐ŸŽฏ CRITICAL: Logical %.0fx%.0f โ†’ Actual image %.0fx%.0f",
78
+ logicalSize.width, logicalSize.height, actualImageSize.width, actualImageSize.height);
79
+
80
+ NSLog(@"๐Ÿ–ฅ๏ธ Display bounds (logical): %.0fx%.0f", logicalSize.width, logicalSize.height);
81
+ NSLog(@"๐Ÿ–ฅ๏ธ Display pixels (physical): %.0fx%.0f", physicalSize.width, physicalSize.height);
82
+
83
+ if (scaleFactor > 1.5) {
84
+ NSLog(@"๐Ÿ” Scale factor: %.1fx โ†’ Retina display detected (macOS 14/13 scaling fix applied)", scaleFactor);
85
+ } else if (scaleFactor > 1.1) {
86
+ NSLog(@"๐Ÿ” Scale factor: %.1fx โ†’ Non-standard scaling detected", scaleFactor);
87
+ } else {
88
+ NSLog(@"๐Ÿ” Scale factor: %.1fx โ†’ Standard display", scaleFactor);
89
+ }
90
+
91
+ NSLog(@"๐ŸŽฏ Recording size: %.0fx%.0f (using logical dimensions for AVFoundation)", recordingSize.width, recordingSize.height);
64
92
 
65
93
  // Video settings with macOS compatibility
66
94
  NSString *codecKey;
@@ -123,9 +151,37 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
123
151
  g_avStartTime = CMTimeMakeWithSeconds(CACurrentMediaTime(), 600);
124
152
  [g_avWriter startSessionAtSourceTime:g_avStartTime];
125
153
 
126
- // Store recording parameters
154
+ // Store recording parameters with scaling correction
127
155
  g_avDisplayID = displayID;
128
- g_avCaptureRect = captureRect;
156
+
157
+ // Apply scaling to capture rect if provided (for macOS 14/13 compatibility)
158
+ if (!CGRectIsEmpty(captureRect)) {
159
+ // Scale capture rect to match actual image dimensions if needed
160
+ CGFloat imageScaleX = actualImageSize.width / logicalSize.width;
161
+ CGFloat imageScaleY = actualImageSize.height / logicalSize.height;
162
+
163
+ if (imageScaleX > 1.1 || imageScaleY > 1.1) {
164
+ // Scale up capture rect for high-DPI displays
165
+ CGRect scaledRect = CGRectMake(
166
+ captureRect.origin.x * imageScaleX,
167
+ captureRect.origin.y * imageScaleY,
168
+ captureRect.size.width * imageScaleX,
169
+ captureRect.size.height * imageScaleY
170
+ );
171
+ g_avCaptureRect = scaledRect;
172
+ NSLog(@"๐Ÿ”ฒ Capture area scaled: %.0f,%.0f %.0fx%.0f (scale %.1fx%.1fx)",
173
+ scaledRect.origin.x, scaledRect.origin.y, scaledRect.size.width, scaledRect.size.height,
174
+ imageScaleX, imageScaleY);
175
+ } else {
176
+ g_avCaptureRect = captureRect;
177
+ NSLog(@"๐Ÿ”ฒ Capture area (no scaling): %.0f,%.0f %.0fx%.0f",
178
+ captureRect.origin.x, captureRect.origin.y, captureRect.size.width, captureRect.size.height);
179
+ }
180
+ } else {
181
+ g_avCaptureRect = CGRectZero; // Full screen
182
+ NSLog(@"๐Ÿ–ฅ๏ธ Full screen capture (actual image dimensions)");
183
+ }
184
+
129
185
  g_avFrameNumber = 0;
130
186
 
131
187
  // Start capture timer (10 FPS for Electron compatibility)
@@ -184,8 +240,11 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
184
240
  size_t imageWidth = CGImageGetWidth(screenImage);
185
241
  size_t imageHeight = CGImageGetHeight(screenImage);
186
242
 
243
+ NSLog(@"๐Ÿ” Debug: Buffer %zux%zu, Image %zux%zu", bufferWidth, bufferHeight, imageWidth, imageHeight);
244
+
187
245
  if (bufferWidth != imageWidth || bufferHeight != imageHeight) {
188
- NSLog(@"โš ๏ธ Size mismatch! Buffer %zux%zu vs Image %zux%zu", bufferWidth, bufferHeight, imageWidth, imageHeight);
246
+ NSLog(@"โš ๏ธ CRITICAL SIZE MISMATCH! Buffer %zux%zu vs Image %zux%zu", bufferWidth, bufferHeight, imageWidth, imageHeight);
247
+ NSLog(@" This indicates Retina scaling issue on macOS 14/13");
189
248
  }
190
249
 
191
250
  CVPixelBufferLockBaseAddress(pixelBuffer, 0);
@@ -892,11 +892,21 @@ void updateOverlay() {
892
892
  CGFloat primaryOffsetX = primaryFrame.origin.x - combinedFrame.origin.x;
893
893
  CGFloat primaryOffsetY = primaryFrame.origin.y - combinedFrame.origin.y;
894
894
 
895
+ NSLog(@"๐Ÿ”ง PRIMARY DEBUG:");
896
+ NSLog(@" Primary frame: (%.0f,%.0f) %.0fx%.0f", primaryFrame.origin.x, primaryFrame.origin.y, primaryFrame.size.width, primaryFrame.size.height);
897
+ NSLog(@" Combined frame: (%.0f,%.0f) %.0fx%.0f", combinedFrame.origin.x, combinedFrame.origin.y, combinedFrame.size.width, combinedFrame.size.height);
898
+ NSLog(@" Primary offset: (%.0f,%.0f)", primaryOffsetX, primaryOffsetY);
899
+ NSLog(@" Window coords: (%.0f,%.0f) โ†’ Local: (%.0f,%.0f)", (CGFloat)x, (CGFloat)y, x + primaryOffsetX, ([g_overlayView frame].size.height - (y + primaryOffsetY)) - height);
900
+
895
901
  localX = x + primaryOffsetX;
896
902
  localY = ([g_overlayView frame].size.height - (y + primaryOffsetY)) - height;
897
903
 
898
904
  } else {
899
905
  // Secondary display windows: Apply standard coordinate transformation
906
+ NSLog(@"๐Ÿ”ง SECONDARY DEBUG:");
907
+ NSLog(@" GlobalOffset: (%.0f,%.0f)", globalOffset.x, globalOffset.y);
908
+ NSLog(@" Window coords: (%.0f,%.0f) โ†’ Local: (%.0f,%.0f)", (CGFloat)x, (CGFloat)y, x - globalOffset.x, ([g_overlayView frame].size.height - (y - globalOffset.y)) - height);
909
+
900
910
  localX = x - globalOffset.x;
901
911
  localY = ([g_overlayView frame].size.height - (y - globalOffset.y)) - height;
902
912
  }