node-mac-recorder 2.13.2 → 2.13.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.13.2",
3
+ "version": "2.13.4",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -168,9 +168,9 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
168
168
  }
169
169
 
170
170
  @try {
171
- // Use stable AVFoundation approach - ScreenCaptureKit disabled until Electron crash resolved
172
- NSLog(@"🔍 Using stable AVFoundation approach (ScreenCaptureKit disabled for Electron compatibility)");
173
- if (false) { // Disable ScreenCaptureKit completely for now
171
+ // Phase 4: Pure ScreenCaptureKit with memory-optimized implementation
172
+ NSLog(@"🔍 Phase 4: Pure ScreenCaptureKit with Electron-safe memory optimization");
173
+ if (@available(macOS 12.3, *)) {
174
174
  NSLog(@"✅ macOS 12.3+ detected - ScreenCaptureKit should be available");
175
175
  if ([ScreenCaptureKitRecorder isScreenCaptureKitAvailable]) {
176
176
  NSLog(@"✅ ScreenCaptureKit availability check passed");
@@ -26,11 +26,13 @@ static BOOL g_writerStarted = NO;
26
26
  if (error) {
27
27
  NSLog(@"❌ Stream stopped with error: %@", error);
28
28
  } else {
29
- NSLog(@"✅ ScreenCaptureKit stream stopped successfully");
29
+ NSLog(@"✅ ScreenCaptureKit stream stopped successfully in delegate");
30
30
  }
31
31
 
32
32
  // Finalize video writer
33
+ NSLog(@"🎬 Delegate calling finalizeVideoWriter...");
33
34
  [ScreenCaptureKitRecorder finalizeVideoWriter];
35
+ NSLog(@"🎬 Delegate finished calling finalizeVideoWriter");
34
36
  }
35
37
  @end
36
38
 
@@ -55,18 +57,45 @@ static BOOL g_writerStarted = NO;
55
57
  NSLog(@"✅ Electron-safe video writer started");
56
58
  }
57
59
 
58
- // Write sample buffer directly (Electron-safe approach)
59
- if (g_writerStarted && g_assetWriterInput.isReadyForMoreMediaData) {
60
- CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
61
- if (pixelBuffer && g_pixelBufferAdaptor) {
62
- CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
63
- CMTime relativeTime = CMTimeSubtract(presentationTime, g_startTime);
60
+ // Ultra-conservative Electron-safe sample buffer processing
61
+ @autoreleasepool {
62
+ if (!g_writerStarted || !g_assetWriterInput || !g_pixelBufferAdaptor) {
63
+ return; // Skip if not ready
64
+ }
65
+
66
+ // Rate limiting for Electron stability
67
+ static NSTimeInterval lastProcessTime = 0;
68
+ NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
69
+ if (currentTime - lastProcessTime < 0.1) { // Max 10 FPS for stability
70
+ return;
71
+ }
72
+ lastProcessTime = currentTime;
73
+
74
+ if (g_assetWriterInput.isReadyForMoreMediaData) {
75
+ CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
64
76
 
65
- BOOL success = [g_pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:relativeTime];
66
- if (success) {
67
- g_currentTime = relativeTime;
68
- } else {
69
- NSLog(@"⚠️ Failed to append pixel buffer");
77
+ if (pixelBuffer && g_pixelBufferAdaptor) {
78
+ // Ultra-conservative validation
79
+ size_t width = CVPixelBufferGetWidth(pixelBuffer);
80
+ size_t height = CVPixelBufferGetHeight(pixelBuffer);
81
+
82
+ if (width == 1280 && height == 720) { // Exact match only
83
+ CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
84
+ CMTime relativeTime = CMTimeSubtract(presentationTime, g_startTime);
85
+
86
+ // Conservative time validation
87
+ if (CMTimeGetSeconds(relativeTime) >= 0 && CMTimeGetSeconds(relativeTime) < 30) {
88
+ BOOL success = [g_pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:relativeTime];
89
+ if (success) {
90
+ g_currentTime = relativeTime;
91
+ static int safeFrameCount = 0;
92
+ safeFrameCount++;
93
+ if (safeFrameCount % 10 == 0) {
94
+ NSLog(@"✅ Electron-safe: %d frames", safeFrameCount);
95
+ }
96
+ }
97
+ }
98
+ }
70
99
  }
71
100
  }
72
101
  }
@@ -108,12 +137,14 @@ static BOOL g_writerStarted = NO;
108
137
  // Simple content filter - no exclusions for now
109
138
  SCContentFilter *filter = [[SCContentFilter alloc] initWithDisplay:targetDisplay excludingWindows:@[]];
110
139
 
111
- // Stream configuration
140
+ // Electron-optimized stream configuration (lower resource usage)
112
141
  SCStreamConfiguration *streamConfig = [[SCStreamConfiguration alloc] init];
113
142
  streamConfig.width = 1280;
114
143
  streamConfig.height = 720;
115
- streamConfig.minimumFrameInterval = CMTimeMake(1, 30);
144
+ streamConfig.minimumFrameInterval = CMTimeMake(1, 10); // 10 FPS for stability
116
145
  streamConfig.pixelFormat = kCVPixelFormatType_32BGRA;
146
+ streamConfig.capturesAudio = NO; // Disable audio for simplicity
147
+ streamConfig.excludesCurrentProcessAudio = YES;
117
148
 
118
149
  // Create Electron-safe delegates
119
150
  g_streamDelegate = [[ElectronSafeDelegate alloc] init];
@@ -153,7 +184,11 @@ static BOOL g_writerStarted = NO;
153
184
  } else {
154
185
  NSLog(@"✅ ScreenCaptureKit stream stopped in completion handler");
155
186
  }
156
- // Video finalization happens in delegate
187
+
188
+ // Finalize video since delegate might not be called
189
+ NSLog(@"🎬 Completion handler calling finalizeVideoWriter...");
190
+ [ScreenCaptureKitRecorder finalizeVideoWriter];
191
+ NSLog(@"🎬 Completion handler finished calling finalizeVideoWriter");
157
192
  }];
158
193
  }
159
194
 
@@ -178,19 +213,20 @@ static BOOL g_writerStarted = NO;
178
213
  return;
179
214
  }
