node-mac-recorder 2.24.2 → 2.24.3

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.
Files changed (2) hide show
  1. package/index.js +64 -13
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -891,6 +891,8 @@ class MacRecorder extends EventEmitter {
891
891
  // bir zaman kaymasi olarak kalir. Native gercek video baslangicini
892
892
  // biliyor; okuyup sakla ki stop'ta cursor JSON'una yazabilelim.
893
893
  this.videoStartTimestamp = 0;
894
+ // Onceki kayittan kalan referans sizmasin
895
+ this.timelineStartTimestamp = 0;
894
896
  try {
895
897
  const nativeVideoStart =
896
898
  typeof nativeBinding.getVideoStartTimestamp === 'function'
@@ -908,6 +910,28 @@ class MacRecorder extends EventEmitter {
908
910
  console.warn('⚠️ SYNC: Video start timestamp read failed:', videoStartError.message);
909
911
  }
910
912
 
913
+ // ZAMAN REFERANSI: cursor/klavye timeline'i VIDEONUN ilk karesine
914
+ // hizalanir, JS'in "kayit hazir" dedigi ana degil.
915
+ //
916
+ // NEDEN: syncTimestamp, yukaridaki hazir-olma dongusunden sonraki an.
917
+ // Bu an ile videonun gercek t=0'i arasindaki fark, baslatma hizina
918
+ // gore DEGISIYOR (ornegin ScreenCaptureKit isitilmissa video cok daha
919
+ // erken basliyor). Cursor bu degisken ana baglanirsa her kayitta
920
+ // farkli bir kayma olusuyor ve editordeki telafi 1sn limitine
921
+ // takilabiliyor. Videonun kendi baslangicini referans alinca fark
922
+ // yapisal olarak sifir olur; hizlanma senkronu bozmaz.
923
+ const timelineStartTimestamp =
924
+ this.videoStartTimestamp > 0
925
+ ? this.videoStartTimestamp
926
+ : syncTimestamp;
927
+ this.timelineStartTimestamp = timelineStartTimestamp;
928
+
929
+ if (timelineStartTimestamp !== syncTimestamp) {
930
+ console.log(
931
+ `🎯 SYNC: Timeline referansi video ilk karesine cekildi (${(syncTimestamp - timelineStartTimestamp).toFixed(0)}ms geri)`
932
+ );
933
+ }
934
+
911
935
  const standardCursorOptions = {
912
936
  videoRelative: true,
913
937
  displayInfo: this.recordingDisplayInfo,
@@ -915,11 +939,11 @@ class MacRecorder extends EventEmitter {
915
939
  this.options.captureArea ? 'area' : 'display',
916
940
  captureArea: this.options.captureArea,
917
941
  windowId: this.options.windowId,
918
- startTimestamp: syncTimestamp // Align cursor timeline to actual start
942
+ startTimestamp: timelineStartTimestamp
919
943
  };
920
944
 
921
945
  try {
922
- console.log('🎯 SYNC: Starting cursor tracking at timestamp:', syncTimestamp);
946
+ console.log('🎯 SYNC: Starting cursor tracking at timestamp:', timelineStartTimestamp);
923
947
  await this.startCursorCapture(cursorFilePath, standardCursorOptions);
924
948
  console.log('✅ SYNC: Cursor tracking started successfully');
925
949
  } catch (cursorError) {
@@ -929,8 +953,8 @@ class MacRecorder extends EventEmitter {
929
953
 
930
954
  // Klavye kısayolu yakalama (cursor ile AYNI zaman referansı)
931
955
  try {
932
- console.log('⌨️ SYNC: Starting keyboard shortcut capture at timestamp:', syncTimestamp);
933
- await this.startKeyboardCapture(keyboardFilePath, { startTimestamp: syncTimestamp });
956
+ console.log('⌨️ SYNC: Starting keyboard shortcut capture at timestamp:', timelineStartTimestamp);
957
+ await this.startKeyboardCapture(keyboardFilePath, { startTimestamp: timelineStartTimestamp });
934
958
  console.log('✅ SYNC: Keyboard shortcut capture started successfully');
935
959
  } catch (keyboardError) {
936
960
  console.warn('⚠️ Keyboard capture failed to start:', keyboardError.message);
@@ -1021,7 +1045,8 @@ class MacRecorder extends EventEmitter {
1021
1045
 
1022
1046
  // Native kayıt gerçekten başladığını kontrol etmek için polling başlat
1023
1047
  let recordingStartedEmitted = false;
1024
- const checkRecordingStatus = setInterval(() => {
1048
+ let checkRecordingStatus = null;
1049
+ const pollRecordingStatus = () => {
1025
1050
  try {
1026
1051
  const nativeStatus = nativeBinding.getRecordingStatus();
1027
1052
  if (nativeStatus && !recordingStartedEmitted) {
@@ -1067,8 +1092,10 @@ class MacRecorder extends EventEmitter {
1067
1092
  });
1068
1093
  }
1069
1094
  }
1070
- }, 50); // Her 50ms kontrol et
1071
-
1095
+ };
1096
+
1097
+ checkRecordingStatus = setInterval(pollRecordingStatus, 50);
1098
+
1072
1099
  // Timeout fallback - 5 saniye sonra hala başlamamışsa emit et
1073
1100
  setTimeout(() => {
1074
1101
  if (!recordingStartedEmitted) {
@@ -1700,12 +1727,30 @@ class MacRecorder extends EventEmitter {
1700
1727
  }
1701
1728
 
1702
1729
  // Add sync metadata to first event only
1730
+ //
1731
+ // KRITIK: `videoStartTime` SADECE native'in bildirdigi gercek video
1732
+ // baslangici varsa yazilir. Onceden buraya `cursorCaptureSessionTimestamp`
1733
+ // yaziliyordu; o videonun ilk karesi DEGIL, dosya adi icin uretilen
1734
+ // oturum damgasi. Editor (cursorPlaybackTimeline) bu alani video t=0
1735
+ // sanip birebir telafi uyguladigi icin cursor kayiyordu.
1736
+ // Gercek deger yoksa alani hic yazmiyoruz -> editor heuristik
1737
+ // hizalamaya duser, ki yanlis bir offset uygulamaktan iyidir.
1703
1738
  if (this.cursorCaptureFirstWrite && this.cursorCaptureSessionTimestamp) {
1704
- cursorData._syncMetadata = {
1705
- videoStartTime: this.cursorCaptureSessionTimestamp,
1706
- cursorStartTime: this.cursorCaptureStartTime,
1707
- offsetMs: this.cursorCaptureStartTime - this.cursorCaptureSessionTimestamp
1708
- };
1739
+ const knownVideoStart =
1740
+ Number(this.videoStartTimestamp) > 0
1741
+ ? Number(this.videoStartTimestamp)
1742
+ : null;
1743
+
1744
+ cursorData._syncMetadata = knownVideoStart
1745
+ ? {
1746
+ videoStartTime: knownVideoStart,
1747
+ cursorStartTime: this.cursorCaptureStartTime,
1748
+ offsetMs: this.cursorCaptureStartTime - knownVideoStart,
1749
+ }
1750
+ : {
1751
+ cursorStartTime: this.cursorCaptureStartTime,
1752
+ sessionTimestamp: this.cursorCaptureSessionTimestamp,
1753
+ };
1709
1754
  }
1710
1755
 
1711
1756
  // Sadece eventType değiştiğinde veya pozisyon değiştiğinde kaydet
@@ -1793,7 +1838,13 @@ class MacRecorder extends EventEmitter {
1793
1838
  */
1794
1839
  _writeCursorSyncMetadata(cursorFilePath) {
1795
1840
  const videoStartTime = Number(this.videoStartTimestamp);
1796
- const cursorStartTime = Number(this.syncTimestamp);
1841
+ // Cursor timeline'inin GERCEK referansi. Video baslangici okunabildiyse
1842
+ // timeline zaten ona hizalandi (delay 0); okunamadiysa syncTimestamp'e
1843
+ // dusuldu. Burada varsayim yapmak yerine kullanilan degeri yaziyoruz,
1844
+ // aksi halde editor var olmayan bir kaymayi telafi etmeye calisir.
1845
+ const cursorStartTime = Number(
1846
+ this.timelineStartTimestamp || this.syncTimestamp
1847
+ );
1797
1848
  if (
1798
1849
  !Number.isFinite(videoStartTime) ||
1799
1850
  videoStartTime <= 0 ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.24.2",
3
+ "version": "2.24.3",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [