@audio /麦克风
在浏览器中试试: 调谐器, 录音机, 房间和扬声器测量. 在此包上运行,没有上载任何内容。
捕获音频从麦克风在节点或浏览器。
使用
import mic from '@audio/mic'
let read = mic({
sampleRate: 44100,
channels: 1,
bitDepth: 16,
// bufferSize: 50, // the most one block holds, ms (default 50)
// backlog: 10000, // the most held unread, ms (default 10000)
// backend: 'miniaudio', // force backend
})
read((err, pcmBuffer) => {
// process chunk
})
read(null) // stop capture
异步iterable
import mic from '@audio/mic'
let read = mic({ sampleRate: 44100, channels: 1 })
for await (let chunk of read) {
// process PCM chunk
}
一、 break 跳出循环停止捕获。溢出(参见 read(cb))被抛出。
设备
import mic, { devices } from '@audio/mic'
await devices()
// [{ id: 'BuiltInMicrophoneDevice', name: 'MacBook Pro Microphone', default: true }, …]
let read = mic({ device: 'USB' }) // by id, by name, or by part of its name when only one holds it
id是平台自己的:CoreAudio的UID、WASAPI的端点id、ALSA或PulseAudio名称。不存在的设备是错误的(code: 'ENODEVICE'),而不是其他设备。在浏览器中, devices() 读取 enumerateDevices() (姓名显示一旦页面可以使用麦克风)和 device 就变成了 deviceId getUserMedia请求。
记录到磁盘
import { record } from '@audio/mic'
let take = record('take.wav', { device: 'Scarlett', channels: [1, 2] }) // inputs from 1, as the interface labels them
take.status() // { seconds, peaks, clips, silenced, stalled, rerouted, missed, done, error }: peaks since the last call
take.read() // Float32Array: the audio written since the last read, interleaved, to draw or hear it as it comes
await take.stop() // the same, once the file is closed
// several files from one device, one clock: tracks of one take, sample for sample together
record({ 'voice.wav': [1], 'guitar.wav': [2], 'room.wav': [3, 4] }, { device: 'Scarlett' })
// no files: every input's level, nothing written, to set levels before recording
record({}, { device: 'Scarlett' }).status().peaks
插件自己写文件,从设备填充的20秒的周期开始,所以JS中没有任何东西到达take:事件循环持续几分钟,崩溃,杀死。设备以自己的速率运行并产生浮动;没有任何东西被重新采样,除非 sampleRate 请求另一个速率,然后设备切换到它(在macOS上,就像音频MIDI设置一样)。
- 当它来的时候在磁盘上。 每隔一秒,头文件就会显示到目前为止的长度,并将文件刷新到磁盘本身(
F_FULLFSYNC在macOS上,其中fsync在驱动器的缓存处停止)。进程被终止或电源中断,WAV会一直播放到最后一秒;recover(path)剩下的就交给它了。process.exit()和一个结束的环境关闭整个。 - 没有什么会悄然失去。 环没有空间容纳的帧(一个磁盘停顿了20秒)在它们所在的位置被写为静默,因此占用时间,并被计算在内
silenced. 一个设备,停止,拔掉插头,结束与error.code === 'EDEVICELOST'写到最后一帧;没有音频的秒数为stalled;系统将其默认输入移到其他地方也算rerouted. - 从不超过一次。 文件已经存在错误(
EEXIST),除非overwrite: true;设备缺少的输入是ECHANNEL;要么在写任何东西之前。 - WAV作为每个程序读取它: PCM 16位(tpdf抖动)或24位,或32位浮点;
WAVE_FORMAT_EXTENSIBLE两个频道;超过4 GB的标头将RF64放在适当的位置(EBU Tech 3306),变成为它保留的垃圾块。
在macOS上,当系统仍然请求麦克风权限时,输入打开等待答案,并且线程打开它:一个应用程序首先请求(AVCaptureDevice.requestAccess),并在得到应答后打开一个输入。
选项: device, channels (输入,默认为前两个或一个), bitDepth (16, 24 (默认), 32), sampleRate (默认是设备自己的), ring (秒,默认为20), overwrite. 这说明 sampleRate, channels (设备的), device (其名称)和 files ([{ path, channels }])。
import { recover } from '@audio/mic'
recover('take.wav') // → { frames, before }: the frames the file holds, and those its header told
节点可读
import MicReadable from '@audio/mic/stream'
MicReadable({ sampleRate: 44100, channels: 1 }).pipe(dest)
后端
按顺序试过;谁先成功,谁就赢。
| 后端 | 如何 | 延迟 | 安装 |
|---|---|---|---|
miniaudio | N-API插件包装 miniaudio.h | 低 | 预先构建的通过 @audio/mic-* 包 |
process | 来自ffmpeg/sox/arecord的管道 | 高 | 必须安装系统工具 |
null | 沉默,保持定时合同 | - - - - - - | 内置(CI/无头回退) |
mediastream | getUserMedia + AudioWorklet(浏览器) | 低 | 内置的 |
API
read = mic(opts?)
返回一个源函数。选项:
sampleRate违约44100channels违约1bitDepth- - - - - -8,16(默认),24,32bufferSize-距离设备最大的一个块,单位为毫秒,默认值50backlog-最长未读音频,单位为毫秒,默认值10000(见read(cb))device-按id或名称输入(devices()),默认为系统的backend-强制指定后端
read(cb)
读取PCM数据。每个捕获的块都会触发回调: (err, buffer) => {}.
捕获不等待读取:它们之间的内容被保留,下一次读取将把所有内容放在一个缓冲区中,因此占用时间的读取器没有损失任何东西。过去的 backlog 持有未读,捕获停止:持有的内容仍在读取,然后出现错误 code: 'EOVERFLOW',然后结束(null). 在node中,设备自己的环保存事件循环繁忙时出现的内容, backlog的值高达2秒,并以同样的方式溢出。自动停止(不插电)的设备也以同样的方式结束 code: 'EDEVICELOST'.
read(null)
停止捕获。关闭音频设备。那么在它还能读取之前捕获了什么呢 null.
read.close()
立即关闭音频设备。
read.backend
活动后端名称('miniaudio', 'process', 'null', 'mediastream')。
建筑
npm run build # compile native addon locally
npm test # run tests
出版
# JS-only change (no native code changed):
npm version patch && git push && git push --tags
npm publish
# Native code changed — rebuild platform packages:
npm version patch && git push && git push --tags
gh run watch # wait for CI
rm -rf artifacts
gh run download --dir artifacts \
-n mic-darwin-arm64 -n mic-darwin-x64 \
-n mic-linux-x64 -n mic-linux-arm64 -n mic-win32-x64
# (fallback) If darwin-x64 CI is unavailable, cross-compile locally:
npx node-gyp@latest rebuild --arch=x64
mkdir -p artifacts/mic-darwin-x64
cp build/Release/mic.node artifacts/mic-darwin-x64/
for pkg in packages/mic-*/; do
cp artifacts/$(basename $pkg)/mic.node $pkg/
(cd $pkg && npm publish)
done
npm publish
许可证
麻省理工学院