node-mac-recorder 2.24.0 → 2.24.1

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 +85 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -866,6 +866,31 @@ class MacRecorder extends EventEmitter {
866
866
  this.recordingStartTime = syncTimestamp;
867
867
  console.log(`🎯 CURSOR SYNC: Cursor tracking will use timestamp: ${syncTimestamp}`);
868
868
 
869
+ // CURSOR/VIDEO TIME ALIGNMENT:
870
+ // Cursor timeline'in t=0'i bu andir (syncTimestamp), ama videonun
871
+ // ILK KARESI daha once yakalanmis olabilir (ScreenCaptureKit
872
+ // baslatma gecikmesi + yukaridaki hazir-olma beklemesi). Editor
873
+ // "cursor'un ilk ornegi = video t=0" varsayarsa aradaki fark sabit
874
+ // bir zaman kaymasi olarak kalir. Native gercek video baslangicini
875
+ // biliyor; okuyup sakla ki stop'ta cursor JSON'una yazabilelim.
876
+ this.videoStartTimestamp = 0;
877
+ try {
878
+ const nativeVideoStart =
879
+ typeof nativeBinding.getVideoStartTimestamp === 'function'
880
+ ? Number(nativeBinding.getVideoStartTimestamp())
881
+ : 0;
882
+ if (Number.isFinite(nativeVideoStart) && nativeVideoStart > 0) {
883
+ this.videoStartTimestamp = nativeVideoStart;
884
+ console.log(
885
+ `🎯 SYNC: Video first-frame timestamp: ${nativeVideoStart} (cursor starts ${(syncTimestamp - nativeVideoStart).toFixed(0)}ms later)`
886
+ );
887
+ } else {
888
+ console.warn('⚠️ SYNC: Video start timestamp unavailable — cursor sync metadata will be skipped');
889
+ }
890
+ } catch (videoStartError) {
891
+ console.warn('⚠️ SYNC: Video start timestamp read failed:', videoStartError.message);
892
+ }
893
+
869
894
  const standardCursorOptions = {
870
895
  videoRelative: true,
871
896
  displayInfo: this.recordingDisplayInfo,
@@ -1709,12 +1734,20 @@ class MacRecorder extends EventEmitter {
1709
1734
  this.cursorCaptureInterval = null;
1710
1735
 
1711
1736
  // Dosyayı kapat
1737
+ let closedCursorFile = null;
1712
1738
  if (this.cursorCaptureFile) {
1713
1739
  const fs = require("fs");
1714
1740
  fs.appendFileSync(this.cursorCaptureFile, "]");
1741
+ closedCursorFile = this.cursorCaptureFile;
1715
1742
  this.cursorCaptureFile = null;
1716
1743
  }
1717
1744
 
1745
+ // Cursor/video zaman hizalama bilgisini dosyaya yaz (editör bunu
1746
+ // okuyup sabit kaymayı telafi ediyor).
1747
+ if (closedCursorFile) {
1748
+ this._writeCursorSyncMetadata(closedCursorFile);
1749
+ }
1750
+
1718
1751
  // Değişkenleri temizle
1719
1752
  this.lastCapturedData = null;
1720
1753
  this.cursorCaptureStartTime = null;
@@ -1729,6 +1762,58 @@ class MacRecorder extends EventEmitter {
1729
1762
  });
1730
1763
  }
1731
1764
 
1765
+ /**
1766
+ * Cursor JSON'una video/cursor zaman hizalama bilgisini yazar.
1767
+ *
1768
+ * NEDEN: Cursor timeline'inin t=0'i `syncTimestamp` (kayit hazir olduktan
1769
+ * sonraki an), videonun t=0'i ise ILK KARENIN yakalandigi an. ScreenCaptureKit
1770
+ * baslatma gecikmesi yuzunden bu ikisi ayni degil; fark bilinmezse oynatimda
1771
+ * sabit bir zaman kaymasi olusur (cursor video ile "sync tutmuyor").
1772
+ * Editor tarafi `_syncMetadata.videoStartTime` / `cursorStartTime` okuyup
1773
+ * tam telafi ediyor — burada sadece gercek degerleri yaziyoruz.
1774
+ *
1775
+ * Dosyanin ilk noktasina yazilir; okuyucu ilk metadata'yi bulup kullanir.
1776
+ */
1777
+ _writeCursorSyncMetadata(cursorFilePath) {
1778
+ const videoStartTime = Number(this.videoStartTimestamp);
1779
+ const cursorStartTime = Number(this.syncTimestamp);
1780
+ if (
1781
+ !Number.isFinite(videoStartTime) ||
1782
+ videoStartTime <= 0 ||
1783
+ !Number.isFinite(cursorStartTime) ||
1784
+ cursorStartTime <= 0
1785
+ ) {
1786
+ // Native video baslangici okunamadiysa metadata yazma — editor eski
1787
+ // (telafisiz) davranisa duser, yanlis bir offset uygulamaktan iyidir.
1788
+ return;
1789
+ }
1790
+
1791
+ try {
1792
+ const fs = require("fs");
1793
+ const raw = fs.readFileSync(cursorFilePath, "utf8");
1794
+ const positions = JSON.parse(raw);
1795
+ if (!Array.isArray(positions) || positions.length === 0) return;
1796
+
1797
+ positions[0]._syncMetadata = {
1798
+ videoStartTime,
1799
+ cursorStartTime,
1800
+ startDelayMs: cursorStartTime - videoStartTime,
1801
+ recordingType: this.options?.windowId
1802
+ ? "window"
1803
+ : this.options?.captureArea
1804
+ ? "area"
1805
+ : "display",
1806
+ };
1807
+
1808
+ fs.writeFileSync(cursorFilePath, JSON.stringify(positions));
1809
+ console.log(
1810
+ `🎯 SYNC: Cursor sync metadata written (video→cursor delay ${(cursorStartTime - videoStartTime).toFixed(0)}ms)`
1811
+ );
1812
+ } catch (error) {
1813
+ console.warn("⚠️ SYNC: Cursor sync metadata write failed:", error.message);
1814
+ }
1815
+ }
1816
+
1732
1817
  /**
1733
1818
  * Klavye kısayolu (shortcut) yakalamayı başlatır.
1734
1819
  * Native CGEventTap keyDown olaylarını dinler; yalnızca ⌘/⌃/⌥ modifier'lı
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.24.0",
3
+ "version": "2.24.1",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [