summaryrefslogtreecommitdiff
path: root/src/multi-room-audio.thrust
blob: 078de3c661988ca65bf946c20817100b90ddbfb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
---
title: multi-room audio
subtitle: Audio, in rooms. Multiple rooms.
date: 2020-04-08
---
{% extends 'templates/base.html' %}
{% block body %}
	<nav>
		<a href='/projects'>&gt; projects</a>
	</nav>

	<header>
		<h1>{{ title }}</h1>
		<p>{{ subtitle }}</p>
	</header>

	<article>
	{% markdown %}
	I briefly tried using [PulseAudio over the network](https://wiki.archlinux.org/index.php/PulseAudio/Examples#PulseAudio_over_network), but decided to use [Snapcast](https://github.com/badaix/snapcast) instead.
	Snapcast seems to be more tolerant of network issues, doesn't require installing PulseAudio on otherwise headless machines, and has pretty good synchronization between rooms.

	A Snapcast installation is split into one _Snapserver_ and multiple _Snapclients_.
	Audio comes in to the Snapserver from one or more sources, and is broadcast out to the Snapclients, with a minor delay for synchronization.

	On the machine being the Snapserver, install the `snapserver` package from APT, and configure its audio sources.
	This snippet configures two sources:

	- For [MPD controlled by UPnP](https://www.lesbonscomptes.com/upmpdcli/), it
	    - reads from a named pipe at `/tmp/snapfifo`,
	    - and presents it in the Snapcast UI as `UPnP`.
	- For [AirPlay](https://en.wikipedia.org/wiki/AirPlay), it
	    - starts the binary `/usr/bin/shairport-sync`,
	    - presents it in the UI as `AirPlay`,
	    - sets it to use 44.1Khz output instead of 48Khz,
	    - and logs `shairport-sync`'s stderr.
	    - `shairport-sync` itself is configured to output audio to its stdout.

	```sh
	$ cat /etc/default/snapserver
	SNAPSERVER_OPTS="--stream pipe:///tmp/snapfifo?name=UPnP --stream process:///usr/bin/shairport-sync?name=AirPlay&sampleformat=44100:16:2&log_stderr=true"
	```

	On all the machines being Snapclients, install the `snapclient` package, and configure their human-readable names.
	For example, for the Snapclient in my living room:

	```sh
	$ cat /etc/default/snapcast
	SNAPCLIENT_OPTS="--hostID 'Living Room'"
	```

	## Control

	I primarily control Snapcast using a [CatBus](/catbus) daemon.

	In addition, I have configured both `shairport-sync` and `upmpdcli` to switch Snapcast to their respective input when they start playing.
	{% endmarkdown %}
	</article>
{% endblock %}