node-mac-recorder 2.18.10 → 2.19.0
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/binding.gyp +1 -1
- package/index.js +8 -96
- package/package.json +1 -1
- package/src/avfoundation_recorder.mm +24 -113
- package/src/screen_capture_kit.h +1 -0
- package/src/screen_capture_kit.mm +9 -15
package/binding.gyp
CHANGED
package/index.js
CHANGED
|
@@ -252,12 +252,6 @@ class MacRecorder extends EventEmitter {
|
|
|
252
252
|
|
|
253
253
|
// Recording için display bilgisini sakla (cursor capture için)
|
|
254
254
|
const targetDisplay = displays.find(d => d.id === targetDisplayId);
|
|
255
|
-
|
|
256
|
-
// CRITICAL FIX: For now, use logical dimensions to avoid cross-display scaling issues
|
|
257
|
-
// This prevents using wrong display's physical dimensions
|
|
258
|
-
let displayScalingInfo = null;
|
|
259
|
-
// TODO: Implement proper per-display scaling detection in native layer
|
|
260
|
-
|
|
261
255
|
this.recordingDisplayInfo = {
|
|
262
256
|
displayId: targetDisplayId,
|
|
263
257
|
x: targetDisplay.x,
|
|
@@ -267,10 +261,6 @@ class MacRecorder extends EventEmitter {
|
|
|
267
261
|
// Add scaling information for cursor coordinate transformation
|
|
268
262
|
logicalWidth: parseInt(targetDisplay.resolution.split("x")[0]),
|
|
269
263
|
logicalHeight: parseInt(targetDisplay.resolution.split("x")[1]),
|
|
270
|
-
// CRITICAL: Add physical dimensions for proper cursor scaling
|
|
271
|
-
physicalWidth: displayScalingInfo ? displayScalingInfo.physicalWidth : parseInt(targetDisplay.resolution.split("x")[0]),
|
|
272
|
-
physicalHeight: displayScalingInfo ? displayScalingInfo.physicalHeight : parseInt(targetDisplay.resolution.split("x")[1]),
|
|
273
|
-
scaleFactor: displayScalingInfo ? displayScalingInfo.scaleFactor : 1.0,
|
|
274
264
|
};
|
|
275
265
|
}
|
|
276
266
|
|
|
@@ -308,11 +298,6 @@ class MacRecorder extends EventEmitter {
|
|
|
308
298
|
}
|
|
309
299
|
|
|
310
300
|
if (targetDisplay) {
|
|
311
|
-
// CRITICAL FIX: For now, use logical dimensions to avoid cross-display scaling issues
|
|
312
|
-
// This prevents using wrong display's physical dimensions
|
|
313
|
-
const displayScalingInfo = null;
|
|
314
|
-
// TODO: Implement proper per-display scaling detection in native layer
|
|
315
|
-
|
|
316
301
|
this.recordingDisplayInfo = {
|
|
317
302
|
displayId: targetDisplay.id,
|
|
318
303
|
x: targetDisplay.x || 0,
|
|
@@ -322,10 +307,6 @@ class MacRecorder extends EventEmitter {
|
|
|
322
307
|
// Add scaling information for cursor coordinate transformation
|
|
323
308
|
logicalWidth: parseInt(targetDisplay.resolution.split("x")[0]),
|
|
324
309
|
logicalHeight: parseInt(targetDisplay.resolution.split("x")[1]),
|
|
325
|
-
// CRITICAL: Add physical dimensions for proper cursor scaling
|
|
326
|
-
physicalWidth: displayScalingInfo ? displayScalingInfo.physicalWidth : parseInt(targetDisplay.resolution.split("x")[0]),
|
|
327
|
-
physicalHeight: displayScalingInfo ? displayScalingInfo.physicalHeight : parseInt(targetDisplay.resolution.split("x")[1]),
|
|
328
|
-
scaleFactor: displayScalingInfo ? displayScalingInfo.scaleFactor : 1.0,
|
|
329
310
|
};
|
|
330
311
|
}
|
|
331
312
|
} catch (error) {
|
|
@@ -705,8 +686,6 @@ class MacRecorder extends EventEmitter {
|
|
|
705
686
|
// Calculate video offset based on recording type
|
|
706
687
|
let videoOffsetX = 0;
|
|
707
688
|
let videoOffsetY = 0;
|
|
708
|
-
// UNIFIED CURSOR SYSTEM: Always use logical dimensions for cursor coordinates
|
|
709
|
-
// This ensures cursor tracking works consistently across all recording engines
|
|
710
689
|
let videoWidth = options.displayInfo.width || options.displayInfo.logicalWidth;
|
|
711
690
|
let videoHeight = options.displayInfo.height || options.displayInfo.logicalHeight;
|
|
712
691
|
|
|
@@ -733,19 +712,10 @@ class MacRecorder extends EventEmitter {
|
|
|
733
712
|
displayY: options.displayInfo.y || 0,
|
|
734
713
|
displayWidth: options.displayInfo.width || options.displayInfo.logicalWidth,
|
|
735
714
|
displayHeight: options.displayInfo.height || options.displayInfo.logicalHeight,
|
|
736
|
-
// CRITICAL: Add physical dimensions for proper cursor scaling
|
|
737
|
-
physicalWidth: options.displayInfo.physicalWidth || options.displayInfo.width || options.displayInfo.logicalWidth,
|
|
738
|
-
physicalHeight: options.displayInfo.physicalHeight || options.displayInfo.height || options.displayInfo.logicalHeight,
|
|
739
|
-
scaleFactor: options.displayInfo.scaleFactor || 1.0,
|
|
740
715
|
videoOffsetX: videoOffsetX,
|
|
741
716
|
videoOffsetY: videoOffsetY,
|
|
742
717
|
videoWidth: videoWidth,
|
|
743
718
|
videoHeight: videoHeight,
|
|
744
|
-
// CRITICAL: Video output size for proper cursor scaling
|
|
745
|
-
videoOutputWidth: (options.displayInfo.scaleFactor > 1.0) ?
|
|
746
|
-
(options.displayInfo.physicalWidth || videoWidth) : videoWidth,
|
|
747
|
-
videoOutputHeight: (options.displayInfo.scaleFactor > 1.0) ?
|
|
748
|
-
(options.displayInfo.physicalHeight || videoHeight) : videoHeight,
|
|
749
719
|
videoRelative: true,
|
|
750
720
|
recordingType: options.recordingType || 'display',
|
|
751
721
|
// Store additional context for debugging
|
|
@@ -760,22 +730,10 @@ class MacRecorder extends EventEmitter {
|
|
|
760
730
|
displayY: this.recordingDisplayInfo.y || 0,
|
|
761
731
|
displayWidth: this.recordingDisplayInfo.width || this.recordingDisplayInfo.logicalWidth,
|
|
762
732
|
displayHeight: this.recordingDisplayInfo.height || this.recordingDisplayInfo.logicalHeight,
|
|
763
|
-
// CRITICAL: Include physical dimensions from recording display info
|
|
764
|
-
physicalWidth: this.recordingDisplayInfo.physicalWidth || this.recordingDisplayInfo.width || this.recordingDisplayInfo.logicalWidth,
|
|
765
|
-
physicalHeight: this.recordingDisplayInfo.physicalHeight || this.recordingDisplayInfo.height || this.recordingDisplayInfo.logicalHeight,
|
|
766
|
-
scaleFactor: this.recordingDisplayInfo.scaleFactor || 1.0,
|
|
767
733
|
videoOffsetX: 0,
|
|
768
734
|
videoOffsetY: 0,
|
|
769
|
-
// UNIFIED CURSOR SYSTEM: Always use logical dimensions
|
|
770
735
|
videoWidth: this.recordingDisplayInfo.width || this.recordingDisplayInfo.logicalWidth,
|
|
771
736
|
videoHeight: this.recordingDisplayInfo.height || this.recordingDisplayInfo.logicalHeight,
|
|
772
|
-
// CRITICAL: Video output size for proper cursor scaling
|
|
773
|
-
videoOutputWidth: (this.recordingDisplayInfo.scaleFactor > 1.0) ?
|
|
774
|
-
(this.recordingDisplayInfo.physicalWidth || this.recordingDisplayInfo.width || this.recordingDisplayInfo.logicalWidth) :
|
|
775
|
-
(this.recordingDisplayInfo.width || this.recordingDisplayInfo.logicalWidth),
|
|
776
|
-
videoOutputHeight: (this.recordingDisplayInfo.scaleFactor > 1.0) ?
|
|
777
|
-
(this.recordingDisplayInfo.physicalHeight || this.recordingDisplayInfo.height || this.recordingDisplayInfo.logicalHeight) :
|
|
778
|
-
(this.recordingDisplayInfo.height || this.recordingDisplayInfo.logicalHeight),
|
|
779
737
|
videoRelative: true,
|
|
780
738
|
recordingType: options.recordingType || 'display'
|
|
781
739
|
};
|
|
@@ -823,23 +781,6 @@ class MacRecorder extends EventEmitter {
|
|
|
823
781
|
|
|
824
782
|
// Apply video-relative transformation for all recording types
|
|
825
783
|
if (this.cursorDisplayInfo && this.cursorDisplayInfo.videoRelative) {
|
|
826
|
-
// FILTER: Only record cursor when it's on the target display
|
|
827
|
-
// Use cached display info to avoid async calls
|
|
828
|
-
const displayX = this.cursorDisplayInfo.displayX;
|
|
829
|
-
const displayY = this.cursorDisplayInfo.displayY;
|
|
830
|
-
const displayWidth = this.cursorDisplayInfo.displayWidth;
|
|
831
|
-
const displayHeight = this.cursorDisplayInfo.displayHeight;
|
|
832
|
-
|
|
833
|
-
const onTargetDisplay = position.x >= displayX &&
|
|
834
|
-
position.x < (displayX + displayWidth) &&
|
|
835
|
-
position.y >= displayY &&
|
|
836
|
-
position.y < (displayY + displayHeight);
|
|
837
|
-
|
|
838
|
-
if (!onTargetDisplay) {
|
|
839
|
-
// Skip cursor data when cursor is on different display
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
784
|
// Step 1: Transform global → display-relative coordinates
|
|
844
785
|
const displayRelativeX = position.x - this.cursorDisplayInfo.displayX;
|
|
845
786
|
const displayRelativeY = position.y - this.cursorDisplayInfo.displayY;
|
|
@@ -847,31 +788,16 @@ class MacRecorder extends EventEmitter {
|
|
|
847
788
|
// Step 2: Transform display-relative → video-relative coordinates
|
|
848
789
|
x = displayRelativeX - this.cursorDisplayInfo.videoOffsetX;
|
|
849
790
|
y = displayRelativeY - this.cursorDisplayInfo.videoOffsetY;
|
|
791
|
+
coordinateSystem = "video-relative";
|
|
850
792
|
|
|
851
|
-
//
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
if (scaleX !== 1.0 || scaleY !== 1.0) {
|
|
857
|
-
x = x * scaleX;
|
|
858
|
-
y = y * scaleY;
|
|
859
|
-
coordinateSystem = "video-output-scaled";
|
|
860
|
-
} else {
|
|
861
|
-
coordinateSystem = "video-relative";
|
|
862
|
-
}
|
|
863
|
-
} else {
|
|
864
|
-
coordinateSystem = "video-relative";
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
// Bounds check for video area using actual video output dimensions
|
|
868
|
-
const checkWidth = this.cursorDisplayInfo.videoOutputWidth || this.cursorDisplayInfo.videoWidth;
|
|
869
|
-
const checkHeight = this.cursorDisplayInfo.videoOutputHeight || this.cursorDisplayInfo.videoHeight;
|
|
870
|
-
const outsideVideo = x < 0 || y < 0 || x >= checkWidth || y >= checkHeight;
|
|
793
|
+
// Bounds check for video area (don't skip, just note if outside)
|
|
794
|
+
const outsideVideo = x < 0 || y < 0 ||
|
|
795
|
+
x >= this.cursorDisplayInfo.videoWidth ||
|
|
796
|
+
y >= this.cursorDisplayInfo.videoHeight;
|
|
871
797
|
|
|
872
798
|
// For debugging - add metadata if cursor is outside video area
|
|
873
799
|
if (outsideVideo) {
|
|
874
|
-
coordinateSystem =
|
|
800
|
+
coordinateSystem = "video-relative-outside";
|
|
875
801
|
}
|
|
876
802
|
}
|
|
877
803
|
|
|
@@ -889,19 +815,12 @@ class MacRecorder extends EventEmitter {
|
|
|
889
815
|
width: this.cursorDisplayInfo.videoWidth,
|
|
890
816
|
height: this.cursorDisplayInfo.videoHeight,
|
|
891
817
|
offsetX: this.cursorDisplayInfo.videoOffsetX,
|
|
892
|
-
offsetY: this.cursorDisplayInfo.videoOffsetY
|
|
893
|
-
// CRITICAL: Add physical dimensions for debugging
|
|
894
|
-
physicalWidth: this.cursorDisplayInfo.physicalWidth,
|
|
895
|
-
physicalHeight: this.cursorDisplayInfo.physicalHeight
|
|
818
|
+
offsetY: this.cursorDisplayInfo.videoOffsetY
|
|
896
819
|
} : null,
|
|
897
820
|
displayInfo: this.cursorDisplayInfo ? {
|
|
898
821
|
displayId: this.cursorDisplayInfo.displayId,
|
|
899
822
|
width: this.cursorDisplayInfo.displayWidth,
|
|
900
|
-
height: this.cursorDisplayInfo.displayHeight
|
|
901
|
-
// CRITICAL: Add scaling info for debugging AVFoundation cursor issues
|
|
902
|
-
physicalWidth: this.cursorDisplayInfo.physicalWidth,
|
|
903
|
-
physicalHeight: this.cursorDisplayInfo.physicalHeight,
|
|
904
|
-
scaleFactor: this.cursorDisplayInfo.scaleFactor
|
|
823
|
+
height: this.cursorDisplayInfo.displayHeight
|
|
905
824
|
} : null
|
|
906
825
|
};
|
|
907
826
|
|
|
@@ -954,13 +873,6 @@ class MacRecorder extends EventEmitter {
|
|
|
954
873
|
this.cursorCaptureFile = null;
|
|
955
874
|
}
|
|
956
875
|
|
|
957
|
-
// Native cursor tracking'i durdur
|
|
958
|
-
try {
|
|
959
|
-
nativeBinding.stopCursorTracking();
|
|
960
|
-
} catch (nativeError) {
|
|
961
|
-
console.warn('Native cursor tracking stop failed:', nativeError.message);
|
|
962
|
-
}
|
|
963
|
-
|
|
964
876
|
// Değişkenleri temizle
|
|
965
877
|
this.lastCapturedData = null;
|
|
966
878
|
this.cursorCaptureStartTime = null;
|
package/package.json
CHANGED
|
@@ -6,83 +6,6 @@
|
|
|
6
6
|
#import <AppKit/AppKit.h>
|
|
7
7
|
#include <string>
|
|
8
8
|
|
|
9
|
-
// Advanced display scaling detection (same algorithm as cursor_tracker.mm)
|
|
10
|
-
NSDictionary* getAdvancedDisplayScalingInfo(CGDirectDisplayID displayID) {
|
|
11
|
-
@try {
|
|
12
|
-
CGRect displayBounds = CGDisplayBounds(displayID);
|
|
13
|
-
CGSize logicalSize = displayBounds.size;
|
|
14
|
-
|
|
15
|
-
NSLog(@"🔍 Advanced scaling detection for display %u:", displayID);
|
|
16
|
-
NSLog(@" Logical bounds: %.0fx%.0f", logicalSize.width, logicalSize.height);
|
|
17
|
-
|
|
18
|
-
// CRITICAL FIX: Get REAL physical dimensions using multiple detection methods
|
|
19
|
-
// Method 1: CGDisplayCreateImage (may be scaled on some systems)
|
|
20
|
-
CGImageRef testImage = CGDisplayCreateImage(displayID);
|
|
21
|
-
CGSize imageSize = CGSizeMake(CGImageGetWidth(testImage), CGImageGetHeight(testImage));
|
|
22
|
-
CGImageRelease(testImage);
|
|
23
|
-
|
|
24
|
-
// Method 2: Native display mode detection for true physical resolution
|
|
25
|
-
CGSize actualPhysicalSize = imageSize;
|
|
26
|
-
CFArrayRef displayModes = CGDisplayCopyAllDisplayModes(displayID, NULL);
|
|
27
|
-
if (displayModes) {
|
|
28
|
-
CFIndex modeCount = CFArrayGetCount(displayModes);
|
|
29
|
-
CGSize maxResolution = CGSizeMake(0, 0);
|
|
30
|
-
|
|
31
|
-
// Find the highest resolution mode (native resolution)
|
|
32
|
-
for (CFIndex i = 0; i < modeCount; i++) {
|
|
33
|
-
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, i);
|
|
34
|
-
CGSize modeSize = CGSizeMake(CGDisplayModeGetWidth(mode), CGDisplayModeGetHeight(mode));
|
|
35
|
-
|
|
36
|
-
if (modeSize.width > maxResolution.width ||
|
|
37
|
-
(modeSize.width == maxResolution.width && modeSize.height > maxResolution.height)) {
|
|
38
|
-
maxResolution = modeSize;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Use the max resolution if it's significantly higher than image size
|
|
43
|
-
if (maxResolution.width > imageSize.width * 1.5 || maxResolution.height > imageSize.height * 1.5) {
|
|
44
|
-
actualPhysicalSize = maxResolution;
|
|
45
|
-
NSLog(@" Using display mode detection: %.0fx%.0f (was %.0fx%.0f)",
|
|
46
|
-
maxResolution.width, maxResolution.height, imageSize.width, imageSize.height);
|
|
47
|
-
} else {
|
|
48
|
-
actualPhysicalSize = imageSize;
|
|
49
|
-
NSLog(@" Using image size detection: %.0fx%.0f", imageSize.width, imageSize.height);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
CFRelease(displayModes);
|
|
53
|
-
} else {
|
|
54
|
-
actualPhysicalSize = imageSize;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
CGSize reportedPhysicalSize = CGSizeMake(CGDisplayPixelsWide(displayID), CGDisplayPixelsHigh(displayID));
|
|
58
|
-
|
|
59
|
-
NSLog(@"🔍 ADVANCED scaling info:");
|
|
60
|
-
NSLog(@" Logical: %.0fx%.0f", logicalSize.width, logicalSize.height);
|
|
61
|
-
NSLog(@" Reported physical: %.0fx%.0f", reportedPhysicalSize.width, reportedPhysicalSize.height);
|
|
62
|
-
NSLog(@" ACTUAL physical: %.0fx%.0f", actualPhysicalSize.width, actualPhysicalSize.height);
|
|
63
|
-
|
|
64
|
-
CGFloat scaleX = actualPhysicalSize.width / logicalSize.width;
|
|
65
|
-
CGFloat scaleY = actualPhysicalSize.height / logicalSize.height;
|
|
66
|
-
CGFloat scaleFactor = MAX(scaleX, scaleY);
|
|
67
|
-
|
|
68
|
-
NSLog(@"🔍 ADVANCED scale factors: X=%.2f, Y=%.2f, Final=%.2f", scaleX, scaleY, scaleFactor);
|
|
69
|
-
|
|
70
|
-
return @{
|
|
71
|
-
@"displayID": @(displayID),
|
|
72
|
-
@"logicalSize": [NSValue valueWithSize:NSMakeSize(logicalSize.width, logicalSize.height)],
|
|
73
|
-
@"physicalSize": [NSValue valueWithSize:NSMakeSize(actualPhysicalSize.width, actualPhysicalSize.height)],
|
|
74
|
-
@"reportedPhysicalSize": [NSValue valueWithSize:NSMakeSize(reportedPhysicalSize.width, reportedPhysicalSize.height)],
|
|
75
|
-
@"scaleFactor": @(scaleFactor),
|
|
76
|
-
@"scaleX": @(scaleX),
|
|
77
|
-
@"scaleY": @(scaleY),
|
|
78
|
-
@"displayBounds": [NSValue valueWithRect:NSMakeRect(displayBounds.origin.x, displayBounds.origin.y, displayBounds.size.width, displayBounds.size.height)]
|
|
79
|
-
};
|
|
80
|
-
} @catch (NSException *exception) {
|
|
81
|
-
NSLog(@"❌ Advanced scaling detection failed: %@", exception);
|
|
82
|
-
return nil;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
9
|
static AVAssetWriter *g_avWriter = nil;
|
|
87
10
|
static AVAssetWriterInput *g_avVideoInput = nil;
|
|
88
11
|
static AVAssetWriterInputPixelBufferAdaptor *g_avPixelBufferAdaptor = nil;
|
|
@@ -130,35 +53,23 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
|
|
|
130
53
|
return false;
|
|
131
54
|
}
|
|
132
55
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
CGSize
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} else {
|
|
151
|
-
// Fallback to old method
|
|
152
|
-
NSLog(@"⚠️ Advanced scaling detection failed, using fallback");
|
|
153
|
-
CGRect displayBounds = CGDisplayBounds(displayID);
|
|
154
|
-
logicalSize = displayBounds.size;
|
|
155
|
-
|
|
156
|
-
CGImageRef testImage = CGDisplayCreateImage(displayID);
|
|
157
|
-
actualImageSize = CGSizeMake(CGImageGetWidth(testImage), CGImageGetHeight(testImage));
|
|
158
|
-
CGImageRelease(testImage);
|
|
159
|
-
|
|
160
|
-
scaleFactor = MAX(actualImageSize.width / logicalSize.width, actualImageSize.height / logicalSize.height);
|
|
161
|
-
}
|
|
56
|
+
// Get display dimensions with proper scaling for macOS 14/13 compatibility
|
|
57
|
+
CGRect displayBounds = CGDisplayBounds(displayID);
|
|
58
|
+
|
|
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 for pixel buffer
|
|
69
|
+
// CGDisplayCreateImage returns physical pixels on Retina displays
|
|
70
|
+
CGImageRef testImage = CGDisplayCreateImage(displayID);
|
|
71
|
+
CGSize actualImageSize = CGSizeMake(CGImageGetWidth(testImage), CGImageGetHeight(testImage));
|
|
72
|
+
CGImageRelease(testImage);
|
|
162
73
|
|
|
163
74
|
// CRITICAL FIX: Use actual image dimensions to match what CGDisplayCreateImage returns
|
|
164
75
|
// This prevents the "1/4 recording area" bug on Retina displays
|
|
@@ -174,18 +85,18 @@ extern "C" bool startAVFoundationRecording(const std::string& outputPath,
|
|
|
174
85
|
recordingSize = actualImageSize;
|
|
175
86
|
}
|
|
176
87
|
|
|
177
|
-
NSLog(@"🎯
|
|
88
|
+
NSLog(@"🎯 CRITICAL: Logical %.0fx%.0f → Actual image %.0fx%.0f",
|
|
178
89
|
logicalSize.width, logicalSize.height, actualImageSize.width, actualImageSize.height);
|
|
179
|
-
|
|
90
|
+
|
|
180
91
|
NSLog(@"🖥️ Display bounds (logical): %.0fx%.0f", logicalSize.width, logicalSize.height);
|
|
181
|
-
NSLog(@"🖥️ Display
|
|
182
|
-
|
|
92
|
+
NSLog(@"🖥️ Display pixels (physical): %.0fx%.0f", physicalSize.width, physicalSize.height);
|
|
93
|
+
|
|
183
94
|
if (scaleFactor > 1.5) {
|
|
184
|
-
NSLog(@"🔍
|
|
95
|
+
NSLog(@"🔍 Scale factor: %.1fx → Retina display detected (macOS 14/13 scaling fix applied)", scaleFactor);
|
|
185
96
|
} else if (scaleFactor > 1.1) {
|
|
186
|
-
NSLog(@"🔍
|
|
97
|
+
NSLog(@"🔍 Scale factor: %.1fx → Non-standard scaling detected", scaleFactor);
|
|
187
98
|
} else {
|
|
188
|
-
NSLog(@"🔍
|
|
99
|
+
NSLog(@"🔍 Scale factor: %.1fx → Standard display", scaleFactor);
|
|
189
100
|
}
|
|
190
101
|
|
|
191
102
|
NSLog(@"🎯 Recording size: %.0fx%.0f (using actual physical dimensions for Retina fix)", recordingSize.width, recordingSize.height);
|
package/src/screen_capture_kit.h
CHANGED
|
@@ -297,11 +297,9 @@ static NSString *g_outputPath = nil;
|
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
300
|
+
if (!g_recordingOutput) {
|
|
301
|
+
NSLog(@"❌ Failed to create SCRecordingOutput");
|
|
302
|
+
return;
|
|
305
303
|
}
|
|
306
304
|
|
|
307
305
|
NSLog(@"✅ Pure ScreenCaptureKit recording output created");
|
|
@@ -391,11 +389,9 @@ static NSString *g_outputPath = nil;
|
|
|
391
389
|
g_isCleaningUp = YES;
|
|
392
390
|
g_isRecording = NO;
|
|
393
391
|
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
NSLog(@"✅ Pure recording output finalized");
|
|
398
|
-
}
|
|
392
|
+
if (g_recordingOutput) {
|
|
393
|
+
// SCRecordingOutput finalizes automatically
|
|
394
|
+
NSLog(@"✅ Pure recording output finalized");
|
|
399
395
|
}
|
|
400
396
|
|
|
401
397
|
[ScreenCaptureKitRecorder cleanupVideoWriter];
|
|
@@ -417,11 +413,9 @@ static NSString *g_outputPath = nil;
|
|
|
417
413
|
NSLog(@"✅ Stream reference cleared");
|
|
418
414
|
}
|
|
419
415
|
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
NSLog(@"✅ Recording output reference cleared");
|
|
424
|
-
}
|
|
416
|
+
if (g_recordingOutput) {
|
|
417
|
+
g_recordingOutput = nil;
|
|
418
|
+
NSLog(@"✅ Recording output reference cleared");
|
|
425
419
|
}
|
|
426
420
|
|
|
427
421
|
if (g_streamDelegate) {
|