node-mac-recorder 2.21.13 → 2.21.14
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 +3 -1
- package/index.js +82 -27
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -437,9 +437,9 @@ class MacRecorder extends EventEmitter {
|
|
|
437
437
|
|
|
438
438
|
this.outputPath = outputPath;
|
|
439
439
|
|
|
440
|
-
return new Promise((resolve, reject) => {
|
|
440
|
+
return new Promise(async (resolve, reject) => {
|
|
441
441
|
try {
|
|
442
|
-
//
|
|
442
|
+
// SYNC FIX: Create unified session timestamp FIRST for all components
|
|
443
443
|
const sessionTimestamp = Date.now();
|
|
444
444
|
this.sessionTimestamp = sessionTimestamp;
|
|
445
445
|
const outputDir = path.dirname(outputPath);
|
|
@@ -507,15 +507,46 @@ class MacRecorder extends EventEmitter {
|
|
|
507
507
|
};
|
|
508
508
|
}
|
|
509
509
|
|
|
510
|
+
// SYNC FIX: Start cursor tracking BEFORE native recording for perfect sync
|
|
511
|
+
// This ensures cursor data starts at exactly the same time as video
|
|
512
|
+
console.log('🎯 SYNC: Starting cursor tracking at timestamp:', sessionTimestamp);
|
|
513
|
+
const standardCursorOptions = {
|
|
514
|
+
videoRelative: true,
|
|
515
|
+
displayInfo: this.recordingDisplayInfo,
|
|
516
|
+
recordingType: this.options.windowId ? 'window' :
|
|
517
|
+
this.options.captureArea ? 'area' : 'display',
|
|
518
|
+
captureArea: this.options.captureArea,
|
|
519
|
+
windowId: this.options.windowId,
|
|
520
|
+
startTimestamp: sessionTimestamp // Use the same timestamp base
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
try {
|
|
524
|
+
await this.startCursorCapture(cursorFilePath, standardCursorOptions);
|
|
525
|
+
console.log('✅ SYNC: Cursor tracking started successfully');
|
|
526
|
+
} catch (cursorError) {
|
|
527
|
+
console.warn('⚠️ Cursor tracking failed to start:', cursorError.message);
|
|
528
|
+
// Continue with recording even if cursor fails
|
|
529
|
+
}
|
|
530
|
+
|
|
510
531
|
let success;
|
|
511
532
|
try {
|
|
533
|
+
console.log('🎯 SYNC: Starting screen recording at timestamp:', sessionTimestamp);
|
|
512
534
|
success = nativeBinding.startRecording(
|
|
513
535
|
outputPath,
|
|
514
536
|
recordingOptions
|
|
515
537
|
);
|
|
538
|
+
if (success) {
|
|
539
|
+
console.log('✅ SYNC: Screen recording started successfully');
|
|
540
|
+
}
|
|
516
541
|
} catch (error) {
|
|
517
542
|
// console.log('Native recording failed, trying alternative method');
|
|
518
543
|
success = false;
|
|
544
|
+
console.warn('❌ Screen recording failed to start');
|
|
545
|
+
// Stop cursor if recording fails
|
|
546
|
+
if (this.cursorCaptureInterval) {
|
|
547
|
+
console.log('🔄 SYNC: Stopping cursor tracking due to recording failure');
|
|
548
|
+
await this.stopCursorCapture().catch(() => {});
|
|
549
|
+
}
|
|
519
550
|
}
|
|
520
551
|
|
|
521
552
|
if (success) {
|
|
@@ -546,10 +577,12 @@ class MacRecorder extends EventEmitter {
|
|
|
546
577
|
}
|
|
547
578
|
}
|
|
548
579
|
this.isRecording = true;
|
|
549
|
-
|
|
580
|
+
// SYNC FIX: Use session timestamp for consistent timing across all components
|
|
581
|
+
this.recordingStartTime = sessionTimestamp;
|
|
550
582
|
|
|
551
583
|
if (this.options.captureCamera === true && cameraFilePath) {
|
|
552
584
|
this.cameraCaptureActive = true;
|
|
585
|
+
console.log('📹 SYNC: Camera recording started at timestamp:', sessionTimestamp);
|
|
553
586
|
this.emit("cameraCaptureStarted", {
|
|
554
587
|
outputPath: cameraFilePath,
|
|
555
588
|
deviceId: this.options.cameraDeviceId || null,
|
|
@@ -560,6 +593,7 @@ class MacRecorder extends EventEmitter {
|
|
|
560
593
|
|
|
561
594
|
if (captureAudio && audioFilePath) {
|
|
562
595
|
this.audioCaptureActive = true;
|
|
596
|
+
console.log('🎙️ SYNC: Audio recording started at timestamp:', sessionTimestamp);
|
|
563
597
|
this.emit("audioCaptureStarted", {
|
|
564
598
|
outputPath: audioFilePath,
|
|
565
599
|
deviceIds: {
|
|
@@ -571,20 +605,17 @@ class MacRecorder extends EventEmitter {
|
|
|
571
605
|
});
|
|
572
606
|
}
|
|
573
607
|
|
|
574
|
-
//
|
|
575
|
-
//
|
|
576
|
-
const standardCursorOptions = {
|
|
577
|
-
videoRelative: true,
|
|
578
|
-
displayInfo: this.recordingDisplayInfo,
|
|
579
|
-
recordingType: this.options.windowId ? 'window' :
|
|
580
|
-
this.options.captureArea ? 'area' : 'display',
|
|
581
|
-
captureArea: this.options.captureArea,
|
|
582
|
-
windowId: this.options.windowId
|
|
583
|
-
};
|
|
608
|
+
// SYNC FIX: Cursor tracking already started BEFORE recording for perfect sync
|
|
609
|
+
// (Removed duplicate cursor start code)
|
|
584
610
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
611
|
+
// Log synchronized recording summary
|
|
612
|
+
const activeComponents = [];
|
|
613
|
+
activeComponents.push('Screen');
|
|
614
|
+
if (this.cursorCaptureInterval) activeComponents.push('Cursor');
|
|
615
|
+
if (this.cameraCaptureActive) activeComponents.push('Camera');
|
|
616
|
+
if (this.audioCaptureActive) activeComponents.push('Audio');
|
|
617
|
+
console.log(`✅ SYNC COMPLETE: All components synchronized at timestamp ${sessionTimestamp}`);
|
|
618
|
+
console.log(` Active components: ${activeComponents.join(', ')}`);
|
|
588
619
|
|
|
589
620
|
// Timer başlat (progress tracking için)
|
|
590
621
|
this.recordingTimer = setInterval(() => {
|
|
@@ -696,20 +727,38 @@ class MacRecorder extends EventEmitter {
|
|
|
696
727
|
|
|
697
728
|
|
|
698
729
|
/**
|
|
699
|
-
* Ekran kaydını durdurur
|
|
730
|
+
* Ekran kaydını durdurur - SYNCHRONIZED stop for all components
|
|
700
731
|
*/
|
|
701
732
|
async stopRecording() {
|
|
702
733
|
if (!this.isRecording) {
|
|
703
734
|
throw new Error("No recording in progress");
|
|
704
735
|
}
|
|
705
736
|
|
|
706
|
-
return new Promise((resolve, reject) => {
|
|
737
|
+
return new Promise(async (resolve, reject) => {
|
|
707
738
|
try {
|
|
739
|
+
console.log('🛑 SYNC: Stopping all recording components simultaneously');
|
|
740
|
+
|
|
741
|
+
// SYNC FIX: Stop ALL components at the same time for perfect sync
|
|
742
|
+
// 1. Stop cursor tracking FIRST (it's instant)
|
|
743
|
+
if (this.cursorCaptureInterval) {
|
|
744
|
+
try {
|
|
745
|
+
console.log('🛑 SYNC: Stopping cursor tracking');
|
|
746
|
+
await this.stopCursorCapture();
|
|
747
|
+
console.log('✅ SYNC: Cursor tracking stopped');
|
|
748
|
+
} catch (cursorError) {
|
|
749
|
+
console.warn('⚠️ Cursor tracking failed to stop:', cursorError.message);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
708
753
|
let success = false;
|
|
709
|
-
|
|
710
|
-
//
|
|
754
|
+
|
|
755
|
+
// 2. Stop native screen recording
|
|
711
756
|
try {
|
|
757
|
+
console.log('🛑 SYNC: Stopping screen recording');
|
|
712
758
|
success = nativeBinding.stopRecording();
|
|
759
|
+
if (success) {
|
|
760
|
+
console.log('✅ SYNC: Screen recording stopped');
|
|
761
|
+
}
|
|
713
762
|
} catch (nativeError) {
|
|
714
763
|
// console.log('Native stop failed:', nativeError.message);
|
|
715
764
|
success = true; // Assume success to avoid throwing
|
|
@@ -744,6 +793,7 @@ class MacRecorder extends EventEmitter {
|
|
|
744
793
|
|
|
745
794
|
if (this.cameraCaptureActive) {
|
|
746
795
|
this.cameraCaptureActive = false;
|
|
796
|
+
console.log('📹 SYNC: Camera recording stopped');
|
|
747
797
|
this.emit("cameraCaptureStopped", {
|
|
748
798
|
outputPath: this.cameraCaptureFile || null,
|
|
749
799
|
success: success === true,
|
|
@@ -753,6 +803,7 @@ class MacRecorder extends EventEmitter {
|
|
|
753
803
|
|
|
754
804
|
if (this.audioCaptureActive) {
|
|
755
805
|
this.audioCaptureActive = false;
|
|
806
|
+
console.log('🎙️ SYNC: Audio recording stopped');
|
|
756
807
|
this.emit("audioCaptureStopped", {
|
|
757
808
|
outputPath: this.audioCaptureFile || null,
|
|
758
809
|
success: success === true,
|
|
@@ -760,12 +811,11 @@ class MacRecorder extends EventEmitter {
|
|
|
760
811
|
});
|
|
761
812
|
}
|
|
762
813
|
|
|
763
|
-
//
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
814
|
+
// SYNC FIX: Cursor tracking already stopped at the beginning for sync
|
|
815
|
+
// (Removed duplicate cursor stop code)
|
|
816
|
+
|
|
817
|
+
// Log synchronized stop summary
|
|
818
|
+
console.log('✅ SYNC STOP COMPLETE: All recording components stopped simultaneously');
|
|
769
819
|
|
|
770
820
|
// Timer durdur
|
|
771
821
|
if (this.recordingTimer) {
|
|
@@ -964,6 +1014,7 @@ class MacRecorder extends EventEmitter {
|
|
|
964
1014
|
* @param {string} options.recordingType - Type of recording: 'display', 'window', 'area'
|
|
965
1015
|
* @param {Object} options.captureArea - Capture area for area recording coordinate transformation
|
|
966
1016
|
* @param {number} options.windowId - Window ID for window recording coordinate transformation
|
|
1017
|
+
* @param {number} options.startTimestamp - Pre-defined start timestamp for synchronization (optional)
|
|
967
1018
|
*/
|
|
968
1019
|
async startCursorCapture(intervalOrFilepath = 100, options = {}) {
|
|
969
1020
|
let filepath;
|
|
@@ -985,6 +1036,9 @@ class MacRecorder extends EventEmitter {
|
|
|
985
1036
|
throw new Error("Cursor capture is already running");
|
|
986
1037
|
}
|
|
987
1038
|
|
|
1039
|
+
// SYNC FIX: Use pre-defined timestamp if provided for synchronization
|
|
1040
|
+
const syncStartTime = options.startTimestamp || Date.now();
|
|
1041
|
+
|
|
988
1042
|
// Use video-relative coordinate system for all recording types
|
|
989
1043
|
if (options.videoRelative && options.displayInfo) {
|
|
990
1044
|
// Calculate video offset based on recording type
|
|
@@ -1068,7 +1122,8 @@ class MacRecorder extends EventEmitter {
|
|
|
1068
1122
|
fs.writeFileSync(filepath, "[");
|
|
1069
1123
|
|
|
1070
1124
|
this.cursorCaptureFile = filepath;
|
|
1071
|
-
|
|
1125
|
+
// SYNC FIX: Use synchronized start time for accurate timestamp calculation
|
|
1126
|
+
this.cursorCaptureStartTime = syncStartTime;
|
|
1072
1127
|
this.cursorCaptureFirstWrite = true;
|
|
1073
1128
|
this.lastCapturedData = null;
|
|
1074
1129
|
|