我正在尝试点击macOS上当前选择的输出音频设备,所以我基本上有一个直通侦听器,可以监视当前正在输出的音频流而不影响它。
我想将这些数据实时复制到环形缓冲区,以便我可以单独对其进行操作。
Apple 文档和(过时?)SO 答案的结合令人困惑,我是否需要编写一个 hacky 内核扩展,可以利用 CoreAudio 来实现此目的,还是需要与 HAL 进行交互?
如果可能的话,我想用 Swift 工作。
非常感谢
我不知道内核扩展 - Apple 使用特殊的“呼叫我们”签名证书以及关闭 SIP 的必要性阻碍了随意探索。
但是,您可以使用 CoreAudio 和 HAL AudioServer 插件的组合来完成您想要的操作,甚至不需要自己编写插件,有多个开源版本可供选择。
CoreAudio 没有为您提供从(或“点击”)输出设备进行录制的方法 - 您只能从输入设备进行录制,因此解决此问题的方法是创建一个虚拟“直通”设备(AudioServerPlugin),不与任何硬件关联,将输出复制到输入,然后将此传递设备设置为默认输出并从其输入进行记录。我使用开源音频服务器插件(如 BackgroundMusic、BlackHole 以及最近获得 MIT 许可的出色的 libASPL)来完成此操作。
要从生成的设备中点击/录制,您只需使用现有的录制 API,例如添加
AudioDeviceIOProc
回调或将设备设置为 kAudioOutputUnitProperty_CurrentDevice
kAudioUnitSubType_HALOutput
的 AudioUnit
或创建 AVCaptureDevice
(如果您使用 AVCaptureSession
)。
上述虚拟透传设备的方式存在两个问题:
如果 1. 是一个问题,那么一个简单的方法是创建一个包含传递设备和真实输出设备的多输出设备(参见屏幕截图)并将其设置为默认输出设备。音量控制停止工作,但您仍然可以在
Audio MIDI Setup.app
中更改实际输出设备的音量。
对于2.你可以给默认输出设备添加一个监听器,当它改变时更新上面的多输出设备。
您可以快速完成上述大部分操作,尽管对于从缓冲区传递回调进行环形缓冲区存放,您必须使用 C 或其他一些可以尊重实时音频规则的语言(无锁,无内存分配等) )。您也许可以尝试
AVAudioEngine
进行点击,但是 IIRC 更改输入设备是一个 泪谷。
更新:
macOS Monterey 中出现的
ScreenCaptureKit
API 添加了一个标志,可让您捕获输出音频缓冲区。上次我检查过,您还必须捕获屏幕(我猜它在 API 名称中),但这比我上面描述的要容易得多。