Docker
Run the recorder in a container on any laptop — Windows, macOS or Linux — without installing Python, portaudio or any build toolchain.
The image contains the recorder (the device side): bark-monitor,
bark-monitor-lite and bark-monitor-cloud-record. The hosted cloud server
is a separate thing and is not part of this image.
The catch with containers is the microphone: docker cannot hand a mic to a
container on Windows or macOS. The image solves this the same way the snap
does on Linux — the recorder records through PulseAudio, and PulseAudio can
travel over the network. Inside the container ALSA (what pyaudio talks to)
is routed to a PulseAudio server, and the container connects to a PulseAudio
server running on your laptop (PULSE_SERVER).
recorder → pyaudio → ALSA → pulse plugin → PULSE_SERVER=tcp:host.docker.internal:4713 → PulseAudio on the laptop → microphone
Build the image
From the repository root:
docker build --build-arg BARK_MONITOR_VERSION=$(git describe --tags 2>/dev/null || echo 0.0.0) -t bark-monitor .
The version normally comes from git, which a docker build cannot see, so it is passed as a build argument instead.
Give the container your microphone
You need a PulseAudio server on the laptop listening on TCP port 4713.
macOS
-
Install and start PulseAudio:
bash brew install pulseaudio pulseaudio --daemon --exit-idle-time=-1 \ --load="module-native-protocol-tcp auth-anonymous=1" -
The first time a recording is made, macOS must let the pulseaudio daemon use the microphone. If nothing is captured, open System Settings → Privacy & Security → Microphone and make sure
pulseaudiois enabled.
auth-anonymous=1lets any client that can reach port 4713 use your audio. Fine on a laptop behind a firewall at home; on a shared network tighten it withauth-ip-acl=127.0.0.1;192.168.65.0/24(the range Docker Desktop uses to reach the host).
Windows
- Install PulseAudio for Windows
(or
choco install pulseaudio) and runpulseaudio.exefrom the installation folder. -
Load the TCP module so the container can reach it:
bat pactl.exe load-module module-native-protocol-tcp auth-anonymous=1 -
Allow
pulseaudio.exethrough the Windows firewall when prompted, and make sure the microphone is enabled for desktop apps in Settings → Privacy & security → Microphone.
Linux
You can use the same TCP setup (start pulseaudio with
--load="module-native-protocol-tcp auth-anonymous=1", or load the module
in paprefs), but mounting the desktop's existing socket is simpler and
works with PipeWire too:
-e PULSE_SERVER=unix:/run/pulse/native \
-v "${XDG_RUNTIME_DIR}/pulse/native:/run/pulse/native:ro"
Run the recorder
The always-on way (recommended)
The shipped docker/compose.yaml runs the cloud recorder as a
service — the Windows/macOS counterpart of the snap daemon on Linux:
docker compose -f docker/compose.yaml up -d
On first start the container has no pairing yet, so the recorder starts the pairing wizard on port 8753 and prints its URL in the logs:
docker compose -f docker/compose.yaml logs
Open that URL in the laptop browser, paste the pairing code from the
dashboard, and recording starts — restart: unless-stopped brings it
back after reboots and Docker Desktop restarts. Nothing to write by
hand: the config file is created on first run and everything (config,
device id, recordings) lives in the mounted ./config folder.
The one-shot way
Prepare a folder with your config.json (see
the configuration file) and an
empty folder for the recordings, then:
docker run --rm -it \
-v "$(pwd)/config:/config" \
-v "$(pwd)/outputs:/outputs" \
bark-monitor
The default command is bark-monitor --config-file /config/config.json —
set output_folder in your config.json to /outputs so the recordings
survive the container. The same container runs any recorder entry point by
naming it after the image:
| Command | What it runs |
|---|---|
| (default) | bark-monitor — telegram bot + recorder |
bark-monitor-lite --config-file /config/config.json |
the TFLite recorder, for weaker machines |
bark-monitor-cloud-record --config-file /config/parameters.json |
record to the hosted cloud, controlled through the cloud bot (creates the config on first run) |
bark-monitor-cloud-pair ... |
pair the device with a cloud (interactive, needs -it) |
For the always-on cloud recorder, use the shipped
docker/compose.yaml
— see the always-on way above.
Test the microphone
Before pointing the real recorder at it, check that audio actually reaches
the container — this records 5 seconds from the same path the recorder uses
and writes them to outputs/test.wav:
docker run --rm -it \
-v "$(pwd)/outputs:/outputs" \
bark-monitor arecord -d 5 -f S16_LE -r 16000 /outputs/test.wav
Play outputs/test.wav on the laptop. If it is silent:
parecord /outputs/test.wavinside the container talks to PulseAudio directly, skipping the ALSA layer — if that works butarecorddoes not, the ALSA-to-PulseAudio routing (/etc/asound.confin the image) is the problem.pactl list shortfails: the container cannot reach the PulseAudio server — check that the daemon is running on the laptop and that port 4713 is not firewalled.- The host PulseAudio is reachable but no sound: check the macOS/Windows microphone permissions above.
Troubleshooting
ALSA lib pulse.c: ... Connection refused— the container cannot reach the PulseAudio server. On Linux with the TCP setup, add--add-host=host.docker.internal:host-gateway(or use the socket mount, which avoids networking entirely).OSError: [Errno -9985] Device unavailablefrom pyaudio — audio reached PulseAudio but there is no input source; check the mic permissions on the host and that the right input device is selected.- Recordings owned by a wrong user on Linux — the image runs as uid
1000; run with
--user $(id -u):$(id -g)if that does not match you.