180
215
 
181
- // Electron-safe video settings
216
+ // Ultra-conservative Electron video settings
182
217
  NSDictionary *videoSettings = @{
183
218
  AVVideoCodecKey: AVVideoCodecTypeH264,
184
219
  AVVideoWidthKey: @1280,
185
220
  AVVideoHeightKey: @720,
186
221
  AVVideoCompressionPropertiesKey: @{
187
- AVVideoAverageBitRateKey: @(1280 * 720 * 2),
188
- AVVideoMaxKeyFrameIntervalKey: @30
222
+ AVVideoAverageBitRateKey: @(1280 * 720 * 1), // Lower bitrate
223
+ AVVideoMaxKeyFrameIntervalKey: @10,
224
+ AVVideoProfileLevelKey: AVVideoProfileLevelH264BaselineAutoLevel
189
225
  }
190
226
  };
191
227
 
192
228
  g_assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
193
- g_assetWriterInput.expectsMediaDataInRealTime = YES; // Important for live capture
229
+ g_assetWriterInput.expectsMediaDataInRealTime = NO; // Safer for Electron
194
230
 
195
231
  // Pixel buffer attributes matching ScreenCaptureKit format
196
232
  NSDictionary *pixelBufferAttributes = @{
@@ -210,25 +246,29 @@ static BOOL g_writerStarted = NO;
210
246
  }
211
247
 
212
248
  + (void)finalizeVideoWriter {
213
- NSLog(@"🎬 Finalizing Electron-safe video writer");
249
+ NSLog(@"🎬 Finalizing video writer - writer: %p, started: %d", g_assetWriter, g_writerStarted);
214
250
 
215
251
  if (!g_assetWriter || !g_writerStarted) {
216
- NSLog(@"⚠️ Video writer not started, cleaning up");
252
+ NSLog(@"⚠️ Video writer not started properly - writer: %p, started: %d", g_assetWriter, g_writerStarted);
217
253
  [ScreenCaptureKitRecorder cleanupVideoWriter];
218
254
  return;
219
255
  }
220
256
 
257
+ NSLog(@"🎬 Marking input as finished and finalizing...");
221
258
  [g_assetWriterInput markAsFinished];
222
259
 
223
260
  [g_assetWriter finishWritingWithCompletionHandler:^{
261
+ NSLog(@"🎬 Finalization completion handler called");
224
262
  if (g_assetWriter.status == AVAssetWriterStatusCompleted) {
225
- NSLog(@"✅ Electron-safe video created successfully: %@", g_outputPath);
263
+ NSLog(@"✅ Video finalization successful: %@", g_outputPath);
226
264
  } else {
227
- NSLog(@"❌ Video creation failed: %@", g_assetWriter.error);
265
+ NSLog(@"❌ Video finalization failed - status: %ld, error: %@", (long)g_assetWriter.status, g_assetWriter.error);
228
266
  }
229
267
 
230
268
  [ScreenCaptureKitRecorder cleanupVideoWriter];
231
269
  }];
270
+
271
+ NSLog(@"🎬 Finalization request submitted, waiting for completion...");
232
272
  }
233
273
 
234
274
  + (void)cleanupVideoWriter {