node-mac-recorder 1.2.10 → 1.3.0
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/.claude/settings.local.json +8 -1
- package/README.md +50 -6
- package/WINDOW_SELECTOR_README.md +396 -0
- package/binding.gyp +2 -1
- package/debug-audio.js +79 -0
- package/debug-window-selector.js +178 -0
- package/enhanced-window-selector.js +202 -0
- package/examples/integration-example.js +228 -0
- package/examples/window-selector-example.js +254 -0
- package/index.js +7 -2
- package/package.json +4 -2
- package/quick-test.js +50 -0
- package/simple-api-example.js +182 -0
- package/simple-test.js +38 -0
- package/src/mac_recorder.mm +76 -3
- package/src/screen_capture_kit.h +15 -0
- package/src/window_selector.mm +482 -0
- package/system-sound-test.js +46 -0
- package/test-system-audio.js +104 -0
- package/usage-examples.js +202 -0
- package/window-selector-test.js +160 -0
- package/window-selector.js +259 -0
- package/working-example.js +94 -0
|
@@ -6,7 +6,14 @@
|
|
|
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:*)",
|
|
14
|
+
"Bash(mkdir:*)",
|
|
15
|
+
"Bash(/dev/null)",
|
|
16
|
+
"Bash(ls:*)"
|
|
10
17
|
],
|
|
11
18
|
"deny": []
|
|
12
19
|
}
|
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
|
-
###
|
|
352
|
+
### Advanced System Audio Recording
|
|
352
353
|
|
|
353
354
|
```javascript
|
|
354
355
|
const recorder = new MacRecorder();
|
|
355
356
|
|
|
356
|
-
//
|
|
357
|
-
await recorder.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# Window Selector
|
|
2
|
+
|
|
3
|
+
**macOS Window Selection Tool with Real-time Visual Overlay**
|
|
4
|
+
|
|
5
|
+
Bu modül, macOS'ta sistem imleci ile pencere seçimi yapabilmenizi sağlayan güçlü bir araçtır. İmleç hangi pencerenin üstüne gelirse, o pencereyi mavi kapsayıcı ile highlight eder ve merkeze yerleştirilen "Select Window" butonu ile seçim yapabilirsiniz.
|
|
6
|
+
|
|
7
|
+
## ✨ Özellikler
|
|
8
|
+
|
|
9
|
+
- **Real-time Window Detection**: İmleç hangi pencereye gelirse otomatik olarak tespit eder
|
|
10
|
+
- **Visual Overlay**: Seçilebilir pencereleri mavi transparant kapsayıcı ile highlight eder
|
|
11
|
+
- **Interactive Selection**: Merkeze yerleştirilen "Select Window" butonu ile kolay seçim
|
|
12
|
+
- **Multi-display Support**: Çoklu ekran kurulumlarında çalışır
|
|
13
|
+
- **Detailed Window Info**: Pencere pozisyonu, boyutu ve hangi ekranda olduğunu döndürür
|
|
14
|
+
- **Event-driven API**: Pencere hover, seçim ve hata durumları için event'ler
|
|
15
|
+
- **Permission Management**: macOS izin kontrolü ve yönetimi
|
|
16
|
+
|
|
17
|
+
## 🚀 Kurulum
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Ana proje dizininde
|
|
21
|
+
npm install
|
|
22
|
+
|
|
23
|
+
# Native modülü build edin
|
|
24
|
+
npm run build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 📋 Sistem Gereksinimleri
|
|
28
|
+
|
|
29
|
+
- **macOS 10.15+** (Catalina veya üzeri)
|
|
30
|
+
- **Node.js 14+**
|
|
31
|
+
- **Xcode Command Line Tools**
|
|
32
|
+
- **System Permissions**:
|
|
33
|
+
- Screen Recording permission
|
|
34
|
+
- Accessibility permission
|
|
35
|
+
|
|
36
|
+
## 🔐 İzinler
|
|
37
|
+
|
|
38
|
+
İlk kullanımda macOS aşağıdaki izinleri isteyecektir:
|
|
39
|
+
|
|
40
|
+
1. **System Preferences > Security & Privacy > Privacy > Screen Recording**
|
|
41
|
+
- Terminal veya kullandığınız IDE'yi (VSCode, WebStorm, vb.) etkinleştirin
|
|
42
|
+
|
|
43
|
+
2. **System Preferences > Security & Privacy > Privacy > Accessibility**
|
|
44
|
+
- Terminal veya kullandığınız IDE'yi etkinleştirin
|
|
45
|
+
|
|
46
|
+
## 🎯 Temel Kullanım
|
|
47
|
+
|
|
48
|
+
### Basit Pencere Seçimi
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
const WindowSelector = require('./window-selector');
|
|
52
|
+
|
|
53
|
+
async function selectWindow() {
|
|
54
|
+
const selector = new WindowSelector();
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
console.log('Bir pencere seçin...');
|
|
58
|
+
const selectedWindow = await selector.selectWindow();
|
|
59
|
+
|
|
60
|
+
console.log('Seçilen pencere:', {
|
|
61
|
+
title: selectedWindow.title,
|
|
62
|
+
app: selectedWindow.appName,
|
|
63
|
+
position: `(${selectedWindow.x}, ${selectedWindow.y})`,
|
|
64
|
+
size: `${selectedWindow.width}x${selectedWindow.height}`,
|
|
65
|
+
screen: selectedWindow.screenId
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return selectedWindow;
|
|
69
|
+
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Hata:', error.message);
|
|
72
|
+
} finally {
|
|
73
|
+
await selector.cleanup();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
selectWindow();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Manuel Kontrol
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const WindowSelector = require('./window-selector');
|
|
84
|
+
|
|
85
|
+
async function manualSelection() {
|
|
86
|
+
const selector = new WindowSelector();
|
|
87
|
+
|
|
88
|
+
// Event listener'lar
|
|
89
|
+
selector.on('windowEntered', (window) => {
|
|
90
|
+
console.log(`Pencere üstünde: ${window.title} (${window.appName})`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
selector.on('windowSelected', (window) => {
|
|
94
|
+
console.log(`Seçildi: ${window.title}`);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Seçimi başlat
|
|
98
|
+
await selector.startSelection();
|
|
99
|
+
|
|
100
|
+
// Kullanıcı seçim yapana kadar bekle
|
|
101
|
+
// Seçim tamamlandığında 'windowSelected' event'i tetiklenir
|
|
102
|
+
|
|
103
|
+
// Seçimi durdurmak için:
|
|
104
|
+
// await selector.stopSelection();
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 📚 API Reference
|
|
109
|
+
|
|
110
|
+
### WindowSelector Class
|
|
111
|
+
|
|
112
|
+
#### Constructor
|
|
113
|
+
```javascript
|
|
114
|
+
const selector = new WindowSelector();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Methods
|
|
118
|
+
|
|
119
|
+
##### `async selectWindow()`
|
|
120
|
+
Promise tabanlı pencere seçimi. Kullanıcı bir pencere seçene kadar bekler.
|
|
121
|
+
|
|
122
|
+
**Returns:** `Promise<WindowInfo>`
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const window = await selector.selectWindow();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
##### `async startSelection()`
|
|
129
|
+
Pencere seçim modunu başlatır.
|
|
130
|
+
|
|
131
|
+
**Returns:** `Promise<boolean>`
|
|
132
|
+
|
|
133
|
+
##### `async stopSelection()`
|
|
134
|
+
Pencere seçim modunu durdurur.
|
|
135
|
+
|
|
136
|
+
**Returns:** `Promise<boolean>`
|
|
137
|
+
|
|
138
|
+
##### `getSelectedWindow()`
|
|
139
|
+
Son seçilen pencere bilgisini döndürür.
|
|
140
|
+
|
|
141
|
+
**Returns:** `WindowInfo | null`
|
|
142
|
+
|
|
143
|
+
##### `getStatus()`
|
|
144
|
+
Seçici durumunu döndürür.
|
|
145
|
+
|
|
146
|
+
**Returns:** `SelectionStatus`
|
|
147
|
+
|
|
148
|
+
##### `async checkPermissions()`
|
|
149
|
+
macOS izinlerini kontrol eder.
|
|
150
|
+
|
|
151
|
+
**Returns:** `Promise<PermissionStatus>`
|
|
152
|
+
|
|
153
|
+
##### `async cleanup()`
|
|
154
|
+
Tüm kaynakları temizler ve seçimi durdurur.
|
|
155
|
+
|
|
156
|
+
#### Events
|
|
157
|
+
|
|
158
|
+
##### `selectionStarted`
|
|
159
|
+
Seçim modu başladığında tetiklenir.
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
selector.on('selectionStarted', () => {
|
|
163
|
+
console.log('Seçim başladı');
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
##### `windowEntered`
|
|
168
|
+
İmleç bir pencereye geldiğinde tetiklenir.
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
selector.on('windowEntered', (windowInfo) => {
|
|
172
|
+
console.log(`Pencere: ${windowInfo.title}`);
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
##### `windowLeft`
|
|
177
|
+
İmleç bir pencereden ayrıldığında tetiklenir.
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
selector.on('windowLeft', (windowInfo) => {
|
|
181
|
+
console.log(`Ayrıldı: ${windowInfo.title}`);
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
##### `windowSelected`
|
|
186
|
+
Bir pencere seçildiğinde tetiklenir.
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
selector.on('windowSelected', (windowInfo) => {
|
|
190
|
+
console.log('Seçilen pencere:', windowInfo);
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
##### `selectionStopped`
|
|
195
|
+
Seçim modu durduğunda tetiklenir.
|
|
196
|
+
|
|
197
|
+
##### `error`
|
|
198
|
+
Bir hata oluştuğunda tetiklenir.
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
selector.on('error', (error) => {
|
|
202
|
+
console.error('Hata:', error.message);
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 📊 Data Types
|
|
207
|
+
|
|
208
|
+
### WindowInfo
|
|
209
|
+
```javascript
|
|
210
|
+
{
|
|
211
|
+
id: number, // Pencere ID'si
|
|
212
|
+
title: string, // Pencere başlığı
|
|
213
|
+
appName: string, // Uygulama adı
|
|
214
|
+
x: number, // Global X pozisyonu
|
|
215
|
+
y: number, // Global Y pozisyonu
|
|
216
|
+
width: number, // Pencere genişliği
|
|
217
|
+
height: number, // Pencere yüksekliği
|
|
218
|
+
screenId: number, // Hangi ekranda olduğu
|
|
219
|
+
screenX: number, // Ekranın X pozisyonu
|
|
220
|
+
screenY: number, // Ekranın Y pozisyonu
|
|
221
|
+
screenWidth: number, // Ekran genişliği
|
|
222
|
+
screenHeight: number // Ekran yüksekliği
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### SelectionStatus
|
|
227
|
+
```javascript
|
|
228
|
+
{
|
|
229
|
+
isSelecting: boolean, // Seçim modunda mı?
|
|
230
|
+
hasSelectedWindow: boolean, // Seçilmiş pencere var mı?
|
|
231
|
+
selectedWindow: WindowInfo | null,
|
|
232
|
+
nativeStatus: object // Native durum bilgisi
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### PermissionStatus
|
|
237
|
+
```javascript
|
|
238
|
+
{
|
|
239
|
+
screenRecording: boolean, // Ekran kaydı izni
|
|
240
|
+
accessibility: boolean, // Erişilebilirlik izni
|
|
241
|
+
microphone: boolean // Mikrofon izni
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 🎮 Test Etme
|
|
246
|
+
|
|
247
|
+
### Test Dosyasını Çalıştır
|
|
248
|
+
```bash
|
|
249
|
+
# Interaktif test
|
|
250
|
+
node window-selector-test.js
|
|
251
|
+
|
|
252
|
+
# API test modu
|
|
253
|
+
node window-selector-test.js --api-test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Örnekleri Çalıştır
|
|
257
|
+
```bash
|
|
258
|
+
# Basit örnek
|
|
259
|
+
node examples/window-selector-example.js
|
|
260
|
+
|
|
261
|
+
# Gelişmiş örnek (event'lerle)
|
|
262
|
+
node examples/window-selector-example.js --advanced
|
|
263
|
+
|
|
264
|
+
# Çoklu seçim
|
|
265
|
+
node examples/window-selector-example.js --multiple
|
|
266
|
+
|
|
267
|
+
# Detaylı analiz
|
|
268
|
+
node examples/window-selector-example.js --analysis
|
|
269
|
+
|
|
270
|
+
# Yardım
|
|
271
|
+
node examples/window-selector-example.js --help
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## ⚡ Nasıl Çalışır?
|
|
275
|
+
|
|
276
|
+
1. **Window Detection**: macOS `CGWindowListCopyWindowInfo` API'si ile açık pencereleri tespit eder
|
|
277
|
+
2. **Cursor Tracking**: Real-time olarak imleç pozisyonunu takip eder
|
|
278
|
+
3. **Overlay Rendering**: NSWindow ile transparant overlay penceresi oluşturur
|
|
279
|
+
4. **Hit Testing**: İmlecin hangi pencere üstünde olduğunu hesaplar
|
|
280
|
+
5. **Visual Feedback**: Pencereyi highlight eden mavi kapsayıcı çizer
|
|
281
|
+
6. **User Interaction**: Merkeze yerleştirilen button ile seçim yapar
|
|
282
|
+
7. **Data Collection**: Seçilen pencerenin tüm bilgilerini toplar
|
|
283
|
+
|
|
284
|
+
## 🔧 Troubleshooting
|
|
285
|
+
|
|
286
|
+
### Build Hataları
|
|
287
|
+
```bash
|
|
288
|
+
# Xcode Command Line Tools'u yükle
|
|
289
|
+
xcode-select --install
|
|
290
|
+
|
|
291
|
+
# Node-gyp'i yeniden build et
|
|
292
|
+
npm run clean
|
|
293
|
+
npm run build
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### İzin Hataları
|
|
297
|
+
1. **System Preferences > Security & Privacy > Privacy** bölümüne git
|
|
298
|
+
2. **Screen Recording** ve **Accessibility** sekmelerinde Terminal'i etkinleştir
|
|
299
|
+
3. Uygulamayı yeniden başlat
|
|
300
|
+
|
|
301
|
+
### Runtime Hataları
|
|
302
|
+
```javascript
|
|
303
|
+
// İzinleri kontrol et
|
|
304
|
+
const permissions = await selector.checkPermissions();
|
|
305
|
+
if (!permissions.screenRecording) {
|
|
306
|
+
console.log('Screen recording permission required');
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## 🌟 Gelişmiş Örnekler
|
|
311
|
+
|
|
312
|
+
### Otomatik Pencere Kaydı
|
|
313
|
+
```javascript
|
|
314
|
+
const WindowSelector = require('./window-selector');
|
|
315
|
+
const MacRecorder = require('./index');
|
|
316
|
+
|
|
317
|
+
async function recordSelectedWindow() {
|
|
318
|
+
const selector = new WindowSelector();
|
|
319
|
+
const recorder = new MacRecorder();
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
// Pencere seç
|
|
323
|
+
const window = await selector.selectWindow();
|
|
324
|
+
console.log(`Recording: ${window.title}`);
|
|
325
|
+
|
|
326
|
+
// Seçilen pencereyi kaydet
|
|
327
|
+
const outputPath = `./recordings/${window.appName}-${Date.now()}.mov`;
|
|
328
|
+
await recorder.startRecording(outputPath, {
|
|
329
|
+
windowId: window.id,
|
|
330
|
+
captureCursor: true,
|
|
331
|
+
includeMicrophone: true
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// 10 saniye kaydet
|
|
335
|
+
setTimeout(async () => {
|
|
336
|
+
await recorder.stopRecording();
|
|
337
|
+
console.log(`Recording saved: ${outputPath}`);
|
|
338
|
+
}, 10000);
|
|
339
|
+
|
|
340
|
+
} finally {
|
|
341
|
+
await selector.cleanup();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Pencere Monitoring
|
|
347
|
+
```javascript
|
|
348
|
+
const WindowSelector = require('./window-selector');
|
|
349
|
+
|
|
350
|
+
async function monitorWindowChanges() {
|
|
351
|
+
const selector = new WindowSelector();
|
|
352
|
+
const visitedWindows = new Set();
|
|
353
|
+
|
|
354
|
+
selector.on('windowEntered', (window) => {
|
|
355
|
+
const key = `${window.appName}-${window.title}`;
|
|
356
|
+
if (!visitedWindows.has(key)) {
|
|
357
|
+
visitedWindows.add(key);
|
|
358
|
+
console.log(`Yeni pencere keşfedildi: ${window.title} (${window.appName})`);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
await selector.startSelection();
|
|
363
|
+
|
|
364
|
+
// İptal etmek için Ctrl+C
|
|
365
|
+
process.on('SIGINT', async () => {
|
|
366
|
+
console.log(`\nToplam keşfedilen pencere: ${visitedWindows.size}`);
|
|
367
|
+
await selector.cleanup();
|
|
368
|
+
process.exit(0);
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## 📄 Lisans
|
|
374
|
+
|
|
375
|
+
Bu modül ana projenin lisansı altındadır.
|
|
376
|
+
|
|
377
|
+
## 🤝 Katkıda Bulunma
|
|
378
|
+
|
|
379
|
+
1. Fork edin
|
|
380
|
+
2. Feature branch oluşturun (`git checkout -b feature/amazing-feature`)
|
|
381
|
+
3. Commit edin (`git commit -m 'Add amazing feature'`)
|
|
382
|
+
4. Push edin (`git push origin feature/amazing-feature`)
|
|
383
|
+
5. Pull Request açın
|
|
384
|
+
|
|
385
|
+
## ⭐ Özellik İstekleri
|
|
386
|
+
|
|
387
|
+
- [ ] Pencere gruplandırma
|
|
388
|
+
- [ ] Hotkey desteği
|
|
389
|
+
- [ ] Pencere filtreleme
|
|
390
|
+
- [ ] Çoklu seçim modu
|
|
391
|
+
- [ ] Screenshot alma
|
|
392
|
+
- [ ] Window history
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
**Not**: Bu modül sadece macOS'ta çalışır ve sistem izinleri gerektirir.
|
package/binding.gyp
CHANGED
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();
|