macOS系统声音录制指南:从虚拟声卡到ffmpeg实践
2026/8/26 13:36:57 网站建设 项目流程

录制 Mac 正在播放的声音,听起来像是一个很基础的需求:想保存一段网页直播、记录视频会议的讨论、采集某个播放器的音频,或者给游戏画面配上操作解说。但在 macOS 上,这件事并没有想象中那么简单。系统默认只允许录音软件读取麦克风这类输入设备,而扬声器、耳机对应的是输出设备,普通应用默认拿不到正在播放的内容。于是出现了 DesktopAudio 这类工具——它做的事情,就是让 Mac 正在播放的声音能够被录制下来。这篇文章会从 macOS 音频链路说起,把一个可以实际运行的“系统录音”流程完整搭起来,再讲清楚参数、验证、排错和生产环境注意事项。

1. 先理解 macOS 音频链路:为什么系统声音录不下来

1.1 默认状态下,输出设备与输入设备是两条不同链路

macOS 的音频体系建立在 Core Audio 之上。系统把声音设备分为输入和输出两端:麦克风是输入设备,扬声器、耳机、蓝牙音箱是输出设备。播放器把音频数据交给 Core Audio,Core Audio 再送到默认输出设备;录音软件请求的却是输入设备,拿到的是麦克风或其他输入源的数据。

这两条链路在系统层面默认不互通。所以你在录音软件里看到的“麦克风”列表里,不会出现“系统正在播放的声音”这个选项。这不是某个 App 的限制,而是 macOS 音频架构的设计结果。要录制系统声音,必须先做一个“桥接”:让系统输出的数据,能出现在某个输入端口上。

理解这一点,能解释很多看似奇怪的现象。例如录屏软件可以录到画面,却经常录不到电脑内部声音;又例如把系统音量静音后,录音结果也跟着变静音。这些现象都指向同一个根因:系统声音不是天然可采集的视频轨或音频轨,它需要一个专门的采集入口。

1.2 虚拟声卡:把输出“送进”输入端口

虚拟声卡(Virtual Audio Device)就是这座桥。它不是一个物理设备,而是一个借助系统音频驱动接口实现的虚拟设备。BlackHole 是这类工具里非常有代表性的开源实现:安装后,系统里会出现一个名为 “BlackHole 2ch” 的设备,它同时具备输出和输入两端。

应用向 BlackHole 播放声音时,声音不会进入真实扬声器,而是直接落到 BlackHole 的输入端口。录音应用从这个输入端口读取数据,就能拿到系统正在播放的内容。整个过程没有接线、没有物理设备,纯粹是系统音频引擎内部的数据流转。

这里有一个容易误解的地方:BlackHole 本身不会“录音”,它只负责把数据从输出端搬到输入端。真正把数据落盘的任务,仍然要由录音软件或脚本完成。把虚拟声卡当成“一根虚拟音频线”来理解,比把它当成“录音机”更准确。

1.3 DesktopAudio 在整套方案里的位置

DesktopAudio 这类工具通常做的事情,是把上面这套流程封装成更简单的操作:要么提供图形界面,要么把“选择虚拟设备、设置采样率、开始录制、保存文件”几步串成一个命令行工具。工具外壳会变,核心链路不变。不管用 DesktopAudio、ffmpeg、Audacity,还是自己写脚本,最终都要依赖“虚拟音频设备 + 录音程序”的组合。

所以在实际踩坑的时候,不要一遇到问题就怀疑工具本身。如果系统链路没有问题、虚拟声卡工作正常、录音程序也读到了数据,那么改哪一层都是改封装,而不是改核心。下面先从最直接的方式把链路搭出来,再解释参数和排查手段。这样即使以后换一个录制工具,排查思路也完全复用。

补充一下,macOS 上出现过多个类似方案,了解它们能帮助选型:

方案是否开源维护状态特点
Soundflower开源不再活跃维护早期常用虚拟声卡,Apple Silicon 下存在兼容问题
BlackHole开源活跃免费、稳定,支持多通道版本
Loopback商业软件活跃面向多应用混音,易用性好
Background Music开源更新较慢可调整单个应用音量,同时支持录音

2. 环境准备:在 Mac 上先搭好虚拟音频链路

2.1 确认 macOS 版本和芯片

