node-mac-recorder 2.21.11 → 2.21.13
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 +1 -13
- package/package.json +1 -1
- package/src/audio_recorder.mm +18 -5
- package/src/camera_recorder.mm +16 -12
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
|
-
"Bash(
|
|
5
|
-
"Bash(node:*)",
|
|
6
|
-
"Bash(timeout:*)",
|
|
7
|
-
"Bash(open:*)",
|
|
8
|
-
"Read(//Users/onur/codes/**)",
|
|
9
|
-
"Bash(log show:*)",
|
|
10
|
-
"Bash(MAC_RECORDER_DEBUG=1 node:*)",
|
|
11
|
-
"Read(//private/tmp/test-recording/**)",
|
|
12
|
-
"Bash(MAC_RECORDER_DEBUG=1 timeout 5 node:*)",
|
|
13
|
-
"Read(//private/tmp/**)",
|
|
14
|
-
"Bash(ffprobe:*)",
|
|
15
|
-
"Bash(MAC_RECORDER_DEBUG=1 timeout 8 node:*)",
|
|
16
|
-
"Bash(cat:*)"
|
|
4
|
+
"Bash(ffmpeg:*)"
|
|
17
5
|
],
|
|
18
6
|
"deny": [],
|
|
19
7
|
"ask": []
|
package/package.json
CHANGED
package/src/audio_recorder.mm
CHANGED
|
@@ -103,11 +103,13 @@ static dispatch_queue_t g_audioCaptureQueue = nil;
|
|
|
103
103
|
|
|
104
104
|
CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
|
|
105
105
|
const AudioStreamBasicDescription *asbd = formatDescription ? CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription) : NULL;
|
|
106
|
-
|
|
107
|
-
double sampleRate = asbd ? asbd->mSampleRate :
|
|
108
|
-
NSUInteger channels = asbd ? asbd->mChannelsPerFrame :
|
|
106
|
+
|
|
107
|
+
double sampleRate = asbd ? asbd->mSampleRate : 48000.0; // Default to 48kHz (not 44.1kHz)
|
|
108
|
+
NSUInteger channels = asbd ? asbd->mChannelsPerFrame : 1; // Default to mono
|
|
109
109
|
channels = MAX((NSUInteger)1, channels);
|
|
110
110
|
|
|
111
|
+
MRLog(@"🎤 Audio format: %.0f Hz, %lu channel(s)", sampleRate, (unsigned long)channels);
|
|
112
|
+
|
|
111
113
|
AudioChannelLayout layout = {0};
|
|
112
114
|
size_t layoutSize = 0;
|
|
113
115
|
if (channels == 1) {
|
|
@@ -122,7 +124,8 @@ static dispatch_queue_t g_audioCaptureQueue = nil;
|
|
|
122
124
|
AVFormatIDKey: @(kAudioFormatMPEG4AAC),
|
|
123
125
|
AVSampleRateKey: @(sampleRate),
|
|
124
126
|
AVNumberOfChannelsKey: @(channels),
|
|
125
|
-
AVEncoderBitRateKey: @(
|
|
127
|
+
AVEncoderBitRateKey: @(256000), // Increased from 192k to 256k for better quality
|
|
128
|
+
AVEncoderAudioQualityKey: @(AVAudioQualityHigh)
|
|
126
129
|
} mutableCopy];
|
|
127
130
|
|
|
128
131
|
if (layoutSize > 0) {
|
|
@@ -191,7 +194,17 @@ static dispatch_queue_t g_audioCaptureQueue = nil;
|
|
|
191
194
|
}
|
|
192
195
|
return NO;
|
|
193
196
|
}
|
|
194
|
-
|
|
197
|
+
|
|
198
|
+
// Configure audio output settings to ensure proper PCM format
|
|
199
|
+
NSDictionary *audioOutputSettings = @{
|
|
200
|
+
AVFormatIDKey: @(kAudioFormatLinearPCM),
|
|
201
|
+
AVLinearPCMBitDepthKey: @(16),
|
|
202
|
+
AVLinearPCMIsFloatKey: @(NO),
|
|
203
|
+
AVLinearPCMIsBigEndianKey: @(NO),
|
|
204
|
+
AVLinearPCMIsNonInterleaved: @(NO)
|
|
205
|
+
};
|
|
206
|
+
[self.audioOutput setAudioSettings:audioOutputSettings];
|
|
207
|
+
|
|
195
208
|
if (!g_audioCaptureQueue) {
|
|
196
209
|
g_audioCaptureQueue = dispatch_queue_create("native_audio_recorder.queue", DISPATCH_QUEUE_SERIAL);
|
|
197
210
|
}
|
package/src/camera_recorder.mm
CHANGED
|
@@ -9,6 +9,12 @@ static AVVideoCodecType const AVVideoCodecTypeVP9 = @"vp09";
|
|
|
9
9
|
#endif
|
|
10
10
|
|
|
11
11
|
static BOOL MRAllowContinuityCamera() {
|
|
12
|
+
// Check environment variable first (allows runtime override)
|
|
13
|
+
if (getenv("ALLOW_CONTINUITY_CAMERA")) {
|
|
14
|
+
return YES;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Check Info.plist
|
|
12
18
|
static dispatch_once_t onceToken;
|
|
13
19
|
static BOOL allowContinuity = NO;
|
|
14
20
|
dispatch_once(&onceToken, ^{
|
|
@@ -16,9 +22,6 @@ static BOOL MRAllowContinuityCamera() {
|
|
|
16
22
|
if ([continuityKey respondsToSelector:@selector(boolValue)] && [continuityKey boolValue]) {
|
|
17
23
|
allowContinuity = YES;
|
|
18
24
|
}
|
|
19
|
-
if (!allowContinuity && getenv("ALLOW_CONTINUITY_CAMERA")) {
|
|
20
|
-
allowContinuity = YES;
|
|
21
|
-
}
|
|
22
25
|
});
|
|
23
26
|
return allowContinuity;
|
|
24
27
|
}
|
|
@@ -127,9 +130,12 @@ static BOOL MRIsContinuityCamera(AVCaptureDevice *device) {
|
|
|
127
130
|
[deviceTypes addObject:AVCaptureDeviceTypeExternalUnknown];
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
// Add Continuity Camera ONLY if permission is available (to avoid system warning)
|
|
134
|
+
// But we still want to show external devices that happen to be Continuity cameras
|
|
135
|
+
if (allowContinuity) {
|
|
136
|
+
if (@available(macOS 14.0, *)) {
|
|
137
|
+
[deviceTypes addObject:AVCaptureDeviceTypeContinuityCamera];
|
|
138
|
+
}
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
AVCaptureDeviceDiscoverySession *discoverySession =
|
|
@@ -139,12 +145,10 @@ static BOOL MRIsContinuityCamera(AVCaptureDevice *device) {
|
|
|
139
145
|
|
|
140
146
|
for (AVCaptureDevice *device in discoverySession.devices) {
|
|
141
147
|
BOOL continuityCamera = MRIsContinuityCamera(device);
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
+
|
|
149
|
+
// NOTE: We list ALL cameras including Continuity Camera
|
|
150
|
+
// The permission check happens at RECORDING time, not listing time
|
|
151
|
+
// This allows users to see the device even if permission is missing
|
|
148
152
|
|
|
149
153
|
// Determine the best (maximum) resolution format for this device
|
|
150
154
|
CMVideoDimensions bestDimensions = {0, 0};
|