RustAudio/cpal
GitHub: RustAudio/cpal
一个用 Rust 编写的跨平台低级音频输入输出库,为开发者提供统一的音频设备访问和音频流控制接口。
Stars: 3814 | Forks: 513
# CPAL - 跨平台音频库
[](https://github.com/RustAudio/cpal/actions) [](https://crates.io/crates/cpal) [](https://docs.rs/cpal/)
用于音频输入和输出的低级库,使用 Rust 编写。
如果需要更高层次的音频播放和捕获,请考虑使用 [Rodio](https://github.com/RustAudio/rodio) 或类似的库。
## 支持的功能
- 枚举音频宿主、设备及其支持的流配置。
- 通过稳定的 ID 或默认的输入/输出角色查找设备。
- 检查设备元数据:名称、制造商、类型和总线类型。
- 使用编译时或运行时采样格式构建输入和输出流。
- 播放、暂停以及查询流的缓冲区大小和时钟。
## 支持的平台
| 平台 | 默认后端 | 可选后端 |
| -------- | --------------- | ----------------- |
| Android | AAudio | - |
| BSD | ALSA | JACK, PipeWire, PulseAudio |
| iOS | CoreAudio | - |
| Linux | ALSA | JACK, PipeWire, PulseAudio |
| macOS | CoreAudio | JACK |
| tvOS | CoreAudio | - |
| WebAssembly | Web Audio API | Audio Worklet |
| Windows | WASAPI | ASIO, JACK |
## Linux 构建依赖
在 Linux 上,构建 cpal 需要 ALSA 开发文件:Debian 和 Ubuntu 上为 `libasound2-dev`,Fedora 上为 `alsa-lib-devel`。
即使使用 JACK、PipeWire 或 PulseAudio,也依然需要 ALSA。
可选的 `realtime-dbus` 功能额外需要 `libdbus-1-dev` (Debian/Ubuntu) 或 `dbus-devel` (Fedora)。请参阅 [ALSA 实时优先级提升](#alsa-real-time-priority-promotion)。
## 最低支持版本
最低 Rust 版本 (MSRV) 以及最低操作系统 / 运行时版本均取决于您所使用的音频后端和功能,因为每个平台具有不同的依赖项:
| 后端 | 平台 | MSRV | 最低 OS / 运行时 |
| ------- | --------- | ---- | -------------------- |
| AAudio | Android | 1.85 | Android 8.0 (API 26) |
| ALSA | Linux, BSD | 1.85 | — |
| CoreAudio | macOS | 1.85 | macOS 14.2(环回录制需要 14.6+) |
| CoreAudio | iOS | 1.85 | — |
| CoreAudio | tvOS | nightly | — |
| JACK | Linux, BSD, macOS, Windows | 1.85 | — |
| PipeWire | Linux, BSD | 1.85 | PipeWire 0.3.53 |
| PulseAudio | Linux, BSD | 1.88 | — |
| WASAPI / ASIO | Windows | 1.85 | Windows 8 |
| WASM (`wasm32-unknown`) | WebAssembly | 1.85 | — |
| WASM (`wasm32-wasip1`) | WebAssembly | 1.85 | — |
| WASM (`audioworklet`) | WebAssembly | nightly | — |
`audioworklet` 后端额外需要启用了 atomics 支持的 `-Zbuild-std`。
## 可选功能
| 功能 | 平台 | 描述 |
| ------- | -------- | ----------- |
| `asio` | Windows | 用于低延迟音频的 ASIO 后端,绕过 Windows 音频堆栈。需要 ASIO 驱动程序和 LLVM/Clang。请参阅 [ASIO 设置指南](#compiling-for-asio)。 |
| `audioworklet` | WebAssembly (`wasm32-unknown-unknown`) | Audio Worklet 后端,提供比默认 Web Audio API 更低延迟的 Web 音频,在专用线程上运行音频。需要 atomics 支持 (`RUSTFLAGS="-C target-feature=+atomics,+bulk-memory,+mutable-globals"`) 以及用于 `SharedArrayBuffer` 的 `Cross-Origin` 标头。请参阅 `audioworklet-beep` 示例。 |
| `custom` | 所有 | 用户定义的后端实现,适用于 CPAL 原生不支持的其他音频系统。请参阅 `examples/custom.rs`。 |
| `jack` | Linux, BSD, macOS, Windows | 用于专业音频路由和应用程序间连接的 JACK Audio Connection Kit 后端。需要 `libjack-jackd2-dev` (Debian/Ubuntu) 或 `jack-devel` (Fedora)。 |
| `pipewire` | Linux, BSD | PipeWire 媒体服务器后端。需要 `libpipewire-0.3-dev` (Debian/Ubuntu) 或 `pipewire-devel` (Fedora)。 |
| `pulseaudio` | Linux, BSD | PulseAudio 声音服务器后端。需要 `libpulse-dev` (Debian/Ubuntu) 或 `pulseaudio-libs-devel` (Fedora)。 |
| `realtime` | Linux, BSD, Windows, Android | 将音频回调线程提升至实时或高优先级调度,以降低延迟。在 Linux/BSD 上,除非同时启用了 `realtime-dbus`,否则需要在 `limits.conf` 中授予 `rtprio` 权限(例如 `@audio - rtprio 95`)。 |
| `realtime-dbus` | Linux, BSD | 在 Linux/BSD 桌面系统上通过 D-Bus 使用 `rtkit` 进行 RT 调度,免去了手动设置 `limits.conf` 的需要。意味着在所有平台上均启用 `realtime`。在 Linux/BSD 上需要 `libdbus-1-dev`。 |
| `wasm-bindgen` | WebAssembly (`wasm32-unknown-unknown`) | 用于基于浏览器的音频的 Web Audio API 后端;这是支持任何 WebAssembly 音频所必需的。请参阅 `wasm-beep` 示例。 |
请参阅 [beep 示例](examples/beep.rs) 了解如何在运行时选择后端。
## 为 ASIO 编译
### 定位 ASIO SDK
通过设置 `CPAL_ASIO_DIR` 环境变量向 CPAL 暴露 ASIO SDK 的位置。
构建脚本将按以下步骤依次尝试查找 ASIO SDK:
1. 检查是否设置了 `CPAL_ASIO_DIR`,如果已设置,则使用该路径指向 SDK。
2. 检查 ASIO SDK 是否已安装在临时目录中,如果已安装,则使用它并将 `CPAL_ASIO_DIR` 的路径设置为 `std::env::temp_dir().join("asio_sdk")` 的输出。
3. 如果 ASIO SDK 尚未安装,请从 下载并将其安装到临时目录。`CPAL_ASIO_DIR` 的路径将被设置为 `std::env::temp_dir().join("asio_sdk")` 的输出。
在理想情况下,您无需为此步骤操心。
### 准备构建环境
1. **安装 LLVM/Clang**:`bindgen`(用于生成 C++ SDK 绑定的库)需要 clang。从 的“Pre-Built Binaries”部分下载并安装 LLVM。
2. **设置 LIBCLANG_PATH**:将 LLVM 的 `bin` 目录添加到 `LIBCLANG_PATH` 环境变量中。如果您将 LLVM 安装到了默认目录,以下命令在命令提示符中应该可以正常运行:
setx LIBCLANG_PATH "C:\Program Files\LLVM\bin"
3. **安装 ASIO 驱动程序**(对于测试是可选的):如果您没有任何可用的 ASIO 设备或驱动程序,可以从 下载并安装 ASIO4ALL。请确保在安装过程中启用“offline”功能。
4. **Visual Studio**:构建脚本假定已安装 Microsoft Visual Studio。它将尝试找到 `vcvarsall.bat` 并使用正确的主机和目标架构执行它。如有需要,您可以手动执行它:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
有关更多信息,请参阅 [vcvarsall.bat 文档](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line)。
### 在您的应用程序中使用 ASIO
1. 在您的 `Cargo.toml` 中**启用该功能**:
cpal = { version = "*", features = ["asio"] }
2. 在您的代码中**选择 ASIO 后端**:
let host = cpal::host_from_id(cpal::HostId::Asio)
.expect("failed to initialise ASIO host");
### 交叉编译
当 Windows 同时作为宿主和目标 OS 时,构建脚本支持 MSVC 编译器支持的所有交叉编译目标。
也可以在 Linux 和 macOS 上使用 MinGW-w64 工具链编译具有 ASIO 支持的 Windows 应用程序。
**要求:**
- 在您的 `CPLUS_INCLUDE_PATH` 环境变量中包含 MinGW-w64 的 include 目录
- 在您的 `CPLUS_INCLUDE_PATH` 环境变量中包含 LLVM 的 include 目录
**macOS 上的示例**(目标为 `x86_64-pc-windows-gnu`,通过 brew 安装了 `mingw-w64`):
```
export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/opt/homebrew/Cellar/mingw-w64/11.0.1/toolchain-x86_64/x86_64-w64-mingw32/include"
```
## 为 WebAssembly 编译
如果您有兴趣将 CPAL 与 WebAssembly 结合使用,请查阅我们 Wiki 中的[此指南](https://github.com/RustAudio/cpal/wiki/Setting-up-a-new-CPAL-WASM-project),其中详细介绍了如何从头开始设置新项目。本仓库中的一些示例也提供了可供参考的有效配置。
## 故障排除
### 没有可用的默认设备
如果您收到关于没有默认输入或输出设备的错误:
- **Linux/PipeWire:** 检查 PipeWire 是否正在运行:`pw-cli info`
- **Linux/PulseAudio:** 检查 PulseAudio 是否正在运行:`pulseaudio --check`
- **macOS:** 在“系统偏好设置”>“声音”中检查可用设备
- **移动设备 (iOS/Android):** 确保您的应用具有麦克风/音频权限
- **Windows:** 在“声音设置”中验证您的音频设备是否已启用
## ALSA、PipeWire 和 PulseAudio
当 PipeWire 或 PulseAudio 正在运行时,它会独占 ALSA 的 `default` 设备。如果第二个流试图通过 ALSA 宿主打开它,将会失败并报 `DeviceBusy` 错误。要通过 ALSA 将音频路由至声音服务器,请使用桥接设备 `pipewire` 或 `pulse`,而不是 `default`。更好的做法是使用 `pipewire` 或 `pulseaudio` cpal 功能进行原生集成。
在没有声音服务器的目标上,直接使用 `hw:` 或 `plughw:` 寻址设备。
### 缓冲区大小问题
`BufferSize::Default` 使用系统配置的设备默认值,在 **ALSA** 上,这个值的范围可能从 PipeWire 量子(通常为 1024 帧)一直到配置错误或特殊硬件上的 `u32::MAX`。极深的缓冲区会导致样本的消耗速度远快于可听的播放速度,使得音频听起来像是在实际输出之前快进。
请配置系统和/或在您的应用程序中请求一个固定的大小:
| 系统 | 文件 | 设置 |
| ------ | ---- | ------- |
| ALSA | `~/.asoundrc` 或 `/etc/asound.conf` | `buffer_size`, `periods` * `period_size` |
| PipeWire | `~/.config/pipewire/pipewire.conf.d/` | `default.clock.quantum` |
| PulseAudio | `~/.config/pulse/daemon.conf` | `default-fragments` * `default-fragment-size-msec` |
```
config.buffer_size = cpal::BufferSize::Fixed(1024);
```
查询 `device.default_output_config()?.buffer_size()` 以获取有效范围。较小的缓冲区会减少延迟,但会增加 CPU 负载和出现故障的风险。
### ALSA 实时优先级提升
RT 提升仅会针对白名单中的 PCM 类型尝试进行:直接硬件 PCM (`hw:`) 和纯格式转换插件(linear、A-law、mu-law、ADPCM、float、IEC 958)。
只有在尝试进行提升但失败时,才会在错误回调中发出 `RealtimeDenied`,这种情况通常发生在进程缺乏获取 `SCHED_FIFO` 的资源限制时。虽然 RT 优先级对于低延迟来说是理想的,但流仍将以默认的调度优先级继续播放。
启用 `realtime-dbus` 功能后,`rtkit` 将在典型的桌面系统上通过 D-Bus 安排必要的限制。仅启用普通的 `realtime` 功能时,您必须自行确保已授予 `rtprio` 权限。将以下内容添加到 `/etc/security/limits.d/audio.conf` 中,并确保该用户是 `audio` 组的成员:
```
@audio - rtprio 95
```
然后将用户添加到 `audio` 组(`usermod -aG audio "$USER"`)并重新登录。在那些没有通过 `logind` 自动配置 `udev` 以授予 ALSA 设备文件访问权限的系统上,无论如何都可能需要相同的组。
### 构建错误
如果您无法构建该库:
- 确认您已经如上文所述安装了所需的开发库
**Windows 上的 ASIO:** 确认已设置 `CPAL_ASIO_DIR` 和 `LIBCLANG_PATH` 并且已安装 LLVM
## 示例
CPAL 在 `examples/` 目录中提供了几个示例。
使用以下命令运行示例:
```
cargo run --example beep
```
要启用特定平台的功能,请启用相关功能:
```
cargo run --example beep --features asio # Windows ASIO backend
cargo run --example beep --features jack # JACK backend
cargo run --example beep --features pipewire # PipeWire backend
cargo run --example beep --features pulseaudio # PulseAudio backend
```
## 资源
- **文档:** [docs.rs/cpal](https://docs.rs/cpal)
- **示例:** 本仓库中的 [examples/](examples/) 目录
- **更高层次的播放和捕获:** [Rodio](https://github.com/RustAudio/rodio) 或类似的库
- **Discord:** 加入 [#cpal 频道](https://discord.gg/vPmmSgJSPV) 进行提问和讨论
- **GitHub:** [报告问题](https://github.com/RustAudio/cpal/issues) 和 [查看源代码](https://github.com/RustAudio/cpal)
- **RustAudio:** 属于 [RustAudio 组织](https://github.com/RustAudio) 的一部分
## 许可证
在 Apache License, Version 2.0 下授权。详情请参阅 [LICENSE](LICENSE)。
标签:Rust, 可视化界面, 多媒体, 底层库, 网络流量审计, 通知系统, 音频处理, 音频输入输出