开始前先确认 Mac 是哪一代系统、是 Intel 还是 Apple Silicon。查询方法:

sw_vers uname -m

输出示例:

ProductName: macOS ProductVersion: 14.5 BuildVersion: 23F79 arm64

arm64表示 Apple Silicon,x86_64表示 Intel。这个信息决定了后续安装驱动时是否要处理权限问题。BlackHole 的安装包在这两类芯片上都能用,但如果是自行编译或使用旧版驱动,一定要确认对应架构,否则会出现设备安装成功却无法识别的问题。

2.2 安装 Homebrew 作为基础包管理器

虚拟声卡和录音工具都用 Homebrew 安装,最省事。如果系统里还没有,执行官方安装命令:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装后确认:

brew --version

如果提示command not found: brew,通常是 Apple Silicon 上 Homebrew 的路径/opt/homebrew/bin没有加入 PATH。可以在 shell 配置文件中加入:

export PATH="/opt/homebrew/bin:$PATH"

然后把新配置重新加载进当前会话,再检查版本。

2.3 安装 BlackHole 虚拟声卡

BlackHole 有不同的通道版本。日常录制系统声音,2ch版本就够用:

brew install blackhole-2ch

安装完成后,建议刷新一次 Core Audio 服务,让系统立即识别新设备:

sudo killall coreaudiod

这个命令会短暂中断所有音频输出,执行完恢复正常后再继续。随后检查设备是否出现:

system_profiler SPAudioDataType

在输出中应能看到类似内容:

BlackHole 2ch: Type: Audio Input Channels: 2 Output Channels: 2 Manufacturer: ExistentialAudio

到这里,虚拟声卡已经进入系统,可以被负责录音的应用识别了。

2.4 用多输出设备避免录音时完全静音

如果直接把系统默认输出切换成 BlackHole,系统播放的声音会全部进入虚拟声卡,扬声器听不到任何声音,操作变成“盲录”。常见的做法是创建一个“多输出设备”,把真实扬声器和 BlackHole 绑定在一起,让同一份音频同时送到扬声器和虚拟声卡。

操作路径:打开“音频 MIDI 设置”(Audio MIDI Setup),它位于“应用程序 > 实用工具”,也可以在启动台搜索。点击左下角的“+”号,选择“创建多输出设备”,然后在右侧设备列表里勾选“扬声器”和“BlackHole 2ch”。

创建后,把多输出设备设为系统默认输出:系统设置 > 声音 > 输出,选择刚创建的多输出设备。此时播放任意音频,扬声器能听到,BlackHole 输入端口也能收到同样内容,录音链路完整。

注意:多输出设备只是把音频同时路由给多个输出,它不保证这些设备的时钟完全一致。短时间录屏没有问题,长时间专业录制建议按文末“生产环境建议”处理。

3. 最小可运行案例:把系统声音真正录下来

环境搭好后,先用最简单的方式录一段音频,验证链路是否通。

3.1 先用 ffmpeg 做一次纯音频录制

ffmpeg 是目前最方便的录音工具,先确认是否安装:

ffmpeg -version

没有安装则执行:

brew install ffmpeg

ffmpeg 在 macOS 上通过 avfoundation 框架接入音频设备。先查看设备列表:

ffmpeg -f avfoundation -list_devices true -i ""

输出里会列出视频设备和音频设备。音频设备部分通常能看到:

[AVFoundation indev @ 0x...] Found audio device: BlackHole 2ch [AVFoundation indev @ 0x...] Found audio device: MacBook Pro Microphone

avfoundation 的输入格式是“视频设备:音频设备”。只录声音时,视频位置写none

ffmpeg -f avfoundation -i "none:BlackHole 2ch" -c:a aac -b:a 192k record_output.m4a

Ctrl+C停止录制。录制期间播放一段音乐或视频,就能得到系统声音的录音文件。

如果设备名里的空格或特殊字符带来干扰,可以改用设备序号,序号以-list_devices显示为准:

ffmpeg -f avfoundation -i "none:1" -c:a aac record_output.m4a

3.2 用 Python 脚本实现同样的流程

不依赖 ffmpeg 时,可以用 Python 的sounddevice库完成录制。安装依赖:

pip install sounddevice numpy

写一个最小脚本record_system.py

