Open-source project
bondagit/aes67-linux-daemon avatar
bondagit/aes67-linux-daemon

AES67 Linux Daemon: sending synchronised audio over Ethernet with a web interface

AES67 Linux Daemon with configuration WebUI

563 stars105 forksC++GPL-3.0

At a glance

What is it?
The AES67 Linux Daemon is a C++ process that configures an ALSA virtual audio device so it can send and receive RTP audio streams on a PTP clock, and it exposes everything through a REST interface and a web UI. It is broadcast equipment software, so the requirements are unusually specific and the README says so at length.
Who is it for?
Adopt the AES67 Linux Daemon if you need to bridge professional audio between a Linux machine and an AES67 network, and you are willing to load a kernel module and disable PulseAudio. Do not adopt it for general audio routing or as a virtual sound card for ordinary desktop use, since the whole design is a broadcast interoperability device.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

This is a broadcast interoperability device, not a sound card

AES67 Linux Daemon is a Linux implementation of the AES67 interoperability standard used to distribute and synchronise real time audio over Ethernet, and the Wikipedia link for background is in the first paragraph.

The mechanism is worth understanding before the code, because it explains every design choice in the project.

The daemon is a Linux process that uses the Merging Technologies ALSA RAVENNA/AES67 Driver to handle PTP synchronisation and RTP streams, and it exposes a REST interface for configuration and status monitoring.

That driver implements a virtual ALSA audio device configurable using Sources and Sinks, and clocked using the PTP clock. A Source reads audio samples from the ALSA playback device and sends RTP packets to a configured multicast or unicast address. A Sink receives RTP packets from a specific multicast or unicast address and writes them to the ALSA capture device.

So a user can use the ALSA capture device to receive synchronised incoming audio samples from an RTP stream, and the ALSA playback device to send synchronised audio samples to an RTP stream. The binding between a Source and the playback device is determined by the channels used during playback and the configured Source channels map, and the binding between a Sink and the capture device is determined by the channels used while recording and the configured Sink channels map.

The project is GPL-3.0 licensed, written in C++, and the release history shows steady work through 2026: v4.0.2 on 2026-10-02, v4.0.1 on 2026-09-02 and v4.0.0 on 2026-08-21, with the last push on 2026-10-21.

The kernel module does the audio, the daemon does the control

The driver handles the PTP and RTP packet processing and acts as a PTP clock slave to synchronise with a master clock on the specified PTP domain. All the configured Sources and Sinks are synchronised using the same PTP clock.

The separation between the two components is clean, and it is the right one. The kernel module owns the audio path, where latency matters and where the work belongs. The daemon communicates with the driver for control, configuration and status monitoring only, by using netlink sockets.

That word only is doing some work. The daemon never carries audio. It configures sources and sinks, reads status, and reports. So a daemon problem does not corrupt the audio path, and an audio problem is a driver problem, which narrows the debugging surface considerably on a system where debugging is already hard.

The daemon implements a REST interface to configure and monitor the Sources, the Sinks and the PTP slave, with more detail in the daemon README. It also implements SAP sources discovery and advertisement compatible with the AES67 standard, and mDNS sources discovery and advertisement compatible with the Ravenna standard.

Those two discovery mechanisms are worth separating, because they are different worlds. SAP is the session announcement protocol that AES67 standardised on, and mDNS is what the Ravenna ecosystem used, so the daemon speaks both to interoperate with equipment from either camp.

The web UI is a REST client, not a separate service

A WebUI is provided to allow daemon and driver configuration and monitoring. The WebUI uses the daemon REST API and exposes all the supported configuration parameters for the daemon, the PTP slave clock, the Sources and the Sinks.

That design has an advantage that is easy to miss. Because the browser talks to the daemon over the same REST interface that a script would use, there is exactly one implementation of the configuration semantics. A separate control protocol for the UI would be a second thing to keep in step with the first, and this way the UI is just another client of the same API.

The WebUI can also be used to monitor the PTP slave status and the Sinks status, and to browse the remote SAP and mDNS sources. That last capability is the one that makes it more than a settings form. Discovering what sources are on the network, and seeing whether they are locked to the PTP master, is the information you need to work out why a stream is not synchronised, and having it in the same interface as the configuration means you can check and fix in one place.

The repository layout confirms the split into three buildable pieces, with daemon/ and webui/ as separate directories, a 3rdparty/ directory for the vendored driver, a systemd/ directory for the service unit, a test/ directory, and standalone scripts for building, testing and cleanup: build.sh, buildfake.sh, cleanup.sh, run_latency_test.sh and run_test.sh.

The build script builds three things and patches the kernel module

The setup instructions are explicit that you install an Ubuntu Linux distribution on the target machine, both ARM or X86, and in capitals that no virtual machines.

The clone step needs the submodules, because the RAVENNA/AES67 driver submodule provides the public headers the daemon uses, including driver/RTP_stream_info.h:

bash
      git clone --recurse-submodules https://github.com/bondagit/aes67-linux-daemon.git

For an existing checkout, you run git submodule update --init --recursive before configuring with CMake, and the supplied build.sh performs this initialisation automatically.

Then there is the package install step, which runs the ubuntu-packages.sh script, and the build step, which runs build.sh to download and build the driver, the daemon and the WebUI. The README spells out what that script does, and the order matters. It checks out, patches and builds the Merging Technologies ALSA RAVENNA/AES67 module. It checks out cpp-httplib. It builds and deploys the WebUI. And it builds the AES67 daemon.

