node-mac-recorder 1.2.10 → 1.2.11

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.
@@ -6,7 +6,11 @@
6
6
  "Bash(rm:*)",
7
7
  "Bash(python3:*)",
8
8
  "Bash(grep:*)",
9
- "Bash(cat:*)"
9
+ "Bash(cat:*)",
10
+ "Bash(brew install:*)",
11
+ "Bash(open:*)",
12
+ "Bash(curl:*)",
13
+ "Bash(system_profiler:*)"
10
14
  ],
11
15
  "deny": []
12
16
  }
package/README.md CHANGED
@@ -93,6 +93,7 @@ await recorder.startRecording("./recording.mov", {
93
93
  includeMicrophone: false, // Enable microphone (default: false)
94
94
  includeSystemAudio: true, // Enable system audio (default: true)
95
95
  audioDeviceId: "device-id", // Specific audio input device (default: system default)
96
+ systemAudioDeviceId: "system-device-id", // Specific system audio device (auto-detected by default)
96
97
 
97
98
  // Display & Window Selection
98
99
  displayId: 0, // Display index (null = main display)
@@ -348,19 +349,62 @@ await new Promise((resolve) => setTimeout(resolve, 8000));
348
349
  await recorder.stopRecording();
349
350
  ```
350
351
 
351
- ### Audio-Only System Recording
352
+ ### Advanced System Audio Recording
352
353
 
353
354
  ```javascript
354
355
  const recorder = new MacRecorder();
355
356
 
356
- // Record system audio without microphone
357
- await recorder.startRecording("./system-audio.mov", {
358
- includeMicrophone: false,
359
- includeSystemAudio: true,
360
- captureArea: { x: 0, y: 0, width: 1, height: 1 }, // Minimal video
357
+ // List available audio devices to find system audio devices
358
+ const audioDevices = await recorder.getAudioDevices();
359
+ console.log("Available audio devices:");
360
+ audioDevices.forEach((device, i) => {
361
+ console.log(`${i + 1}. ${device.name} (ID: ${device.id})`);
361
362
  });
363
+
364
+ // Find system audio device (like BlackHole, Soundflower, etc.)
365
+ const systemAudioDevice = audioDevices.find(device =>
366
+ device.name.toLowerCase().includes('blackhole') ||
367
+ device.name.toLowerCase().includes('soundflower') ||
368
+ device.name.toLowerCase().includes('loopback') ||
369
+ device.name.toLowerCase().includes('aggregate')
370
+ );
371
+
372
+ if (systemAudioDevice) {
373
+ console.log(`Using system audio device: ${systemAudioDevice.name}`);
374
+
375
+ // Record with specific system audio device
376
+ await recorder.startRecording("./system-audio-specific.mov", {
377
+ includeMicrophone: false,
378
+ includeSystemAudio: true,
379
+ systemAudioDeviceId: systemAudioDevice.id, // Specify exact device
380
+ captureArea: { x: 0, y: 0, width: 1, height: 1 }, // Minimal video
381
+ });
382
+ } else {
383
+ console.log("No system audio device found. Installing BlackHole or Soundflower recommended.");
384
+
385
+ // Record with default system audio capture (may not work without virtual audio device)
386
+ await recorder.startRecording("./system-audio-default.mov", {
387
+ includeMicrophone: false,
388
+ includeSystemAudio: true, // Auto-detect system audio device
389
+ captureArea: { x: 0, y: 0, width: 1, height: 1 },
390
+ });
391
+ }
392
+
393
+ // Record for 10 seconds
394
+ await new Promise(resolve => setTimeout(resolve, 10000));
395
+ await recorder.stopRecording();
362
396
  ```
363
397
 
398
+ **System Audio Setup:**
399
+
400
+ For reliable system audio capture, install a virtual audio device:
401
+
402
+ 1. **BlackHole** (Free): https://github.com/ExistentialAudio/BlackHole
403
+ 2. **Soundflower** (Free): https://github.com/mattingalls/Soundflower
404
+ 3. **Loopback** (Paid): https://rogueamoeba.com/loopback/
405
+
406
+ These create aggregate audio devices that the package can detect and use for system audio capture.
407
+
364
408
  ### Event-Driven Recording
365
409
 
366
410
  ```javascript
package/debug-audio.js ADDED
@@ -0,0 +1,79 @@
1
+ const MacRecorder = require('./index');
2
+
3
+ async function debugAudio() {
4
+ const recorder = new MacRecorder();
5
+
6
+ console.log('🔍 SES CİHAZI DEBUG RAPORU\n');
7
+
8
+ try {
9
+ // Tüm ses cihazlarını detayları ile listele
10
+ const devices = await recorder.getAudioDevices();
11
+ console.log('📋 TÜM SES CİHAZLARI:');
12
+ devices.forEach((device, index) => {
13
+ console.log(`${index + 1}. ${device.name}`);
14
+ console.log(` ID: ${device.id || 'N/A'}`);
15
+ console.log(` Type: ${device.type || 'N/A'}`);
16
+ console.log(` Manufacturer: ${device.manufacturer || 'N/A'}`);
17
+ console.log(` Default: ${device.isDefault ? 'Yes' : 'No'}`);
18
+ console.log('');
19
+ });
20
+
21
+ // Sistem sesi için uygun cihazları bul
22
+ const systemDevices = devices.filter(device => {
23
+ const name = device.name.toLowerCase();
24
+ return name.includes('aggregate') ||
25
+ name.includes('blackhole') ||
26
+ name.includes('soundflower') ||
27
+ name.includes('loopback') ||
28
+ name.includes('system') ||
29
+ name.includes('imobie');
30
+ });
31
+
32
+ console.log('🎵 SİSTEM SESİ İÇİN UYGUN CİHAZLAR:');
33
+ if (systemDevices.length > 0) {
34
+ systemDevices.forEach((device, index) => {
35
+ console.log(`${index + 1}. ${device.name} (ID: ${device.id})`);
36
+ });
37
+ } else {
38
+ console.log('❌ Sistem sesi cihazı bulunamadı!');
39
+ }
40
+
41
+ console.log('\n💡 ÇÖZÜMLERİ:');
42
+ console.log('1. BlackHole kur: https://github.com/ExistentialAudio/BlackHole/releases');
43
+ console.log('2. Audio MIDI Setup ile Aggregate Device oluştur');
44
+ console.log('3. Sistem sesini aggregate device\'a yönlendir');
45
+
46
+ console.log('\n🔧 MANUAL AGGREGATE DEVICE OLUŞTURMA:');
47
+ console.log('1. Spotlight\'ta "Audio MIDI Setup" ara ve aç');
48
+ console.log('2. Sol alt köşedeki "+" butonuna tıkla');
49
+ console.log('3. "Create Aggregate Device" seç');
50
+ console.log('4. Hem built-in output hem de built-in input\'u seç');
51
+ console.log('5. İsim ver (örn: "System Audio Capture")');
52
+ console.log('6. System Preferences > Sound > Output\'ta yeni cihazı seç');
53
+
54
+ // Test kayıt yap
55
+ console.log('\n🧪 TEST KAYIT YAPILIYOR...');
56
+ console.log('🎵 Şimdi müzik çal veya YouTube video aç!');
57
+
58
+ const testDevice = systemDevices[0]; // İlk sistem ses cihazını kullan
59
+
60
+ await recorder.startRecording('./test-output/debug-audio.mov', {
61
+ includeSystemAudio: true,
62
+ includeMicrophone: false,
63
+ systemAudioDeviceId: testDevice?.id,
64
+ captureArea: { x: 0, y: 0, width: 300, height: 200 }
65
+ });
66
+
67
+ // 3 saniye kayıt
68
+ await new Promise(resolve => setTimeout(resolve, 3000));
69
+ await recorder.stopRecording();
70
+
71
+ console.log('✅ Test kayıt tamamlandı: ./test-output/debug-audio.mov');
72
+ console.log('🔍 Dosyayı QuickTime Player ile açıp ses kontrolü yap');
73
+
74
+ } catch (error) {
75
+ console.error('❌ Debug hatası:', error.message);
76
+ }
77
+ }
78
+
79
+ debugAudio();
package/index.js CHANGED
@@ -111,11 +111,12 @@ class MacRecorder extends EventEmitter {
111
111
  setOptions(options = {}) {
112
112
  this.options = {
113
113
  includeMicrophone: options.includeMicrophone || false,
114
- includeSystemAudio: options.includeSystemAudio !== false, // Default true
114
+ includeSystemAudio: options.includeSystemAudio !== false, // Default true unless explicitly disabled
115
115
  captureCursor: options.captureCursor || false,
116
116
  displayId: options.displayId || null, // null = ana ekran
117
117
  windowId: options.windowId || null, // null = tam ekran
118
118
  audioDeviceId: options.audioDeviceId || null, // null = default device
119
+ systemAudioDeviceId: options.systemAudioDeviceId || null, // null = auto-detect system audio device
119
120
  captureArea: options.captureArea || null,
120
121
  };
121
122
  }
@@ -261,11 +262,12 @@ class MacRecorder extends EventEmitter {
261
262
  // Native kayıt başlat
262
263
  const recordingOptions = {
263
264
  includeMicrophone: this.options.includeMicrophone || false,
264
- includeSystemAudio: this.options.includeSystemAudio !== false, // Default true
265
+ includeSystemAudio: this.options.includeSystemAudio !== false, // Default true unless explicitly disabled
265
266
  captureCursor: this.options.captureCursor || false,
266
267
  displayId: this.options.displayId || null, // null = ana ekran
267
268
  windowId: this.options.windowId || null, // null = tam ekran
268
269
  audioDeviceId: this.options.audioDeviceId || null, // null = default device
270
+ systemAudioDeviceId: this.options.systemAudioDeviceId || null, // null = auto-detect system audio device
269
271
  };
270
272
 
271
273
  // Manuel captureArea varsa onu kullan
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
package/quick-test.js ADDED
@@ -0,0 +1,50 @@
1
+ const MacRecorder = require('./index');
2
+
3
+ async function quickTest() {
4
+ const recorder = new MacRecorder();
5
+
6
+ console.log('🚀 Hızlı Sistem Sesi Testi\n');
7
+
8
+ try {
9
+ // Ses cihazlarını listele
10
+ const devices = await recorder.getAudioDevices();
11
+ console.log('🎤 Mevcut ses cihazları:');
12
+ devices.forEach((d, i) => console.log(`${i+1}. ${d.name}`));
13
+
14
+ // Sistem sesi cihazı var mı?
15
+ const sysDevice = devices.find(d =>
16
+ d.name.toLowerCase().includes('aggregate') ||
17
+ d.name.toLowerCase().includes('blackhole') ||
18
+ d.name.toLowerCase().includes('soundflower')
19
+ );
20
+
21
+ if (sysDevice) {
22
+ console.log(`\n✅ Sistem sesi cihazı bulundu: ${sysDevice.name}`);
23
+ console.log('🎵 Sistem sesi yakalama çalışmalı');
24
+ } else {
25
+ console.log('\n⚠️ Sistem sesi cihazı yok');
26
+ console.log('💡 BlackHole veya Soundflower yüklemen gerekiyor');
27
+ }
28
+
29
+ // Kısa test kayıt
30
+ console.log('\n🔴 2 saniyelik test kayıt başlıyor...');
31
+ console.log('🎵 Şimdi müzik çal!');
32
+
33
+ await recorder.startRecording('./test-output/quick-test.mov', {
34
+ includeSystemAudio: true,
35
+ includeMicrophone: false,
36
+ systemAudioDeviceId: sysDevice?.id,
37
+ captureArea: { x: 0, y: 0, width: 200, height: 150 }
38
+ });
39
+
40
+ await new Promise(resolve => setTimeout(resolve, 2000));
41
+ await recorder.stopRecording();
42
+
43
+ console.log('✅ Test tamamlandı! ./test-output/quick-test.mov dosyasını kontrol et');
44
+
45
+ } catch (error) {
46
+ console.error('❌ Hata:', error.message);
47
+ }
48
+ }
49
+
50
+ quickTest();
@@ -0,0 +1,182 @@
1
+ // ===== SENİN UYGULAMANDA NASIL KULLANACAĞIN =====
2
+
3
+ const MacRecorder = require('node-mac-recorder'); // npm install node-mac-recorder
4
+
5
+ async function myAppRecording() {
6
+ const recorder = new MacRecorder();
7
+
8
+ // === 1. KULLANICIYA SES CİHAZLARINI GÖSTER ===
9
+ const devices = await recorder.getAudioDevices();
10
+ console.log('🎤 Ses cihazları:');
11
+ devices.forEach((d, i) => console.log(`${i+1}. ${d.name}`));
12
+
13
+ // === 2. SİSTEM SESİ CİHAZINI BUL ===
14
+ const systemDevice = devices.find(d =>
15
+ d.name.includes('Aggregate') ||
16
+ d.name.includes('iMobie') ||
17
+ d.name.includes('BlackHole')
18
+ );
19
+
20
+ if (!systemDevice) {
21
+ console.log('⚠️ Sistem ses cihazı yok. Sadece mikrofon kullanılacak.');
22
+ }
23
+
24
+ // === 3. KULLANICI TERCİHLERİ ===
25
+ const userPrefs = {
26
+ recordSystemAudio: true, // Kullanıcının sistem sesi tercihi
27
+ recordMicrophone: false, // Kullanıcının mikrofon tercihi
28
+ outputPath: './my-recording.mov'
29
+ };
30
+
31
+ // === 4. KAYIT BAŞLAT ===
32
+ const options = {
33
+ // Sistem sesi
34
+ includeSystemAudio: userPrefs.recordSystemAudio,
35
+ systemAudioDeviceId: systemDevice?.id, // Bulunan cihazı kullan
36
+
37
+ // Mikrofon
38
+ includeMicrophone: userPrefs.recordMicrophone,
39
+
40
+ // Diğer seçenekler
41
+ captureCursor: true,
42
+ quality: 'high'
43
+ };
44
+
45
+ console.log('🔴 Kayıt başlıyor...', options);
46
+ await recorder.startRecording(userPrefs.outputPath, options);
47
+
48
+ // === 5. KAYDI DURDUR ===
49
+ setTimeout(async () => {
50
+ await recorder.stopRecording();
51
+ console.log('✅ Kayıt bitti:', userPrefs.outputPath);
52
+ }, 5000);
53
+ }
54
+
55
+ // === ELECTRONʼDA KULLANIM ===
56
+ // main.js
57
+ const { ipcMain } = require('electron');
58
+ const MacRecorder = require('node-mac-recorder');
59
+
60
+ const recorder = new MacRecorder();
61
+
62
+ // Renderer'dan gelen istekleri dinle
63
+ ipcMain.handle('get-audio-devices', async () => {
64
+ return await recorder.getAudioDevices();
65
+ });
66
+
67
+ ipcMain.handle('start-recording', async (event, options) => {
68
+ try {
69
+ await recorder.startRecording('./recording.mov', {
70
+ includeSystemAudio: options.systemAudio, // true/false
71
+ includeMicrophone: options.microphone, // true/false
72
+ systemAudioDeviceId: options.systemDeviceId || null
73
+ });
74
+ return { success: true };
75
+ } catch (error) {
76
+ return { success: false, error: error.message };
77
+ }
78
+ });
79
+
80
+ ipcMain.handle('stop-recording', async () => {
81
+ return await recorder.stopRecording();
82
+ });
83
+
84
+ // === REACTʼTE KULLANIM ===
85
+ // renderer.js veya React component
86
+ const { ipcRenderer } = require('electron');
87
+
88
+ class RecordingComponent {
89
+ async componentDidMount() {
90
+ // Ses cihazlarını al
91
+ this.audioDevices = await ipcRenderer.invoke('get-audio-devices');
92
+ this.setState({ audioDevices: this.audioDevices });
93
+ }
94
+
95
+ async startRecording() {
96
+ const options = {
97
+ systemAudio: this.state.enableSystemAudio, // checkbox değeri
98
+ microphone: this.state.enableMicrophone, // checkbox değeri
99
+ systemDeviceId: this.state.selectedSystemDevice // dropdown değeri
100
+ };
101
+
102
+ const result = await ipcRenderer.invoke('start-recording', options);
103
+ if (result.success) {
104
+ this.setState({ recording: true });
105
+ }
106
+ }
107
+
108
+ async stopRecording() {
109
+ await ipcRenderer.invoke('stop-recording');
110
+ this.setState({ recording: false });
111
+ }
112
+
113
+ render() {
114
+ return (
115
+ <div>
116
+ <label>
117
+ <input
118
+ type="checkbox"
119
+ checked={this.state.enableSystemAudio}
120
+ onChange={e => this.setState({enableSystemAudio: e.target.checked})}
121
+ />
122
+ Sistem Sesini Kaydet
123
+ </label>
124
+
125
+ <select onChange={e => this.setState({selectedSystemDevice: e.target.value})}>
126
+ {this.state.audioDevices?.map(device => (
127
+ <option key={device.id} value={device.id}>
128
+ {device.name}
129
+ </option>
130
+ ))}
131
+ </select>
132
+
133
+ <button onClick={() => this.startRecording()}>
134
+ Kayıt Başlat
135
+ </button>
136
+ </div>
137
+ );
138
+ }
139
+ }
140
+
141
+ // === EXPRESS API ===
142
+ const express = require('express');
143
+ const MacRecorder = require('node-mac-recorder');
144
+
145
+ const app = express();
146
+ const recorder = new MacRecorder();
147
+
148
+ app.use(express.json());
149
+
150
+ // Ses cihazlarını listele
151
+ app.get('/api/audio-devices', async (req, res) => {
152
+ const devices = await recorder.getAudioDevices();
153
+ res.json(devices);
154
+ });
155
+
156
+ // Kayıt başlat
157
+ app.post('/api/start-recording', async (req, res) => {
158
+ const { systemAudio, microphone, systemDeviceId } = req.body;
159
+
160
+ try {
161
+ await recorder.startRecording('./api-recording.mov', {
162
+ includeSystemAudio: systemAudio, // true/false
163
+ includeMicrophone: microphone, // true/false
164
+ systemAudioDeviceId: systemDeviceId || null
165
+ });
166
+
167
+ res.json({ success: true, message: 'Recording started' });
168
+ } catch (error) {
169
+ res.status(500).json({ success: false, error: error.message });
170
+ }
171
+ });
172
+
173
+ // Kayıt durdur
174
+ app.post('/api/stop-recording', async (req, res) => {
175
+ const result = await recorder.stopRecording();
176
+ res.json(result);
177
+ });
178
+
179
+ // Test et
180
+ if (require.main === module) {
181
+ myAppRecording().catch(console.error);
182
+ }
@@ -71,6 +71,7 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
71
71
  bool includeSystemAudio = true; // Default olarak sistem sesi açık
72
72
  CGDirectDisplayID displayID = CGMainDisplayID(); // Default ana ekran
73
73
  NSString *audioDeviceId = nil; // Default audio device ID
74
+ NSString *systemAudioDeviceId = nil; // System audio device ID
74
75
 
75
76
  if (info.Length() > 1 && info[1].IsObject()) {
76
77
  Napi::Object options = info[1].As<Napi::Object>();
@@ -109,6 +110,12 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
109
110
  includeSystemAudio = options.Get("includeSystemAudio").As<Napi::Boolean>();
110
111
  }
111
112
 
113
+ // System audio device ID
114
+ if (options.Has("systemAudioDeviceId") && !options.Get("systemAudioDeviceId").IsNull()) {
115
+ std::string sysDeviceId = options.Get("systemAudioDeviceId").As<Napi::String>().Utf8Value();
116
+ systemAudioDeviceId = [NSString stringWithUTF8String:sysDeviceId.c_str()];
117
+ }
118
+
112
119
  // Display ID
113
120
  if (options.Has("displayId") && !options.Get("displayId").IsNull()) {
114
121
  double displayIdNum = options.Get("displayId").As<Napi::Number>().DoubleValue();
@@ -214,11 +221,71 @@ Napi::Value StartRecording(const Napi::CallbackInfo& info) {
214
221
  }
215
222
  }
216
223
 
217
- // System audio için AVCaptureScreenInput zaten sistem sesini yakalar
218
- // includeSystemAudio parametresi screen input'un ses yakalama özelliğini kontrol eder
224
+ // System audio configuration
219
225
  if (includeSystemAudio) {
226
+ // Enable audio capture in screen input
220
227
  g_screenInput.capturesMouseClicks = YES;
221
- // AVCaptureScreenInput otomatik olarak sistem sesini yakalar
228
+
229
+ // Try to add system audio input using Core Audio
230
+ // This approach captures system audio by creating a virtual audio device
231
+ if (@available(macOS 10.15, *)) {
232
+ // Configure screen input for better audio capture
233
+ g_screenInput.capturesCursor = captureCursor;
234
+ g_screenInput.capturesMouseClicks = YES;
235
+
236
+ // Try to find and add system audio device (like Soundflower, BlackHole, etc.)
237
+ NSArray *audioDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
238
+ AVCaptureDevice *systemAudioDevice = nil;
239
+
240
+ // If specific system audio device ID is provided, try to find it first
241
+ if (systemAudioDeviceId) {
242
+ for (AVCaptureDevice *device in audioDevices) {
243
+ if ([device.uniqueID isEqualToString:systemAudioDeviceId]) {
244
+ systemAudioDevice = device;
245
+ NSLog(@"[DEBUG] Found specified system audio device: %@ (ID: %@)", device.localizedName, device.uniqueID);
246
+ break;
247
+ }
248
+ }
249
+ }
250
+
251
+ // If no specific device found or specified, look for known system audio devices
252
+ if (!systemAudioDevice) {
253
+ for (AVCaptureDevice *device in audioDevices) {
254
+ NSString *deviceName = [device.localizedName lowercaseString];
255
+ // Check for common system audio capture devices
256
+ if ([deviceName containsString:@"soundflower"] ||
257
+ [deviceName containsString:@"blackhole"] ||
258
+ [deviceName containsString:@"loopback"] ||
259
+ [deviceName containsString:@"system audio"] ||
260
+ [deviceName containsString:@"aggregate"]) {
261
+ systemAudioDevice = device;
262
+ NSLog(@"[DEBUG] Auto-detected system audio device: %@", device.localizedName);
263
+ break;
264
+ }
265
+ }
266
+ }
267
+
268
+ // If we found a system audio device, add it as an additional input
269
+ if (systemAudioDevice && !includeMicrophone) {
270
+ // Only add system audio device if microphone is not already added
271
+ NSError *error;
272
+ AVCaptureDeviceInput *systemAudioInput = [[AVCaptureDeviceInput alloc] initWithDevice:systemAudioDevice error:&error];
273
+ if (systemAudioInput && [g_captureSession canAddInput:systemAudioInput]) {
274
+ [g_captureSession addInput:systemAudioInput];
275
+ NSLog(@"[DEBUG] Successfully added system audio device: %@", systemAudioDevice.localizedName);
276
+ } else if (error) {
277
+ NSLog(@"[DEBUG] Failed to add system audio device: %@", error.localizedDescription);
278
+ }
279
+ } else if (includeSystemAudio && !systemAudioDevice) {
280
+ NSLog(@"[DEBUG] System audio requested but no suitable device found. Available devices:");
281
+ for (AVCaptureDevice *device in audioDevices) {
282
+ NSLog(@"[DEBUG] - %@ (ID: %@)", device.localizedName, device.uniqueID);
283
+ }
284
+ }
285
+ }
286
+ } else {
287
+ // Explicitly disable audio capture if not requested
288
+ g_screenInput.capturesMouseClicks = NO;
222
289
  }
223
290
 
224
291
  // Create movie file output
@@ -0,0 +1,15 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <ScreenCaptureKit/ScreenCaptureKit.h>
3
+ #import <AVFoundation/AVFoundation.h>
4
+
5
+ API_AVAILABLE(macos(12.3))
6
+ @interface ScreenCaptureKitRecorder : NSObject
7
+
8
+ + (BOOL)isScreenCaptureKitAvailable;
9
+ + (BOOL)startRecordingWithConfiguration:(NSDictionary *)config
10
+ delegate:(id)delegate
11
+ error:(NSError **)error;
12
+ + (void)stopRecording;
13
+ + (BOOL)isRecording;
14
+
15
+ @end
@@ -0,0 +1,46 @@
1
+ const MacRecorder = require('./index');
2
+
3
+ async function testWithSystemSound() {
4
+ const recorder = new MacRecorder();
5
+
6
+ console.log('🎵 SİSTEM SESİ TEST EDİLİYOR\n');
7
+ console.log('📋 ÖNEMLİ: Bu testi yapmadan önce:');
8
+ console.log('1. System Preferences > Sound > Output');
9
+ console.log('2. "iMobie Speaker" veya "iMobie Aggregate Device" seç');
10
+ console.log('3. Müzik çalabildiğini kontrol et');
11
+ console.log('');
12
+ console.log('⏳ 5 saniye bekleniyor, hazırlık yap...');
13
+
14
+ await new Promise(resolve => setTimeout(resolve, 5000));
15
+
16
+ try {
17
+ console.log('🔴 KAYIT BAŞLIYOR (3 saniye)...');
18
+ console.log('🎵 ŞİMDİ MÜZİK ÇAL veya YouTube video aç!');
19
+
20
+ await recorder.startRecording('./test-output/system-sound-test.mov', {
21
+ includeSystemAudio: true,
22
+ includeMicrophone: false,
23
+ systemAudioDeviceId: 'iMobie_AggregateDevice_UID', // Direkt ID kullan
24
+ captureArea: { x: 0, y: 0, width: 400, height: 300 }
25
+ });
26
+
27
+ // 3 saniye kayıt
28
+ await new Promise(resolve => setTimeout(resolve, 3000));
29
+
30
+ await recorder.stopRecording();
31
+ console.log('✅ KAYIT TAMAMLANDI!');
32
+ console.log('📁 Dosya: ./test-output/system-sound-test.mov');
33
+
34
+ // Dosyayı aç
35
+ console.log('🔍 Dosya açılıyor...');
36
+ require('child_process').exec('open ./test-output/system-sound-test.mov');
37
+
38
+ console.log('\n✅ Eğer ses duyuyorsan: SİSTEM SESİ ÇALIŞIYOR! 🎉');
39
+ console.log('❌ Eğer ses yoksa: Sistem ses output\'unu iMobie cihazına ayarla');
40
+
41
+ } catch (error) {
42
+ console.error('❌ Test hatası:', error.message);
43
+ }
44
+ }
45
+
46
+ testWithSystemSound();
@@ -0,0 +1,104 @@
1
+ const MacRecorder = require('./index');
2
+ const path = require('path');
3
+
4
+ async function testSystemAudio() {
5
+ const recorder = new MacRecorder();
6
+
7
+ console.log('🎵 Sistem Sesi Yakalama Testi Başlıyor...\n');
8
+
9
+ try {
10
+ // Önce izinleri kontrol et
11
+ const permissions = await recorder.checkPermissions();
12
+ console.log('📋 İzinler:', permissions);
13
+
14
+ if (!permissions.screenRecording) {
15
+ console.log('❌ Ekran kayıt izni gerekli. System Preferences > Security & Privacy > Screen Recording');
16
+ return;
17
+ }
18
+
19
+ // Mevcut ses cihazlarını listele
20
+ console.log('\n🎤 Mevcut Ses Cihazları:');
21
+ const audioDevices = await recorder.getAudioDevices();
22
+ audioDevices.forEach((device, index) => {
23
+ console.log(`${index + 1}. ${device.name}`);
24
+ if (device.id) console.log(` ID: ${device.id}`);
25
+ });
26
+
27
+ // Sistem sesi cihazı ara
28
+ const systemAudioDevice = audioDevices.find(device =>
29
+ device.name.toLowerCase().includes('blackhole') ||
30
+ device.name.toLowerCase().includes('soundflower') ||
31
+ device.name.toLowerCase().includes('loopback') ||
32
+ device.name.toLowerCase().includes('aggregate') ||
33
+ device.name.toLowerCase().includes('imobie')
34
+ );
35
+
36
+ console.log('\n=== Test 1: Sistem Sesi KAPALI ===');
37
+ const outputPath1 = path.join(__dirname, 'test-output', 'no-system-audio.mov');
38
+
39
+ await recorder.startRecording(outputPath1, {
40
+ includeSystemAudio: false, // Sistem sesi kapalı
41
+ includeMicrophone: false,
42
+ captureCursor: true,
43
+ captureArea: { x: 0, y: 0, width: 400, height: 300 } // Küçük alan
44
+ });
45
+
46
+ console.log('🔴 5 saniye kayıt yapılıyor (sistem sesi KAPALI)...');
47
+ console.log('💡 Şimdi müzik çal veya YouTube video aç - ses KAYIT EDİLMEMELİ');
48
+
49
+ await new Promise(resolve => setTimeout(resolve, 5000));
50
+ await recorder.stopRecording();
51
+ console.log(`✅ Kayıt tamamlandı: ${outputPath1}`);
52
+
53
+ // 2 saniye bekle
54
+ await new Promise(resolve => setTimeout(resolve, 2000));
55
+
56
+ console.log('\n=== Test 2: Sistem Sesi AÇIK ===');
57
+ const outputPath2 = path.join(__dirname, 'test-output', 'with-system-audio.mov');
58
+
59
+ const options2 = {
60
+ includeSystemAudio: true, // Sistem sesi açık
61
+ includeMicrophone: false,
62
+ captureCursor: true,
63
+ captureArea: { x: 0, y: 0, width: 400, height: 300 }
64
+ };
65
+
66
+ // Eğer sistem sesi cihazı varsa onu kullan
67
+ if (systemAudioDevice) {
68
+ options2.systemAudioDeviceId = systemAudioDevice.id;
69
+ console.log(`🎯 Kullanılan sistem sesi cihazı: ${systemAudioDevice.name}`);
70
+ }
71
+
72
+ await recorder.startRecording(outputPath2, options2);
73
+
74
+ console.log('🔴 5 saniye kayıt yapılıyor (sistem sesi AÇIK)...');
75
+ console.log('🎵 Şimdi müzik çal veya YouTube video aç - ses KAYIT EDİLMELİ');
76
+
77
+ await new Promise(resolve => setTimeout(resolve, 5000));
78
+ await recorder.stopRecording();
79
+ console.log(`✅ Kayıt tamamlandı: ${outputPath2}`);
80
+
81
+ console.log('\n=== 🎉 TEST TAMAMLANDI ===');
82
+ console.log('📁 Kayıtları karşılaştır:');
83
+ console.log(`1. ${outputPath1} (sistem sesi YOK)`);
84
+ console.log(`2. ${outputPath2} (sistem sesi VAR)`);
85
+
86
+ if (!systemAudioDevice) {
87
+ console.log('\n⚠️ Sistem sesi cihazı bulunamadı!');
88
+ console.log('💡 Daha iyi sistem sesi yakalama için şunları yükle:');
89
+ console.log(' • BlackHole: https://github.com/ExistentialAudio/BlackHole');
90
+ console.log(' • Soundflower: https://github.com/mattingalls/Soundflower');
91
+ }
92
+
93
+ console.log('\n🔍 Kayıtları test etmek için:');
94
+ console.log('1. Dosyaları QuickTime Player ile aç');
95
+ console.log('2. İlk kayıtta ses olmamalı');
96
+ console.log('3. İkinci kayıtta sistem sesi olmalı');
97
+
98
+ } catch (error) {
99
+ console.error('❌ Test hatası:', error.message);
100
+ }
101
+ }
102
+
103
+ // Testi çalıştır
104
+ testSystemAudio();
@@ -0,0 +1,202 @@
1
+ const MacRecorder = require('./index');
2
+
3
+ // ===== PARAMETRIK KULLANIM ÖRNEKLERİ =====
4
+
5
+ async function examples() {
6
+ const recorder = new MacRecorder();
7
+
8
+ console.log('🎯 PARAMETRİK SİSTEM SESİ KULLANIMI\n');
9
+
10
+ // 1. SİSTEM SESİ AÇIK (default)
11
+ console.log('1️⃣ Sistem sesi AÇIK (default):');
12
+ await recorder.startRecording('./output1.mov', {
13
+ includeSystemAudio: true, // Default zaten true
14
+ includeMicrophone: false
15
+ });
16
+ // ... kayıt yap ve durdur
17
+
18
+ // 2. SİSTEM SESİ KAPALI
19
+ console.log('2️⃣ Sistem sesi KAPALI:');
20
+ await recorder.startRecording('./output2.mov', {
21
+ includeSystemAudio: false, // Açıkça kapat
22
+ includeMicrophone: true // Sadece mikrofon
23
+ });
24
+
25
+ // 3. BELİRLİ SES CİHAZI İLE
26
+ console.log('3️⃣ Belirli sistem ses cihazı:');
27
+
28
+ // Önce cihazları listele
29
+ const devices = await recorder.getAudioDevices();
30
+ const systemDevice = devices.find(d =>
31
+ d.name.includes('iMobie') ||
32
+ d.name.includes('BlackHole') ||
33
+ d.name.includes('Aggregate')
34
+ );
35
+
36
+ if (systemDevice) {
37
+ await recorder.startRecording('./output3.mov', {
38
+ includeSystemAudio: true,
39
+ systemAudioDeviceId: systemDevice.id, // Belirli cihaz
40
+ includeMicrophone: false
41
+ });
42
+ }
43
+
44
+ // 4. HER İKİSİ BİRDEN
45
+ console.log('4️⃣ Sistem sesi + Mikrofon:');
46
+ await recorder.startRecording('./output4.mov', {
47
+ includeSystemAudio: true, // Sistem sesi
48
+ includeMicrophone: true, // Mikrofon
49
+ audioDeviceId: 'BuiltInMicrophoneDevice', // Mikrofon cihazı
50
+ systemAudioDeviceId: systemDevice?.id // Sistem ses cihazı
51
+ });
52
+
53
+ console.log('✅ Tüm örnekler hazır!');
54
+ }
55
+
56
+ // BAŞKA UYGULAMADA KULLANIM
57
+ async function usageInYourApp() {
58
+ const recorder = new MacRecorder();
59
+
60
+ // ===== SENİN UYGULAMANLA ENTEGRASYON =====
61
+
62
+ // Kullanıcı ayarları
63
+ const userSettings = {
64
+ captureSystemAudio: true, // Kullanıcının seçimi
65
+ captureMicrophone: false, // Kullanıcının seçimi
66
+ preferredSystemAudioDevice: null // Kullanıcının seçtiği cihaz
67
+ };
68
+
69
+ // Cihazları al ve kullanıcıya göster
70
+ const audioDevices = await recorder.getAudioDevices();
71
+ const systemAudioDevices = audioDevices.filter(device =>
72
+ device.name.toLowerCase().includes('aggregate') ||
73
+ device.name.toLowerCase().includes('blackhole') ||
74
+ device.name.toLowerCase().includes('soundflower') ||
75
+ device.name.toLowerCase().includes('imobie')
76
+ );
77
+
78
+ console.log('🎤 Sistem ses cihazları:');
79
+ systemAudioDevices.forEach((device, i) => {
80
+ console.log(`${i + 1}. ${device.name}`);
81
+ });
82
+
83
+ // Kayıt başlat
84
+ const recordingOptions = {
85
+ includeSystemAudio: userSettings.captureSystemAudio,
86
+ includeMicrophone: userSettings.captureMicrophone,
87
+ };
88
+
89
+ // Eğer kullanıcı belirli cihaz seçtiyse
90
+ if (userSettings.preferredSystemAudioDevice) {
91
+ recordingOptions.systemAudioDeviceId = userSettings.preferredSystemAudioDevice;
92
+ }
93
+
94
+ // Kayıt başlat
95
+ await recorder.startRecording('./user-recording.mov', recordingOptions);
96
+
97
+ console.log('🔴 Kayıt başladı...');
98
+
99
+ // Gerektiğinde durdur
100
+ setTimeout(async () => {
101
+ await recorder.stopRecording();
102
+ console.log('✅ Kayıt bitti!');
103
+ }, 5000);
104
+ }
105
+
106
+ // ===== REACT/ELECTRON ÖRNEĞİ =====
107
+ class AudioRecorderService {
108
+ constructor() {
109
+ this.recorder = new MacRecorder();
110
+ this.isRecording = false;
111
+ }
112
+
113
+ async getAvailableSystemAudioDevices() {
114
+ const devices = await this.recorder.getAudioDevices();
115
+ return devices.filter(device =>
116
+ device.name.toLowerCase().includes('aggregate') ||
117
+ device.name.toLowerCase().includes('blackhole') ||
118
+ device.name.toLowerCase().includes('imobie')
119
+ );
120
+ }
121
+
122
+ async startRecording(options = {}) {
123
+ const {
124
+ outputPath,
125
+ includeSystemAudio = true, // Default açık
126
+ includeMicrophone = false,
127
+ systemAudioDeviceId = null,
128
+ audioDeviceId = null,
129
+ windowId = null,
130
+ displayId = null
131
+ } = options;
132
+
133
+ if (this.isRecording) {
134
+ throw new Error('Already recording');
135
+ }
136
+
137
+ const recordingConfig = {
138
+ includeSystemAudio,
139
+ includeMicrophone,
140
+ systemAudioDeviceId,
141
+ audioDeviceId,
142
+ windowId,
143
+ displayId
144
+ };
145
+
146
+ await this.recorder.startRecording(outputPath, recordingConfig);
147
+ this.isRecording = true;
148
+
149
+ return { success: true, config: recordingConfig };
150
+ }
151
+
152
+ async stopRecording() {
153
+ if (!this.isRecording) {
154
+ throw new Error('Not recording');
155
+ }
156
+
157
+ const result = await this.recorder.stopRecording();
158
+ this.isRecording = false;
159
+
160
+ return result;
161
+ }
162
+
163
+ getRecordingStatus() {
164
+ return {
165
+ isRecording: this.isRecording,
166
+ ...this.recorder.getStatus()
167
+ };
168
+ }
169
+ }
170
+
171
+ // KULLANIM ÖRNEĞİ
172
+ async function exampleUsage() {
173
+ const service = new AudioRecorderService();
174
+
175
+ // Sistem ses cihazlarını listele
176
+ const systemDevices = await service.getAvailableSystemAudioDevices();
177
+ console.log('Mevcut sistem ses cihazları:', systemDevices);
178
+
179
+ // Kayıt başlat - sistem sesi açık
180
+ await service.startRecording({
181
+ outputPath: './my-app-recording.mov',
182
+ includeSystemAudio: true, // ✅ Sistem sesi
183
+ includeMicrophone: false, // ❌ Mikrofon
184
+ systemAudioDeviceId: systemDevices[0]?.id // İlk cihazı kullan
185
+ });
186
+
187
+ console.log('Recording started with system audio!');
188
+
189
+ // 10 saniye sonra durdur
190
+ setTimeout(async () => {
191
+ await service.stopRecording();
192
+ console.log('Recording finished!');
193
+ }, 10000);
194
+ }
195
+
196
+ // Test et
197
+ if (require.main === module) {
198
+ console.log('🚀 Parametrik sistem sesi test ediliyor...\n');
199
+ exampleUsage().catch(console.error);
200
+ }
201
+
202
+ module.exports = { AudioRecorderService };