import sounddevice as sd import numpy as np import wave DEVICE_NAME = "BlackHole 2ch" SAMPLE_RATE = 48000 DURATION_SECONDS = 10 OUTPUT_FILE = "system_audio.wav" sd.default.device = DEVICE_NAME recording = sd.rec( int(DURATION_SECONDS * SAMPLE_RATE), samplerate=SAMPLE_RATE, channels=2, dtype="int16", ) sd.wait() with wave.open(OUTPUT_FILE, "wb") as wf: wf.setnchannels(2) wf.setsampwidth(2) wf.setframerate(SAMPLE_RATE) wf.writeframes(recording.tobytes()) print(f"录音完成,已保存: {OUTPUT_FILE}")

运行:

python3 record_system.py

脚本会等待 10 秒,期间播放任意声音,结束后生成一个 WAV 文件。如果sounddevice找不到 “BlackHole 2ch”,先打印设备列表确认名称:

import sounddevice as sd print(sd.query_devices())

3.3 两种方式怎么选

方式优点缺点适合场景
ffmpeg命令简单、支持格式多、可直接压制编码参数略隐晦,依赖 FFmpeg快速录制、批量脚本
Python 脚本可编程、可叠加处理、便于二次开发需要安装依赖,适合定制逻辑自动化链路、定时任务

实际项目中,两种方式可以同时用:Python 负责触发和调度,ffmpeg 负责最终编码。下一步要理解采样率、通道数这些参数,因为大部分录音异常都出在这里。

4. 参数选择与原理解释:采样率、通道数、编码格式

4.1 采样率务必统一,否则音频会快慢失真

采样率是每秒采样次数。常见值有 44100Hz(CD 标准)和 48000Hz(视频、流媒体标准)。BlackHole 设备本身可以在运行时切换采样率,但同一时刻,系统默认输出设备、BlackHole、录音程序三者的采样率最好保持一致。

如果播放器以 44.1kHz 解码,而 ffmpeg 以 48kHz 去读 BlackHole,Core Audio 会尝试做采样率转换。多数情况下能工作,但可能出现音调偏高、时长缩短或偶发爆音。尤其是某些应用不遵循系统采样率设置时,录音结果会明显不对劲。

推荐做法:在音频 MIDI 设置里,把内置扬声器、BlackHole 2ch 的格式统一调整到 48000Hz。操作方式:选中设备,在右侧“格式”下拉框选择“48000.0 Hz”。这样无论播放什么内容,系统统一的采样率就是 48kHz。

4.2 通道数:2ch 足够,多通道要留意映射

BlackHole 有blackhole-2chblackhole-16chblackhole-64ch等版本。通道数代表虚拟声卡能同时传递多少路音频。系统立体声是左右两个声道,2ch版本已经覆盖常见需求。除非要做多声道混音、音乐制作,或者把不同 App 分配到独立通道,否则没有必要用 16ch。

用错通道数的一个典型问题:用 2ch 版虚拟声卡,却在录音软件里选择 16 通道,录出来的文件会有大量静音通道,占用空间且不好处理。反过来,录音程序只选 1 个通道,左右声道会被混到一路,丢失立体声信息。

4.3 比特深度与编码格式

采样率之外,还有比特深度和编码格式。

  • 比特深度决定每个采样点的精度,常见 16bit 和 24bit。录音中间素材建议 24bit,动态范围更大;最终交付常用 16bit。
  • 编码格式上,WAV 无损但体积大,AAC 有损但兼容性好,FLAC 无损压缩适合存档。

判断文件大小时,可以用公式估算:字节数 = 采样率 × 通道数 × 比特深度 / 8 × 时长。例如 48000Hz、2 通道、24bit、1 小时的 WAV 文件,体积约 48000 × 2 × 3 × 3600 = 1036800000 字节,接近 1GB。压缩编码会明显降低体积,但要做后期剪辑时,建议先从无损格式录制,最终再压成 AAC。

ffmpeg 常见组合:

# 无损中间格式 ffmpeg -f avfoundation -i "none:BlackHole 2ch" -c:a pcm_s24le record_master.wav # 压缩交付格式 ffmpeg -f avfoundation -i "none:BlackHole 2ch" -c:a aac -b:a 192k record_delivery.m4a

按用途选参数:

