teodly/inferno
GitHub: teodly/inferno
这是一个基于 Rust 的 Dante 协议非官方开源实现,旨在让 Linux 系统能够作为 Dante 音频设备进行网络音频收发。
Stars: 248 | Forks: 24
# - Dante 协议的非官方实现
[GitLab](https://gitlab.com/lumifaza/inferno) | [GitHub](https://github.com/teodly/inferno) | [主要作者网站](https://info.lumifaza.org/)
本项目以[一个地方](https://en.wikipedia.org/wiki/Inferno_(Dante)命名,那是为那些创建未公开文档的网络协议的人准备的归宿。
目前处于高度实验阶段。我不建议将其用于严肃用途。
不过,它破坏已经正常工作的 Dante 网络的可能性很低。
如果你知道自己在做什么,并且具备基本的 Linux 命令行经验,它完全可以用于非关键任务,例如听音乐、通过调音台播放多轨录音以进行混音练习、录制排练。
非常感谢 [Project Pendulum](https://github.com/pendulum-project)(由 [Trifecta Tech Foundation](https://trifectatech.org/)发起)创建和维护 [Statime](https://github.com/pendulum-project/statime),并在视听网络功能所需特性上的合作!如果没有它,音频传输的实现将会困难得多。
# 功能
* 从 Dante 设备和虚拟设备接收音频,以及向其发送音频
* 兼容 Dante Controller 和 [network-audio-controller](https://github.com/chris-ritsen/network-audio-controller)(`netaudio` 命令行工具)的大部分功能
## 与其他 AoIP 虚拟声卡的比较
| | **Inferno** | [DVS](https://www.getdante.com/products/software-essentials/dante-virtual-soundcard) | [AES67 Linux daemon](https://github.com/bondagit/aes67-linux-daemon) |
|---|---|---|---|
| 成熟度 | ⏳ Alpha 阶段但已在生产环境使用 | ✅ 生产就绪 | ✅ 可能稳定 |
| 平台 | Linux | Mac, Windows | Linux |
| 支持的协议 | Dante | Dante | AES67 |
| 直接支持的音频后端 | ALSA | CoreAudio, ASIO, WDM | ALSA |
| 与 DAW 兼容 | 💣 实验性 | ✅ 是 | ✅ 是 |
| 使用 Dante Controller 跳线盘路由音频 | ✅ 是! | ✅ 是 | 🚫 仅限 AES67->Dante |
| 使用 Dante Controller 配置 | ⏳ 部分支持(通道名称,TX 组播) | ✅ 是 | 🚫 否 |
| 与 Dante Domain Manager 兼容 | 🚫 否 | ✅ 是 | 🚫 否(但可能进行 AES67 集成) |
| 支持的时钟协议 | [PTPv1](https://github.com/teodly/statime/tree/inferno-dev) ☑️, PTPv2 ☑️ | PTPv1 ✅ | PTPv2 ✅ |
| 时钟主控 | PTPv2 ☑️ 通过 [Statime](https://github.com/pendulum-project/statime) | 🚫 否(但在 Dante Via 中可能) | ☑️ 通过外部守护进程 |
* 从现代 Dante 硬件流式传输音频 | ✅ 是 | ✅ 是 | ✅ 是 |
* 从/向 DVS、Dante Via 和旧版 Dante 硬件流式传输音频 | ✅ 是 | ✅ 是 | 🚫 否 |
* 从/向 AES67 流式传输音频 | 🚫 否 | 🚫 否 | ✅ 是 |
| 最低延迟 | 取决于你的内核 | 4ms | ... |
| 发送和接收组播 | ✅ 是 | ✅ 是 | ✅ 是 |
| 操作系统集成 | 完全用户态 | 内核驱动和用户态服务 | 内核驱动和用户态辅助程序 |
| 轻量级录音应用 | ✅ 是 (Inferno2pipe) | 🚫 否 | ☑️ FFmpeg 配合 RTP 输入即可实现 |
| 磁盘空间和 RAM 占用 | 🌱 低 (~12MB RAM) | 🔥 高 | 🌱 低 |
| 编写语言 | Rust | C++, Java | C++, C |
| 许可证 | 🥰 FOSS, copyleft | 🔒 闭源 | 🥰 FOSS, copyleft |
| [DRM](https://drm.info/what-is-drm.en.html) | 😊 无 | 🔒 需要激活,禁止虚拟机 | 😊 无 |
| 价格 | 免费 | 🤑 50-80 美元 ... *仅用于一个 **设备驱动程序*** | 免费 |
| 隐私 | 😊 无跟踪 | 😡 需要注册,默认启用遥测 | 😊 无跟踪 |
* ✅ - 可用
* 💣 - 实验性
* ☑️ - 不是本软件的一部分,但集成很容易实现
* ⏳ - 即将实现(大概在 2025-06 之前)
* 🚫 - 未实现且近期无计划
## 怪癖,使用前请阅读:
* Dante 协议没有公开文档。所有内容都是通过逆向工程得出的,或者基于其他逆向工程项目。实现中的某些内容是猜测的。因此,虽然它在我的设置中有效,但在你的设置上可能无效。
* 注意到与 NTP 时钟同步存在冲突。内置时钟过滤器不够用。[正确修复它很复杂。](https://github.com/pendulum-project/statime/issues/389#issuecomment-2214559362) 如果你的网络接口支持硬件时间戳,你可以通过将 `/dev/ptp0` 用作 [`CLOCK_PATH`](#configuration) 并使用[不使用全局系统时钟的 PTP 守护进程](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/AES67#setting-up-ptp-time-sync) 来变通解决,但你需要在一台 Dante 设备上启用 PTPv2 (AES67),因为 ptp4l 与 PTPv1 不兼容。
* 要在 Statime 中修复此问题,需要为硬件时间戳实现 [PHC-only 模式](https://github.com/pendulum-project/statime/issues/517),为软件时间戳实现 [基于 CLOCK_MONOTONIC 且具有任意时间刻度的虚拟时钟](https://github.com/pendulum-project/statime/issues/389)
* Inferno2pipe 由传入的媒体流计时。当未连接任何内容时,“时间将停止”(即录音将暂停),直到再次连接某些内容——除非至少连接了一个通道,否则不会生成静音。
# 快速开始
1. [安装 Rust](https://rustup.rs/)
2. 如果使用防火墙,请打开 UDP 端口:4455, 8700, 4400, 8800(如果指定了 [`INFERNO_ALT_PORT`](#environment-variables),则为其他端口),5353。此外,允许来自可能的发送方的传入 UDP 流量(端口号由操作系统分配,因此无法预先知道)
3. 确保 seccomp、SELinux 或其他内核级安全机制没有阻止与时钟相关的系统调用。例如,如果你想将 `alsa_pcm_inferno` 与 PipeWire 一起使用,并且 PipeWire 服务由 systemd 管理,请将 [`os_integration/systemd_allow_clock.conf`](os_integration/systemd_allow_clock.conf) 复制到 `$HOME/.config/systemd/user/pipewire.service.d/override.conf`(或者,如果已存在,则追加到其中)
4. 如果想使用 Inferno2pipe 以外的任何东西, 需要时钟同步守护进程。Inferno 与修改版的 [Statime](https://github.com/pendulum-project/statime) 兼容:
* 目前,即使只是捕获音频,也总是需要 Statime,但这并非设计使然,将会修复
* `git clone --recurse-submodules -b inferno-dev https://github.com/teodly/statime`
* `cd statime && cargo build`
* 在 `inferno-ptpv1.toml` 中调整网络接口
* `sudo target/debug/statime -c inferno-ptpv1.toml`
* 在使用 Inferno 期间禁用全局系统时间同步(`systemctl stop chronyd.service`)
* 实验性时钟保护已添加到我们的 Inferno 分支中,所以如果你很勇敢,可以跳过它。
5. 使用 `--recursive` 选项克隆此仓库(某些依赖项在子模块中)
6. `cd` 到所需的程序/库目录
* 简单的命令行音频录音机:[`Inferno2pipe`](inferno2pipe/README.md)
* 用于 ALSA 的虚拟声卡:[`alsa_pcm_inferno`](alsa_pcm_inferno/README.md) - 也可以与 PipeWire 一起使用,应该可以与 JACK 一起使用(尚未测试)
7. 如果使用 `alsa_pcm_inferno`,请安装 alsa 开发库。
* 在 Debian/Ubuntu/Mint 上:`sudo apt install libasound2-dev`
* 在 Arch 上:`pacman -S alsa-lib`
* 在 Fedora/Centos 上:`dnf install alsa-lib-devel`
8. `cargo build`
9. 按照特定程序/库的 README 中的说明进行操作
## 交叉编译
如果你想在 Raspberry Pi 或其他单板计算机上使用 Inferno,通常在台式机/服务器/笔记本电脑(*主机*)上编译并将生成的二进制文件复制到*目标设备*会更快。此外,你不会耗尽 SD 卡空间或 RAM。
幸运的是,有一个**实际上零配置**的工具可以做到这一点:[`cross`](https://crates.io/crates/cross)。安装它,然后代替执行 `cargo build`,执行:
```
cross build --release --target=aarch64-unknown-linux-gnu
```
你将在 `target/aarch64-unknown-linux-gnu/release` 中找到编译好的二进制文件。
目前,目标系统上唯一需要的依赖项是 ALSA 库(如果使用 `alsa_pcm_inferno`)。其他所有内容都存储在二进制文件中。
不需要在主机系统上安装依赖项——`cross` 会根据 `Cargo.toml` 中的说明在其容器内安装它们。
如果你需要为不同的架构进行编译,请在运行 `cross` 之前将其添加到 `Cargo.toml`(复制粘贴 `workspace.metadata.cross.target` 部分)。这仅对 `alsa_pcm_inferno` 是必需的。Statime 没有任何共享库依赖项。
## 你更喜欢 Docker 吗?
这不适用于通常的桌面系统使用,但如果你正在使用 ALSA 将音频应用程序打包到 Docker 容器中,我们已经为你准备好了!请参阅 `test/containerized_trx` 目录以获取灵感。
请记住:
* 时钟同步仍然是你的责任。我不想用服务管理使基础镜像复杂化,因此未包含 PTP 守护进程。`usrvclock-rs` 要求所有容器的套接字路径(包括客户端套接字)相同,因此需要为 `/tmp` 设置共享卷。未来版本可能会将 Statime 作为单独的容器包含在内。
* Dante 协议需要良好的计时。允许实时优先级。
* 网络路由(包括组播)可能很难正确配置,但 `--network=host` 是你的朋友。或者将容器与你的 AoIP 网络桥接。NAT 是你的敌人。
* 要保持状态持久化,请将 `/root/.local/state/inferno_aoip` 挂载为卷(如果你的应用程序不以 root 身份运行,则为不同用户的卷)
# 法律和道德事项
免责声明:Dante 使用 Audinate 拥有专利的技术。此源代码也可能使用这些专利。如果你想:
* 靠它赚钱
* 在(或从)适用软件专利的地区分发二进制文件
请咨询律师。
本项目不声称已获得 Audinate 的授权或批准。
请不要使用本项目来制作假冒的 Dante 设备/软件,这是不道德且非法的(而 Audinate 的做法仅仅是不道德)。请始终说明该实现是非官方的,且未得到 Audinate 的认可。也许你可以在法律上声称它与 Dante 协议的子集兼容,但我不是律师。
## 许可证
本项目在 GPLv3-or-later 和 AGPLv3-or-later 下双重许可。你可以选择使用哪种许可证,或者保留两者。例如:
* 如果你想将其集成到已经获得 GPL 许可的项目中,你有权这样做。
* 如果你想将其分叉到在云中运行的东西(或通常在公共 Internet 上),使用 AGPL 并在分叉时**移除** GPL 将对自由软件社区有益。
# 已测试
## Dante 设备
* Audinate AVIO
* AVIO-AES3
* AVIO-DAI2
* AVIO-DIOUSBC
* Ben & Fellows 523019 4x4 平衡模拟 I/O 模块(基于 Dante UltimoX4)
* MUSIC Group
* Klark Teknik DN32-DANTE(在 Behringer X32 中)(基于 Dante Brooklyn II)
* Behringer Aoip-Dante(在 Behringer Wing-Rack 中)(基于 Dante Brooklyn III)
* Orban Optimod 5750(基于 Dante Broadway)
* Soundcraft
* Vi2000
* Vi3000
* Allen&Heath
* SQ-5
* SQ-6
* Qu-5D
* Yamaha Dante-MY16-AUD(在 Yamaha LS9 中)(也测试了旧的 3.x Dante 固件版本)
* ESI planet 22c
* Dante Via @ OS X 和 Windows 11
* Dante Virtual Soundcard @ Windows 10
## 控制软件
* Dante Controller @ Windows 10, 11
* network-audio-controller
## 主机
* x86_64 Linux
* Arch
* Ubuntu
* Fedora
* aarch64 (ARM 64-bit) Linux
* Raspberry Pi 5 - Raspberry Pi OS & Armbian Bookworm
* Raspberry Pi 4(无硬件 PTP)- Raspberry Pi OS Lite (64bit)
* Raspberry Pi Zero 2 W(带 USB 以太网)- Raspberry Pi OS Lite (bit) - 注意构建时间很长
# 仓库结构
* `inferno_aoip` - 用于模拟 Dante 音频 over IP 设备的主要库 crate。将来还将实现控制器功能。**如果你想基于 Inferno 开发应用程序,请从这里开始**。
* `inferno2pipe` - 捕获音频,将交错的 32 位整数样本写入 Unix 命名管道(或原始文件)。还提供了用于录制为更方便格式的辅助脚本。**如果你想使用 Inferno 捕获音频而无需设置整个音频堆栈,请从这里开始**
* `alsa_pcm_inferno` - 用于 ALSA 的虚拟声卡。**如果你曾经梦想过 Linux 版的 Dante Virtual Soundcard,请从这里开始**
* `searchfire` - [Searchlight](https://github.com/WilliamVenner/searchlight) mDNS crate 的分支,经过修改以与 Dante 的 mDNS 兼容
# 时钟选项
## 软件时间戳
这是默认选项,与所有 NIC(网卡)和 Dante 设备兼容。它需要[我们的分支或 Statime 守护进程](https://github.com/teodly/statime/tree/inferno-dev)。
在 `inferno-ptpv1.toml` 配置文件中更改网络接口,并使用以下命令运行守护进程:
```
sudo target/debug/statime -c inferno-ptpv1.toml
```
如果你想要额外的稳定性,请禁用时间同步,通常以下命令之一就足够了:
```
sudo systemctl stop chronyd.service
sudo systemctl stop systemd-timesyncd.service
sudo systemctl stop ntpd.service
```
如果 `virtual-system-clock-base` 设置为 `monotonic` 或任何以 `monotonic` 开头的值,这应该不再需要,但此修复/变通方法非常新,所以请小心。
如果你配置了足够高的 `TX_LATENCY_NS` 和 `RX_LATENCY_NS`(TODO:多高才算足够?),你可以尝试使用 `monotonic_coarse`,这应该会减少 CPU 负载。
你可以在 Statime 配置中将协议从 PTPv1 更改为 PTPv2——这允许主控操作(目前仅针对 PTPv2 实现),因此即使网络中没有物理 Dante 设备,也可以使用 Inferno。但是,网络中必须至少存在一台启用了 AES67 的 Dante 设备,才能使 Inferno 和 Dante 设备互操作。
## 硬件时间戳
如果你的网卡支持硬件时间戳(使用 `ethtool -T` 检查),你可以直接使用其时钟,而无需依赖系统时钟。它比软件时间戳更准确,这意味着你可能会使用更低的音频延迟。
将 Inferno 的配置选项 `CLOCK_PATH` 设置为 PTP 时钟设备路径,通常是 `/dev/ptp0`。
如果你需要 PTPv1(不带 AES67 的 Dante),你需要使用我们的 Statime 分支,因为没有其他开源 PTPv1 守护进程。在 `inferno-ptpv1.toml` 中,将 `hardware-clock` 选项设置为 `auto` 并启动守护进程:
```
sudo target/debug/statime -c inferno-ptpv1.toml
```
如果你能接受 PTPv2,你可以使用不同的 PTP 实现,例如 [linuxptp](https://www.linuxptp.org/):
```
sudo ptp4l -i enp0s31f6 -p /dev/ptp0 -l6 -E -H -s -m -4 --priority1 255 --priority2 255 --domainNumber 0 --freq_est_interval=7 --delay_filter_length=240 --dscp_event 46
```
或 [未修补(上游)Statime](https://github.com/pendulum-project/statime)。
使用 Statime 和 ptp4l 时,音频数据包延迟抖动相似,但 DC 中的时钟直方图显示,从长远来看 ptp4l 的变化更剧烈,而 Statime 在启动期间几秒钟内不稳定。
请注意,Inferno 非常频繁地查询时钟,这可能会比使用系统时钟给 CPU 带来更大的负载。如果你想避免这种情况,但仍然获得硬件时间戳的一些好处,请在 Statime 配置中指定 `hardware-clock`,但保持 Inferno 的 `CLOCK_PATH` 未设置。此外,请阅读[软件时间戳](#software-timestamping)部分。
# 配置
可以通过以下方式设置配置:
* 环境变量 - 在设置名称前添加 `INFERNO_` 前缀
* ALSA 插件配置 - 建议在你的 `asoundrc` 中指定它们,因为过长的 ALSA 设备字符串可能会被截断(发生在 PipeWire 中,不确定其他应用程序)
## 设置
所有设置都有默认值。在简单的设置中,你应该能够在不指定任何参数的情况下启动。
* `BIND_IP` - 绑定到哪个本地 IP。如果你有多个网络接口,可能需要指定它。或者,可以指定网络接口名称,在这种情况下,将使用属于该接口的第一个地址。
* `DEVICE_ID` - 用作设备 ID 的 16 位十六进制数字(8 字节)。Dante 设备通常使用用零填充的 MAC 地址。Inferno 默认使用 `00000000`。设备 ID 是保存状态时的存储键。
* `NAME` - 广告设备的名称。如果未指定,将根据应用程序名称和 IP 地址生成名称。可能会在将来的版本中删除,当它可以从 DC 设置并因此存储在配置文件中时。
* `SAMPLE_RATE` - 此设备将运行的采样率
* `PROCESS_ID` - 0 到 65535 之间的整数。在单个 IP 地址上启动多个实例时必须提供且唯一。指定不同的 `DEVICE_ID` 是不够的。
* `ALT_PORT` - 套接字侦听器使用的 UDP 端口范围的开始。如果未指定,将使用硬件设备中看到的标准 Dante 端口。在单个 IP 地址上启动多个实例时必须提供。目前使用 4 个端口(`ALT_PORT` 到 `ALT_PORT+3`),但这将来可能会改变,所以最好将不同的实例至少分开 10 个端口。
* `RX_CHANNELS` - 接收通道数,默认为 2,如果应用程序支持更改通道数,将被覆盖。
* `TX_CHANNELS` - 发送通道数,默认为 2,如果应用程序支持更改通道数,将被覆盖。
* `RX_LATENCY_NS` - 以纳秒为单位的接收延迟,即相对于 PTP 媒体时钟等待媒体数据包的时间。相当于 Dante Controller 中的延迟设置。默认为 10ms。可能会在将来的版本中删除,当它可以从 DC 设置并因此存储在配置文件中时。
* `TX_LATENCY_NS` - 以纳秒为单位的发送延迟,即此设备将从我们接收的设备要求的接收延迟。相当于 Dante Virtual Soundcard 中的延迟设置。默认为 10ms。
* `CLOCK_PATH` - [usrvclock](https://gitlab.com/lumifaza/usrvclock) 套接字或 PTP 设备的路径。如果是后者,请确保[你被允许](https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/78642cc53bd84c2ad529f2175cc50a658d1e52c0/src/daemon/90-pipewire-aes67-ptp.rules) 读取它。此外,如果你想查看 DC 中的实际频率偏移,则需要写入权限。(时钟从未在 Inferno 内部调整,但读取频率的系统调用需要写入访问权限)
# 音频稳定性提示
## 设置适当的延迟
禁用 Inferno。运行 cyclictest 至少 20 分钟,同时执行你通常在计算机上执行的操作:
```
cyclictest --mlockall --smp --priority=80 --interval=5000 --distance=0
```
你还可以添加一些人工系统负载:
```
stress -m `nproc` -c `nproc`
```
在 cyclictest 输出中,最后一列是以微秒为单位的最坏情况延迟。将其乘以 1000,加上一些余量和网络传输时间,你就得到了 `TX_LATENCY_NS` 和 `RX_LATENCY_NS` 的最低安全值。如果这些值高于你可接受的延迟,你将很难使用 Inferno(以及一般的计算机音频)。还要记住,Dante 官方允许的最大延迟是 40ms。你可以尝试遵循教程使延迟更可预测:
* [Professional audio @ Arch wiki](https://wiki.archlinux.org/title/Professional_audio)(不仅限于 Arch)
* [Performance tuning @ PipeWire wiki](https://wiki.archlinux.org/title/Professional_audio)
* [Fedora Pipewire Low Latency Audio Configuration Reference Guide](https://linuxmusicians.com/viewtopic.php?t=27121)(特定于 Fedora)
* 使用 `isolcpus` [或 `cset`](https://unix.stackexchange.com/a/692558) 隔离 CPU 内核,并将音频进程和网卡 IRQ 固定到隔离的内核
* 如果没有其他帮助,请尝试 `PREEMPT_RT` 内核
## 依赖项
本项目依赖于 Statime([上游](https://github.com/pendulum-project/statime),[我们的分支](https://github.com/teodly/statime/tree/inferno-dev)),所以如果你想提供帮助,也请查看它的 TODO 列表!最重要的是:
* [PTPv1 支持](https://github.com/pendulum-project/statime/pull/602) - 从机已经工作但尚未上游
* [PHC-only 模式](https://github.com/pendulum-project/statime/issues/517)(用于硬件时间戳)
* [任意时间刻度的独立时钟](https://github.com/pendulum-project/statime/issues/389)(用于软件时间戳)- 已经有点工作了,但由于 Linux 使用 CLOCK_REALTIME 进行软件时间戳而不稳定,并且尚未完全上游
# 更新日志
## 0.5.0
* 与 JACK 一起工作,应该可以与任何使用声卡作为中断源的应用程序一起工作
* 引入了自动化集成测试,该测试启动多个实例,在它们之间流式传输音频数据并检查其正确性(包括音频比较)。目前测试 JACK、PipeWire、aplay、arecord 与 alsa_pcm_inferno。计划支持 SoX 和 Inferno2pipe。
* Dockerfile
* 修复 CPU 锁定预防代码中的逻辑错误
## 0.4.3
* 支持单调时钟作为基础,并带有防跳变保护(Statime)
* 减少 CPU 过载时的滚雪球效应,发送器滞后并尝试一次传输多个数据包:最大滞后设置为 `TX_LATENCY_NS`,如果发送线程锁定超过 5ms,将强制休眠 2ms
## 0.4.2
* 优化:从环形缓冲区索引计算中删除模除法
## 0.4.1
* 暂时禁用 SafeClock,没有太大帮助并且会损害 PHC
* 修复在可以每个流发送大量通道的设备(例如 Behringer Wing)上的恐慌
## 0.4.0
* 重构 - 为引入控制器功能做准备
* 组播发送器
## 0.3.3
* 修复在路由表中没有默认路由的情况下启动(Searchfire)
## 0.3.2
* 可更改的 RX 和 TX 通道名称
* RX 和 TX 延迟可通过环境变量或 ALSA 插件参数配置
* 重新许可为 GPL-or-AGPL,以简化分叉到 AGPL 项目,因为本项目的某些部分在云应用程序中可能有用
## 0.3.1
* 从 ALSA 插件参数读取配置 - 对于 PipeWire 中的多个源和接收器很有用
* 发送统计信息(时钟、延迟、信号电平)
* 可更改的 usrvclock 路径
## 0.3.0
* 引入了 ALSA PCM 插件 - 与大多数 Linux 音频应用程序兼容的虚拟声卡
* 使用记录的协议接收时钟:[usrvclock](https://gitlab.com/lumifaza/usrvclock)
* 各种内部更改,主要与允许使用外部缓冲区(ALSA 插件中的 mmap 模式所需)有关
* 接收组播
* 能够使用非默认网络端口以允许在单个 IP 地址上运行多个实例
* 删除了 Inferno Wired,因为 ALSA 插件与 PipeWire 配合良好。对于好奇的人来说,[这是最后一个版本](https://gitlab.com/lumifaza/inferno/-/blob/3941765700696f545425a5479be25091fda514d4/inferno_wired/src/main.rs)。
## 0.2.0
* 音频发送器
* Inferno Wired 的 Alpha 版本 - 用于 PipeWire 的虚拟音频源和接收器
* 从为 PTPv1 和虚拟时钟支持而修改的 [Statime](https://github.com/teodly/statime) 接收时钟 - 目前仅限 Linux(因为 CLOCK_TAI 仅限 Linux)
* 提高接收线程优先级以减少操作系统 UDP 输入队列溢出的可能性
## 0.1.0
初始版本
# 待办事项
可能会按它们将被实现的顺序排列
* 能够在 Dante Controller 中更改设置
此时,Inferno 将大致成为 Dante Virtual Soundcard 的替代品。
* 可配置的实时线程优先级
* 在 DC 中报告迟到的数据包
* 在没有 PTP 守护进程的情况下以较低的时钟精度运行 - 对于 Linux 以外的操作系统有用
* 从文本文件读取配置
* 能够作为时钟源工作(PTPv1 主控)- Statime
* 如果你使用 PTPv2,这已经是可能的——理论上你应该能够建立仅 Inferno 的 AoIP 网络——尚未测试
* 向集成测试添加更多应用程序和 Linux 发行版
* 完美发送器(内部始终使用 32 位整数;16 位和 24 位输出的 TX 抖动可通过 `TX_SOURCE_BIT_DEPTH` 配置)
* 命令行助手 / TUI / GUI
* 安装程序脚本,支持交叉编译
* 对网络数据包序列化器和反序列化器进行更多重构,以便在即将推出的控制器应用程序中重用更多代码(因为 DC 臃肿且是闭源的,用户体验很差)
* AES67
* 主网络和辅助网络支持,适用于双网卡计算机
* API:无需重启设备服务器即可更改通道数(对于类似 Dante Via 的操作很有用,其中发送器和接收器可以动态添加和删除)
* 并不是真正需要复制 Via 的功能,因为现在支持在单个 IP 地址上运行多个 Inferno 实例
* `grep -r TODO inferno_aoip/src`
# 设计
* 99% 安全的 Rust(unsafe 是必需的,因为 ALSA 插件 API 没有安全的 Rust 绑定)
* 不需要外部库,依赖项是 Rust crates
# 动机
多年来,我一直使用自由(言论自由意义上的)开源软件。我也着迷于音乐与技术之间的联系。有一天,我的音响工程师同事向我展示了 Dante 的工作原理,它是多么易于使用并且(大多数时候)稳定。问题在于它不是一个开放标准,没有开源实现,而且我无法在我最喜欢的操作系统——Linux 上使用它。现在我可以了。
## 为什么不使用 AES67?
* AES67 只是媒体传输的标准,而不是控制标准,因此需要手动建立流。NMOS 可以解决这个问题,但我怀疑 Audinate 会在合理的未来实现它。
以下是 Dante 中 AES67 实现的限制,而不是一般的 AES67:
* Dante Virtual Soundcard 和 Dante Via 不支持它
* 一些较旧的 Dante 设备(没有固件升级)也不支持它
* 它仅支持组播
* 采样率锁定为 48kHz
# 其他与 Dante 相关的开源项目
* [network-audio-controller](https://github.com/chris-ritsen/network-audio-controller) - 命令行连接和设备控制器,Dante Controller 的替代品
* [companion-module-audinate-dantecontroller](https://github.com/bitfocus/companion-module-audinate-dantecontroller) - 用于控制 Dante 设备的 Bitfocus Companion 模块
* [inferno_runners](https://github.com/maze42d/inferno_runners) - 用于运行 Inferno 的脚本,带有基于 PipeWire 的声卡间桥接和 [USB audio gadget](https://www.diyaudio.com/community/threads/linux-usb-audio-gadget-rpi4-otg.342070/)
* [dante-aes67-relay.js](https://gist.github.com/philhartung/87d336a3c432e2ce5452befcad1b945f) - 将 Dante 组播流中继到 AES67
* [wycliffe](https://github.com/jsharkey/wycliffe),包含在视频控制软件中的接收器实现——逆向工程 Dante 的最早公开尝试
* [AES67 音频资源列表](https://aes67.app/resources) 位于 [AES67 Stream Monitor](https://aes67.app/) 网站(Dante 与 AES67 兼容,但并非在所有设备上,并且需要手动配置)
## 替代方案
据我所知,没有其他与 Dante 兼容的音频传输非官方实现。但是,如果 AES67 适合你的用例,你可能想要使用:
* [AES67 Linux daemon](https://github.com/bondagit/aes67-linux-daemon) 配合内核级虚拟声卡
* [pipewire-aes67](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/AES67)
* [aes67-recorder](https://github.com/voc/aes67-recorder)([与 Dante 一起使用的教程](https://behringer.world/viewtopic.php?t=197))
* AES67 也可以由任何支持 RTP 数据包中原始音频的软件接收,例如 FFmpeg 或 GStreamer。
* ... Dante 组播同样简单……只需在每个 UDP 数据包的前面切掉 9 个字节 ;)
标签:ALSA, AoIP, Dante 协议, DNS解析, PTP, Statime, 云资产清单, 内核驱动, 可视化界面, 媒体传输, 开源项目, 录音, 现场扩声, 网络协议, 网络音频, 虚拟声卡, 请求拦截, 逆向工程, 通知系统, 非官方实现, 音频, 音频 over IP, 音频制作, 音频发送, 音频接收