Snips is currently native only on Debian based systems (ARM and X86). But thanks to Docker and the Open Source project PulseAudio, it is relatively easy to talk to Snips on OS X as well. There is already an official image for the Snips platform on Docker Hub, but this does not work on macOS without any hassle. Docker for Mac does not allow you to pass audio devices through, because on macOS, the Core Audio API is used to access such devices. This is where PulseAudio comes into play: PulseAudio is natively available on macOS and offers a network mode for streaming audio input/output on the network. In the following I will show you the necessary steps to run the Snips Audio Server (which is the interface between the Snips Platform and your audio devices - i.e. microphone and speaker) in Docker on OS X and to run your Mac as a Snips satellite. In the following showcase I have my Snips main unit running on an Raspberry Pi 3 with a basic assistant installed.

This is what you will have at the end of this blog:

Installing and Running PulseAudio

The awesome Homebrew makes it easy to install PulseAudio. I assume you already have Homebrew in use - otherwise you should make up for it urgently. After the installation we start PulseAudio in daemon mode and load the module module-native-protocol-tcp, which is responsible for network audio streaming.

To check the found audio devices, use pactl. I have connected a USB headset besides the built-in microphone and speaker. So I'm sure your listing can vary.

A customized Docker image

The Dockerfile is initially based on the installation instructions of Snips on Debian. We will additionally install the packages for PulseAudio and set up a user to be assigned to the corresponding PulseAudio groups. Then the configuration for Snips and for the PulseAudio client is copied into the image and finally the Snips Audio Server is started. The Dockerfile has an intentionally simple structure. I am aware that various things can be improved and also parameterized.

The configuration of Snips is to be found in the snips.toml file and must be adjusted if necessary. Adjust the IP of the MQTT broker used by Snips in this file - typically running on your Snips main unit. If you like, you can also customize the bind name for your macOS device. You just have to make sure that this name is registered on your main unit later. More about this later on.

Since this configuration is "baked" into the image, it must be happen before the following Docker build. Simply run the Docker build and tag the image, e.g. snips.ai/audio-server.

Let's give it a shot. Start the newly built container - but note that we're passing two additional flags! The PULSE_AUDIO environment variable is to be set to the IP of your macOS host. This is the IP where the PulseAudio client in the running container connects to for audio streaming. We also mount the host directory ~/.config/pulse to /home/pulseaudio/.config/pulse in the container. This directory contains user defined pulse configuration. The most important - at least to my understanding - is the cookie file, which must be identical to that of the server. Which is the case here, since we mounted it from the Docker host which is the same as the PulseAudio server.

Configure PulseAudio service to run on login

If you want to run PulseAudio on startup or login you have to provide a launchd configuration. Fortunately Homebrew provides a feature called service, which seamlessly integrate into macOS launchd service management framework. First, the PulseAudio start parameters specified above must be translated to a launchd configuration. This is done in a so-called .plist file - for PulseAudio it is located in the directory /usr/local/Cellar/pulseaudio/12.x. Replace the content of the file homebrew.mxcl.pulseaudio.plist.xml with the following snippet and run brew services start pulseaudio to start the service and register it to launch on login.

I have checked the project for creating the container image into our Gitlab instance. Feel free to use it as a basis for your own image. To activate Gitlab's CI/CD pipeline, a .gitlab-ci.yml is also available. Our internal build infrastructure for container images is based on Makefiles. But finally Gitlab builds the container image as described above. Furthermore, the built image is available in our Docker registry: docker pull registry.smb-tec.com/snips.ai/audio-server - which you can also browse from within Gitlab.

unsplash-logoSabri Tuzcu

Lars Martin

I have been developing software for 20 years - mostly on the basis of the JVM. In the recent past I've been doing a methamorphosis towards polyglot projects. In my spare time, I enjoy Smart Home and Home Automation.

Blog Comments powered by Disqus.