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.
- package/.claude/settings.local.json +2 -1
- package/index.js +4 -6
- package/package.json +1 -1
- package/src/avfoundation_recorder.mm +20 -25
|
@@ -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
|
-
//
|
|
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
|
-
|
|
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
|
@@ -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
|
-
//
|
|
75
|
-
CGSize recordingSize = captureRect.size.width > 0 ? captureRect.size :
|
|
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
|
-
//
|
|
157
|
+
// CRITICAL FIX: Use coordinates as-is from JS layer (already display-relative)
|
|
158
158
|
if (!CGRectIsEmpty(captureRect)) {
|
|
159
|
-
//
|
|
160
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
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
|
|
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(@"
|
|
247
|
-
NSLog(@" This
|
|
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
|
-
|
|
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
|