场景采样率比特深度编码
录制后剪辑4800024bitWAV / PCM
视频配音4800016bitAAC 192k 以上
播客存档4800024bitFLAC 或 WAV
快速分享44100 或 4800016bitM4A / AAC

5. 运行验证与结果检查

5.1 确认设备和采样率

录制前先检查设备状态:

system_profiler SPAudioDataType

查看 BlackHole 的Nominal Sample Rate是否与计划一致。如果显示 48000,说明设备已按 48kHz 工作。

5.2 检查录音文件是否正常

录制完成后,用 ffprobe 查看文件信息:

ffprobe record_delivery.m4a

关注时长、声道数、编码格式。时长应与实际录制时间接近。再用播放器试听,确认左右声道都有内容、没有爆音和拉伸感。

如果想用脚本检查波形幅值,可以用 Python 快速统计:

import wave import numpy as np with wave.open("system_audio.wav", "rb") as wf: data = np.frombuffer(wf.readframes(wf.getnframes()), dtype=np.int16) print(f"采样点数量: {len(data)}") print(f"最大幅值: {np.max(np.abs(data))}") print(f"有效数据比例: {np.mean(np.abs(data) > 100):.2%}")

如果最大幅值很低,说明录音中没有信号或输入电平设置太低;如果有效数据比例接近 0%,大概率是链路没有接通。

5.3 长时间录制先做稳定性测试

短录音成功不代表长录音没问题。建议先用 1 到 3 分钟的长度测试,观察是否出现声音漂移、周期卡顿或文件尾部截断。这类问题在多输出设备场景下更容易出现,原因是扬声器和虚拟声卡的时钟来源不同。测试时关注两个点:实际录制时长与计划时长是否一致、中途是否有明显丢帧。

确认链路稳定后再进入正式录制,避免录到一半发现素材不可用。

6. 常见问题排查:从现象倒推原因

以下整理这套方案里最容易出现的几个问题,按“现象 -> 原因 -> 检查 -> 解决”的顺序说明。

6.1 录音时听不到声音

现象:录制程序在跑,但扬声器没有声音,或者录音文件是静音。

原因:默认输出设备被切换成了单独的 BlackHole,系统把声音全部送进虚拟声卡,真实扬声器拿不到数据。

检查:

system_profiler SPAudioDataType

看默认输出设备是否为“多输出设备”。

解决:在音频 MIDI 设置里创建多输出设备,把扬声器和 BlackHole 都勾上,并将默认输出切换到这个多输出设备。如果只是长时间录音、不需要实时监听,也可以不做多输出,但操作时属于“盲录”,要留意时间点。

6.2 录音速度明显变快或音调不对

现象:录制出来的声音比原声音调高、时长偏短,或者明显偏慢。

原因:播放端和录制端的采样率不一致。比如系统输出 44.1kHz,而录音程序以 48kHz 读取,就会出现音调和速度漂移。

检查:在音频 MIDI 设置中逐个查看内置扬声器、BlackHole 的采样率,确认三者一致。

解决:统一设置采样率为 48000Hz。设置后重启播放器和录音程序,让所有应用重新读取设备格式。

6.3 录音文件有周期性爆音或卡顿

现象:录制过程中间隔几秒就出现“咔咔”声,或者音频片段丢失。

原因:可能来自两处。一是多输出设备没有时钟同步,长时间使用后两个输出端开始漂移;二是录音程序的缓冲区太小,系统处理不过来。

检查:观察录制时 CPU 占用是否过高,尝试调大录音程序的缓冲设置。

解决:如果只是监听用途,可以把多输出设备换成“仅 BlackHole + 录音软件内置监听”;如果必须同时听和录,优先选择支持时钟同步的聚合设备方案,或在正式录制前用短测试确认无卡顿。ffmpeg 录制时还可以减少不必要的滤镜,降低 CPU 压力。

6.4 录音 App 看不到 BlackHole 设备

现象:录音软件里找遍设备列表,始终没有 BlackHole。

原因:设备驱动已安装,但应用仍处于旧音频会话中;或者 coreaudiod 没有正确刷新。

检查:在终端执行system_profiler SPAudioDataType,如果能看到 BlackHole,说明系统已识别。

解决:退出所有录音相关 App,执行:

sudo killall coreaudiod

再重新打开录音软件。如果仍然看不到,检查是否在卸载后重装时驱动未完全注册,重新安装并重启 Mac。