The patch step is the interesting one. The driver is not consumed as an upstream release, it is checked out, modified and built, which is what a project that has to work around kernel specifics ends up doing.

The configuration step is a single edit. You edit the daemon configuration file daemon/daemon.conf and change the interface_name parameter to the ethernet network interface you want to use, for example eth0. Then you install the driver by executing from the main folder:

bash
      (cd 3rdparty/ravenna-alsa-lkm/driver && sudo insmod ./MergingRavennaALSA.ko)

And you start the daemon by executing from the main folder:

bash
      cd daemon
      ./aes67-daemon -c daemon.conf

There is a daemon option -a if you want to bind the daemon HTTP server to another address, with -a 0.0.0.0 to bind to all the local network interfaces.

The requirements list reads like a support matrix

The prerequisite section is the most useful thing in the README for anyone deciding whether to try this, and it is specific to the point of being a support matrix.

The daemon and the test have been verified starting from Ubuntu 18.04 onwards for ARMv7 and x86 platforms, using a Linux kernel version of at least 4.10.x, GCC 7.x or newer or clang 6.x or newer with C++17 support required, cmake 3.7 or newer, boost libraries 1.65 or newer, Avahi service discovery at 0.7 or newer if enabled, and libfaac 1.30 or newer if the streamer is enabled.

Two of those are conditional, which tells you the Avahi dependency is for the mDNS discovery path and faac is for the streamer, so a minimal build that uses only SAP discovery and receives rather than sends does not need them.

The platforms used for testing are named too, and they are small computers rather than servers. A NanoPi NEO2 with an Allwinner H5 quad-core 64-bit Cortex A53, and a Mini PC N40 with an Intel Celeron N4020, two cores and two threads with 4 MB of cache up to 2.80 GHz. Both are the kind of fanless embedded box that would sit in a rack or a studio, which is a good indication of the target use.

There is a debian-packages.sh script that can be used to install all the packages required to compile and run the daemon, and a platform compatibility test referenced from the same section.

Three environment warnings that will cost you an afternoon if you skip them

The README has three important notes about the environment, and each one corresponds to a failure that is hard to diagnose from the symptom alone.

The first is that CPU scaling events could affect daemon streams causing unexpected distortions, and there is a section of notes and scripts about it. A governor that changes the clock frequency mid-stream is exactly the kind of thing that produces a stream that is intermittently broken, and on a modern system the default scaling behaviour is not what an audio device wants.

The second is a kernel change. Starting from Linux kernel 5.10.x onwards, a change in a kernel parameter is required to fix a problem with the round robin scheduler causing the latency test to fail. The project links the section on real time scheduler throttling for the detail. In other words, on any current kernel you will not get a passing latency test until you make that change, and the README does not hide that.

The third is that PulseAudio must be disabled or uninstalled for the daemon to work properly, with a section on PulseAudio and scripts notes. That is the one that surprises people, because PulseAudio is the default sound server on most desktop Linux distributions and it takes exclusive control of the ALSA device, which is exactly what a virtual ALSA device with PTP clocking needs to do.

Taken together the three notes say something about the class of software this is. It is not a desktop application that runs alongside your music player. It is infrastructure that takes over the audio path on a machine, which is why the README insists on a real machine rather than a virtual machine.

Editorial conclusion

Adopt the AES67 Linux Daemon if you need to bridge professional audio between a Linux machine and an AES67 network, and you are willing to load a kernel module and disable PulseAudio. Do not adopt it for general audio routing or as a virtual sound card for ordinary desktop use, since the whole design is a broadcast interoperability device. Before you build it, read the prerequisites carefully, because the daemon needs a kernel of at least 4.10, a C++17 compiler, boost, Avahi and libfaac, and the README also insists on a real machine rather than a virtual machine, and on PulseAudio being disabled.

Frequently asked questions

What does the AES67 Linux Daemon actually do?

It is a Linux process that uses the Merging Technologies ALSA RAVENNA/AES67 Driver to handle PTP synchronisation and RTP streams, and exposes a REST interface for configuration and status monitoring. The driver implements a virtual ALSA device clocked by the PTP clock, with Sources that read from playback and send RTP, and Sinks that receive RTP and write to capture.

How do I build and start the AES67 Linux Daemon?

Clone with `--recurse-submodules` or run `git submodule update --init --recursive`, install packages with ubuntu-packages.sh, then run build.sh, which checks out and patches the RAVENNA/AES67 module, builds the WebUI and the daemon. Load the module with `sudo insmod ./MergingRavennaALSA.ko` and start the daemon with `./aes67-daemon -c daemon.conf` after setting interface_name in the config.

What are the system requirements for the AES67 Linux Daemon?

Ubuntu 18.04 or later on ARMv7 or x86 with no virtual machines, a Linux kernel of at least 4.10.x, GCC 7.x or clang 6.x or newer with C++17, cmake 3.7 or newer, boost 1.65 or newer, Avahi 0.7 or newer if service discovery is enabled, and libfaac 1.30 or newer if the streamer is enabled.

Why do I have to disable PulseAudio to use the AES67 Linux Daemon?

The README states that PulseAudio must be disabled or uninstalled for the daemon to work properly, and links a section on PulseAudio and scripts notes. The daemon's virtual ALSA device is clocked by PTP and needs control of the audio path, which conflicts with a sound server taking exclusive control of the ALSA device.

Official sources

  1. bondagit/aes67-linux-daemon on GitHub
  2. Issues
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bondagit-aes67-linux-daemon.svg)](https://hysenlabs.com/projects/bondagit-aes67-linux-daemon)

Was this useful?