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.
- package/index.js +85 -0
- 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ı
|