node-mac-recorder 2.16.28 → 2.16.29

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.
@@ -2,7 +2,8 @@
2
2
  "permissions": {
3
3
  "allow": [
4
4
  "Bash(FORCE_AVFOUNDATION=1 node test-sequential.js)",
5
- "Bash(grep:*)"
5
+ "Bash(grep:*)",
6
+ "Bash(FORCE_AVFOUNDATION=1 node -e \"\nconsole.log(''🧪 Testing macOS 14/13 coordinate scaling fix...'');\nconst MacRecorder = require(''./index.js'');\nconst recorder = new MacRecorder();\n\nrecorder.startRecording(''/tmp/coordinate-fix-test.mov'')\n .then(success => {\n console.log(''Start result:'', success ? ''✅ SUCCESS'' : ''❌ FAILED'');\n if (success) {\n setTimeout(() => {\n recorder.stopRecording().then(() => {\n console.log(''✅ Recording stopped'');\n const fs = require(''fs'');\n if (fs.existsSync(''/tmp/coordinate-fix-test.mov'')) {\n const size = Math.round(fs.statSync(''/tmp/coordinate-fix-test.mov'').size/1024);\n console.log(''📹 File size:'', size + ''KB'');\n if (size > 100) {\n console.log(''🎉 macOS 14/13 coordinate fix test SUCCESS!'');\n } else {\n console.log(''⚠️ File too small, may have issues'');\n }\n } else {\n console.log(''❌ No output file created'');\n }\n });\n }, 3000); // 3 seconds recording\n }\n })\n .catch(console.error);\n\")"
6
7
  ],
7
8
  "deny": [],
8
9
  "ask": []
package/index.js CHANGED
@@ -212,14 +212,12 @@ class MacRecorder extends EventEmitter {
212
212
  targetWindow.y < display.y + displayHeight
213
213
  ) {
214
214
  targetDisplayId = display.id; // Use actual display ID, not array index
215
- // Koordinatları display'e göre normalize et
215
+ // CRITICAL FIX: Convert global coordinates to display-relative coordinates
216
+ // AVFoundation expects simple display-relative top-left coordinates (no flipping)
216
217
  adjustedX = targetWindow.x - display.x;
218
+ adjustedY = targetWindow.y - display.y;
217
219
 
218
- // Y coordinate conversion: CGWindow (top-left) to AVFoundation (bottom-left)
219
- // Overlay'deki dönüşümle aynı mantık: screenHeight - windowY - windowHeight
220
- const displayHeight = parseInt(display.resolution.split("x")[1]);
221
- const convertedY = displayHeight - targetWindow.y - targetWindow.height;
222
- adjustedY = Math.max(0, convertedY - display.y);
220
+ console.log(`🔧 macOS 14/13 coordinate fix: Global (${targetWindow.x},${targetWindow.y}) -> Display-relative (${adjustedX},${adjustedY})`);
223
221
  break;
224
222
  }
225
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.16.28",
3
+ "version": "2.16.29",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -71,8 +71,8 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
71
71
  CGSize actualImageSize = CGSizeMake(CGImageGetWidth(testImage), CGImageGetHeight(testImage));
72
72
  CGImageRelease(testImage);
73
73
 
74
- // For AVFoundation, use actual image size that CGDisplayCreateImage returns
75
- CGSize recordingSize = captureRect.size.width > 0 ? captureRect.size : actualImageSize;
74
+ // CRITICAL FIX: Use logical size for consistency, actual image size only for validation
75
+ CGSize recordingSize = captureRect.size.width > 0 ? captureRect.size : logicalSize;
76
76
 
77
77
  NSLog(@"🎯 CRITICAL: Logical %.0fx%.0f → Actual image %.0fx%.0f",
78
78
  logicalSize.width, logicalSize.height, actualImageSize.width, actualImageSize.height);
@@ -154,32 +154,25 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
154
154
  // Store recording parameters with scaling correction
155
155
  g_avDisplayID = displayID;
156
156
 
157
- // Apply scaling to capture rect if provided (for macOS 14/13 compatibility)
157
+ // CRITICAL FIX: Use coordinates as-is from JS layer (already display-relative)
158
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;
159
+ // Use coordinates directly - JS layer already converted global to display-relative
160
+ g_avCaptureRect = captureRect;
162
161
 
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);
162
+ NSLog(@"🔲 macOS 14/13 FIXED: Display-relative capture area: %.0f,%.0f %.0fx%.0f",
163
+ captureRect.origin.x, captureRect.origin.y, captureRect.size.width, captureRect.size.height);
164
+
165
+ // Validate coordinates are within logical display bounds
166
+ if (captureRect.origin.x >= 0 && captureRect.origin.y >= 0 &&
167
+ captureRect.origin.x + captureRect.size.width <= logicalSize.width &&
168
+ captureRect.origin.y + captureRect.size.height <= logicalSize.height) {
169
+ NSLog(@"✅ Coordinates validated within logical display bounds %.0fx%.0f", logicalSize.width, logicalSize.height);
175
170
  } 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);
171
+ NSLog(@"⚠️ Coordinates may be outside logical display bounds - clipping may occur");
179
172
  }
180
173
  } else {
181
174
  g_avCaptureRect = CGRectZero; // Full screen
182
- NSLog(@"🖥️ Full screen capture (actual image dimensions)");
175
+ NSLog(@"🖥️ Full screen capture using logical dimensions %.0fx%.0f", logicalSize.width, logicalSize.height);
183
176
  }
184
177
 
185
178
  g_avFrameNumber = 0;
@@ -243,8 +236,8 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
243
236
  NSLog(@"🔍 Debug: Buffer %zux%zu, Image %zux%zu", bufferWidth, bufferHeight, imageWidth, imageHeight);
244
237
 
245
238
  if (bufferWidth != imageWidth || bufferHeight != 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");
239
+ NSLog(@"🔧 EXPECTED SIZE DIFFERENCE: Buffer %zux%zu (logical) vs Image %zux%zu (physical)", bufferWidth, bufferHeight, imageWidth, imageHeight);
240
+ NSLog(@" This is normal on Retina displays - scaling handled correctly now");
248
241
  }
249
242
 
250
243
  CVPixelBufferLockBaseAddress(pixelBuffer, 0);
@@ -282,7 +275,9 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
282
275
  8, bytesPerRow, colorSpace, bitmapInfo);
283
276
 
284
277
  if (context) {
285
- CGContextDrawImage(context, CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer)), screenImage);
278
+ // CRITICAL FIX: Draw image at correct size - scale physical image to logical buffer size
279
+ CGSize bufferSize = CGSizeMake(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
280
+ CGContextDrawImage(context, CGRectMake(0, 0, bufferSize.width, bufferSize.height), screenImage);
286
281
  CGContextRelease(context);
287
282
 
288
283
  // Write frame only if input is ready