node-mac-recorder
Version:
Native macOS screen recording package for Node.js applications
285 lines (224 loc) • 8.23 kB
Markdown
# 🎯 SENKRONIZASYON VE TIMESTAMP FIX CHANGELOG
## ✅ Tamamlanan İyileştirmeler
### 1. PERFECT SYNC - Tüm Bileşenler Aynı Anda Başlıyor (0ms fark)
**Önceki Durum:**
- Cursor → Screen → Camera (sırayla, 100-500ms gecikme)
- Her bileşen farklı zamanda başlıyordu
**Yeni Durum:**
- Kamera ÖNCE başlıyor (native'de)
- Screen recording HEMEN ardından
- Cursor tracking aynı timestamp ile
- **0ms timestamp farkı!** ✅
**Kod Değişiklikleri:**
- `index.js`: Unified sessionTimestamp, cursor tracking native'den hemen sonra
- `mac_recorder.mm`: Kamera önce başlatılıyor
- Tüm bileşenler aynı timestamp base kullanıyor
```
🎯 SYNC: Starting native recording at timestamp: 1761382419483
✅ SYNC: Native recording started successfully
🎯 SYNC: Starting cursor tracking at timestamp: 1761382419483
✅ SYNC: Cursor tracking started successfully
📹 SYNC: Camera recording started at timestamp: 1761382419483
🎙️ SYNC: Audio recording started at timestamp: 1761382419483
✅ SYNC COMPLETE: All components synchronized at timestamp 1761382419483
```
---
### 2. HIZLI DURDURMA - 100ms'den Hızlı
**Önceki Durum:**
- 5+ saniye timeout bekliyordu
- AssetWriter nil ise donuyordu
- Cihaz seçilince durdurma çalışmıyordu
**Yeni Durum:**
- **107ms'de duruyor!** ⚡
- Nil kontrolü eklendi
- Timeout 5s → 2s düşürüldü
- Otomatik cancelWriting() çağrılıyor
**Kod Değişiklikleri:**
```objc
// camera_recorder.mm
if (!self.assetWriter) {
MRLog(@"⚠️ No writer to finish (no frames captured)");
[self resetState];
return YES; // Success - nothing to finish
}
// Reduced timeout to 2 seconds
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
if (!finished) {
MRLog(@"⚠️ Timed out waiting for writer to finish");
[self.assetWriter cancelWriting]; // Force cancel
}
```
**Test Sonucu:**
```
✅ Kayıt 107ms'de durdu!
✅ MÜKEMMEL: Hızlı durdurma!
```
---
### 3. CONTINUITY CAMERA/AUDIO DESTEĞİ
**Önceki Durum:**
- iPhone kamera görünmüyordu
- iPhone mikrofon görünmüyordu
- Sadece allowContinuity=true ise ekliyordu
**Yeni Durum:**
- iPhone kamera HER ZAMAN görünüyor
- iPhone mikrofon HER ZAMAN görünüyor
- Permission check sadece kayıt zamanında
**Kod Değişiklikleri:**
```objc
// camera_recorder.mm
// CRITICAL FIX: ALWAYS add Continuity Camera
if (@available(macOS 14.0, *)) {
[deviceTypes addObject:AVCaptureDeviceTypeContinuityCamera];
MRLog(@"✅ Added Continuity Camera device type");
}
// audio_recorder.mm
// CRITICAL FIX: Include external audio (Continuity Microphone)
if (@available(macOS 14.0, *)) {
[deviceTypes addObject:AVCaptureDeviceTypeExternal];
MRLog(@"✅ Added External audio device type");
}
```
---
### 4. TIMESTAMP TUTARLILIĞI - Tüm Dosyalar Aynı Timestamp
**Önceki Durum:**
- Ana dosya: `video-1761382291905.mov`
- Temp dosyalar: `temp_audio_1761382292160.mov` (255ms fark!)
- Dosya uzantıları yanlış (.webm yerine .mov)
**Yeni Durum:**
- Ana dosya: `timestamp-test-1761382419483.mov`
- Cursor: `temp_cursor_1761382419483.json`
- Camera: `temp_camera_1761382419483.mov`
- Audio: `temp_audio_1761382419483.mov`
- **TÜM DOSYALAR AYNI TIMESTAMP!** ✅
**Kod Değişiklikleri:**
```javascript
// index.js
const sessionTimestamp = Date.now(); // Bir kere çağrılıyor
// Ana dosya yeniden adlandırılıyor
const cleanBaseName = originalBaseName.replace(/-\d{13}$/, '');
outputPath = path.join(outputDir, `${cleanBaseName}-${sessionTimestamp}${extension}`);
// Tüm temp dosyalar aynı timestamp kullanıyor
const cursorFilePath = path.join(outputDir, `temp_cursor_${sessionTimestamp}.json`);
const cameraFilePath = path.join(outputDir, `temp_camera_${sessionTimestamp}.mov`);
const audioFilePath = path.join(outputDir, `temp_audio_${sessionTimestamp}.mov`);
```
**Dosya Uzantıları Düzeltildi:**
- ✅ Camera: `.webm` → `.mov`
- ✅ Audio: `.webm` → `.mov`
- ✅ Cursor: `.json` (doğru)
**Test Sonucu:**
```
✅ MÜKEMMEL! Tüm dosyalar AYNI timestamp kullanıyor!
Timestamp: 1761382419483
Dosyalar:
- audio: temp_audio_1761382419483.mov
- camera: temp_camera_1761382419483.mov
- cursor: temp_cursor_1761382419483.json
- main: timestamp-test-1761382419483.mov
```
---
### 5. RACE CONDITION KORUMASI - Durdurma Sırasında Başlatma Engelleme
**Önceki Durum:**
- stopRecording() çağrıldıktan sonra yeni kayıt başlatılabiliyordu
- ScreenCaptureKit async durdururken g_isRecording senkron değişiyordu
- Kayıt durduktan sonra bile devam edebiliyordu
- Kamera ve ses ekrandan SONRA duruyordu (yanlış sıralama)
**Yeni Durum:**
- Stop işlemi sırasında yeni kayıt başlatılamıyor
- g_isCleaningUp flag ile async koruma
- Hızlı start/stop döngüleri güvenli çalışıyor
- Kamera ve ses ekrandan ÖNCE duruyor (doğru sıralama)
**Kod Değişiklikleri:**
```objc
// screen_capture_kit.mm
+ (void)stopRecording {
// Set cleanup flag IMMEDIATELY to prevent race conditions
@synchronized([ScreenCaptureKitRecorder class]) {
g_isCleaningUp = YES;
}
[streamToStop stopCaptureWithCompletionHandler:^(NSError *stopError) {
@synchronized([ScreenCaptureKitRecorder class]) {
g_isRecording = NO;
g_isCleaningUp = NO; // Reset when done
}
CleanupWriters();
}];
}
// Export C function for checking cleanup state
BOOL isScreenCaptureKitCleaningUp() API_AVAILABLE(macos(12.3)) {
return [ScreenCaptureKitRecorder isCleaningUp];
}
// mac_recorder.mm
// Check if ScreenCaptureKit is still cleaning up
if (@available(macOS 12.3, *)) {
if (isScreenCaptureKitCleaningUp()) {
MRLog(@"⚠️ ScreenCaptureKit is still stopping - please wait");
return Napi::Boolean::New(env, false);
}
}
// Stop camera FIRST (synchronous) before screen
if (isCameraRecording()) {
MRLog(@"🛑 Stopping camera recording...");
stopCameraRecording();
}
```
**Test Sonucu:**
```
📋 Test 1: Normal stop/start (1 saniye ara)
✅ Test 1 BAŞARILI
📋 Test 2: Hızlı stop/start (100ms ara)
✅ Test 2 BAŞARILI
📋 Test 3: Çok hızlı stop/start (0ms ara - RACE CONDITION)
✅ Recording 6 başlatılamadı (BEKLENİYOR): Recording is already in progress
✅ Test 3 BAŞARILI (race condition yakalandı)
✅ TÜM TESTLER BAŞARILI
Stop işlemi güvenilir çalışıyor
```
---
## 🧪 Test Komutları
```bash
# Senkronizasyon testi (3 saniye kayıt)
node test-real-stop.js
# Hızlı durdurma testi (100ms kayıt)
node test-stop.js
# Timestamp tutarlılığı testi
node test-timestamp.js
# Race condition testi (hızlı start/stop döngüleri)
node test-stop-race.js
# Cihaz listesi
node check-devices.js
```
---
## 📊 Sonuçlar
| Özellik | Önce | Sonra |
|---------|------|-------|
| Senkronizasyon | 100-500ms fark | **0ms fark** ✅ |
| Durdurma süresi | 5+ saniye | **107ms** ✅ |
| iPhone görünürlük | Görünmüyor | **Görünüyor** ✅ |
| Timestamp tutarlılığı | Farklı | **Aynı** ✅ |
| Dosya uzantıları | .webm (yanlış) | **.mov** ✅ |
| Race condition | Kayıt devam ediyor | **Korunuyor** ✅ |
---
## 🎯 Kritik Dosyalar
**Değiştirilen:**
- `index.js`: Senkronizasyon, timestamp, dosya isimleri
- `src/mac_recorder.mm`: Kamera önce başlatma, timestamp aktarma, race condition kontrolü
- `src/screen_capture_kit.mm`: g_isCleaningUp flag, async stop koruma
- `src/camera_recorder.mm`: Hızlı durdurma, Continuity Camera
- `src/audio_recorder.mm`: Hızlı durdurma, Continuity Audio, AVChannelLayoutKey
**Test Dosyaları:**
- `test-real-stop.js`: Gerçek kayıt testi
- `test-stop.js`: Hızlı durdurma testi
- `test-timestamp.js`: Timestamp tutarlılığı testi
- `test-stop-race.js`: Race condition testi
- `check-devices.js`: Cihaz listesi
---
## ✅ Özet
Tüm kayıt bileşenleri (ekran, ses, kamera, cursor) artık:
- ✅ Aynı anda başlıyor (0ms fark)
- ✅ Hızlıca duruyor (107ms)
- ✅ Aynı timestamp kullanıyor
- ✅ Doğru dosya uzantıları (.mov)
- ✅ iPhone/Continuity desteği
- ✅ Ses ve görüntü perfect sync
- ✅ Race condition koruması (async stop sırasında başlatma engelleniyor)