6.5 麦克风权限或屏幕录制权限导致的静音

现象:录音软件没有报错,但录出来是无声;或者新安装的录音工具首次运行时提示需要权限。

原因:从 macOS Catalina 开始,应用访问麦克风需要用户授权;录制屏幕声音时还需要屏幕录制权限。BlackHole 被系统视为输入设备,录音应用读取它时可能触发麦克风授权。

检查:系统设置 > 隐私与安全性 > 麦克风,确认对应 App 已勾选;如果是录屏相关,还要检查“屏幕录制”授权。

解决:勾选授权后完全退出 App 再启动。第一次授权失败后,个别系统版本需要删除该 App 的权限记录,再重新授权一次。

注意:录音应用如果在“屏幕录制”权限未开启的状态下启动,可能拿不到系统级音频数据。排查时优先看授权,而不是反复重装虚拟声卡。

6.6 问题速查表

问题现象常见原因检查方式处理建议
录音静音默认输出切成了单独 BlackHole查看声音输出设置创建多输出设备并设为默认
音调偏高、时长偏短采样率不一致音频 MIDI 设置统一设为 48000Hz
周期性爆音多输出时钟漂移或缓冲过小观察 CPU、调大缓冲换聚合设备或减少负载
设备不识别coreaudiod 未刷新system_profiler重启 coreaudiod 或重启系统
无声但程序正常麦克风/屏幕录制权限缺失系统隐私设置授权后重启 App

7. 生产环境使用建议与扩展方向

7.1 不同场景选不同链路

  • 录教程视频:需要“系统声音 + 麦克风人声”同时录制,建议用多输出设备,并在后期把两条音轨分开处理。
  • 录播客:重点是麦克风音质和对端远程语音。应优先确保输入设备稳定,虚拟声卡只做辅助,不要为了让系统声音进录音而反复切换默认设备。
  • 多人协作或直播:避免频繁改动系统默认输出。建议给每个场景单独创建一套多输出设备配置,在音频 MIDI 设置里命名区分。

7.2 用定时任务实现自动录制

需要让 Mac 在固定时间自动录制某个播放源时,可以把 ffmpeg 命令写进 shell 脚本,再用launchd调度。脚本示例:

#!/bin/bash OUT_DIR="$HOME/Desktop/audio_records" STAMP=$(date +"%Y%m%d_%H%M%S") mkdir -p "$OUT_DIR" ffmpeg -f avfoundation -i "none:BlackHole 2ch" \ -c:a aac -b:a 192k \ "$OUT_DIR/rec_$STAMP.m4a"

执行权限:

chmod +x record.sh

生产环境使用脚本时,要补充日志、磁盘空间检查和失败退出码。录音任务长期运行时,还要定期清理旧文件,否则磁盘会被占满。

7.3 后期混流与降噪

录制完成后,视频和音频分开了,可以用 ffmpeg 合并:

ffmpeg -i video.mp4 -i audio.m4a -c:v copy -c:a aac -shortest merged.mp4

如果录的是远程会议,对端声音可能存在回声和压缩损失,建议在后期用专业音频软件做降噪和电平处理。前期采样格式和采样率越高,后期处理余地越大。

7.4 生产环境维护清单

  • 所有音频设备采样率统一为 48000Hz,并写入团队文档。
  • 录音脚本具备失败退出码、日志输出和磁盘空间预检查。
  • 长期运行的录制任务定期清理旧文件,避免占满磁盘。
  • 升级 macOS 前确认虚拟声卡驱动兼容性,保留前一个系统版本用于回滚。
  • 重要录制先做 1 分钟链路测试,再进入正式流程。
  • 涉及人声采集时,明确区分麦克风授权和屏幕录制授权,分别检查。

整体来看,DesktopAudio 这类工具的出现,本质上是把 macOS 系统音频输出“重新打通”的过程封装成了易用产品。只要理解了虚拟声卡在 Core Audio 里的作用,自己搭一套录制链路并不复杂;真正影响成品质量的,往往是采样率一致性、设备选择和权限管理这些细节。对刚接触的同学,建议先把 BlackHole 加多输出设备的链路跑通,再用 ffmpeg 录一段 10 秒音频检查文件;跑通之后再进入定时录制、多通道混音和自动化处理,就不会被各种报错牵着走了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询