Email or username:

Password:

Forgot your password?
Hailey

Introducing Bark! Low-latency multi-receiver live-sync lossless audio streaming for local networks. It's like Sonos, but open source, so nobody can brick your devices remotely. It's also written in Rust :)

github.com/haileys/bark

It sends 48khz uncompressed float32 data over UDP multicast. It can achieve playback sync to within hundreds of microseconds in ideal conditions, and usually to within a millisecond.

I've been working on it in my spare time over the past week, and I'm pretty happy with how it's shaped up. I have three receivers setup and it works remarkably well at keeping everything in sync as I walk around my house. For now it only really works on Linux, and supports Pipewire (and Pulse in theory), but there's no huge impediment to making it truly cross-platform.

It also features a fancy live stats subcommand, which can used on any computer in the same multicast domain to watch the status of the stream cluster:

A screenshot of the `bark stats` command on my local network. The command reads from ~/.config/bark.toml, and then shows each node in the cluster.

There are three receivers, and they are all fairly in-sync with each other, all within a millisecond. There's some other stats too, showing how much audio is in the buffers, the network latency, and the clock prediction offset.
133 comments
Jeremy Kerr

@hailey this looks fantastic! Is there a repo where I can have a go / experiment / contribute?

Hailey

I realised I forgot to put a link in the original post lol so I have edited it, but here is the link in case: github.com/haileys/bark

mlp

@hailey have you seen Roon Labs RAAT - it is quite popular in hifi circles and has pretty good list of supported network streamers/dacs/amplifiers. Would be nice to have compatible opensource implementation help.roonlabs.com/portal/en/kb

Hailey

it is so so so cool to hear some music playing in my lounge room, and then on my desktop run `systemctl --user start bark-receive`, and hear the exact same thing out of my computer speakers.

The stream source is hooked to line-in on the lounge room server, so it can cast to the network anything playing from my cheap little spotify/airplay/bluetooth/etc stream box, or the Apple TV, or my FM radio even.

The latency added by Bark is basically imperceptible too!

:prideflag_demigirl:​:texmoji_ko_nonbinoko:​서버메이드 깐프

@hailey next level: Hack sonos to install Bark in it. (IMO, it seems possible unless they blown up secure boot fuses)

Anyway, Thanks for the software.

I'll try to cross compile it into mips-unknown-linux-musleabi and run it in my old smart speaker (ReSpeaker gen1)

Martin Whitaker

@hailey this does sound like an ideal solution for multi room audio. Thank you!

Have you tried it on a raspberry pi? If so does it work okay on the pi?

Hailey

@martin I have not, but I imagine it would work fine! it doesn't use that much CPU on the mac minis I have it running on right now

Martin Whitaker

@hailey I'll have a play and let you know!

It's hard to believe there isn't a standard already defined for this purpose... Thanks again for coming up with it!

Fixstern

@hailey is that all ethernet devices? How does wifi do? How big is the jitter buffer/input latency? The project sound exactly what i was searching earlier! Thanks for sharing!

⚳ rapid unscheduled assembly ⚳

@dunkelstern @hailey Wifi does _terribly_ since it'll be stuck at 6 Mbit/sec max

jaxter184

@hailey this looks really great! what are you using for your devices?

Hailey

@jaxter184 other than my desktop, the receivers are a couple of old 2012-ish mac minis I had lying around which I installed arch linux on for this

Tommy Thorn

@hailey @jaxter184 UDP should make it fairly easy to whip up a microcontroller receiver

jaxter184

@tommythorn @hailey yeah, i originally asked because i had vague desires to make a PoE AES67 speaker, but i got bogged down in the research. just a little ESP32 with regular UDP messages seems much more reasonable.

Tommy Thorn

@jaxter184 @hailey The #RISCV based, #Rust focused ESP32-C3-RUST-1 dev kit should be coming from @adafruit in a few days. That ought to be a good target (not that I will have time to pursue this).

jaxter184

@tommythorn @adafruit is the ESP32-C3 not already available? I'm pretty sure ive had one laying around somewhere for like a year at least

Tommy Thorn

@jaxter184 @hailey @adafruit The board arrived and it *literally* took me 9 min from I sat down with the board until I had read the instructions [1], installed the software, and run the Hello World. This is great.

Slightly puzzled about the SHA-256 checksum warnings that show up.

[1] esp-rs.github.io/no_std-traini

Picture of the tiny Espressif ESP32-C3-DevKit-RUST-1 dev board attached to a USB-C cable
The terminal output from the 1st run of a Hello World workload on this board
s0: Soldering Sorceress

@hailey that’s super neat. I really wish there was better AES67 & PTP support in Linux, because all this stuff done closed-source in a pro audio could come across to open source and consumer network stuff so easily. One day I’ll have time to work on it.

Hailey

@s0 I borrowed some ideas from PTP in this at least!! :)

s0: Soldering Sorceress

@hailey nice :) I use MoOde Audio on a raspberry pi at home for a web interface to play back audio on my Hifi, this seems like something that would be great to add into that project for multi-zone audio, instead of relying on reverse-engineerings of airplay and Sonos protocols with so many layers of subtle bugs and compatibility problems…

Dickenhobelix

@s0 @hailey Linuxptp and Pipewire-aes67/gstreamer work reasonably well, you might want to take a closer look at it

s0: Soldering Sorceress

@dickenhobelix @hailey a year ago I couldn't get linuxptp to work at all, but I admit I haven't tried again recently.

Dickenhobelix

@s0 @hailey I use it for several projects at work, and it's probably the most mature PTP stack I have encountered so far. Fiddly to parameterize, but it works quite well. Get in touch if you have any specific questions

s0: Soldering Sorceress

@dickenhobelix @hailey that's very good to hear. I also work a fair bit with Dante & AES67 at work and have various projects where interop with regular audio stack would be great.

Dickenhobelix

@s0 @hailey Dante is...well, special. Also Audinates's AES67 Implementation has had several Issues when I looked at it several years ago. But then I changed my employer and did not have access to the stacks, documentation and devices... Maybe stuff has improved since back then.

If you care about Interop, I'd recommend to also have a look at Milan (that's basically an Interop Layer for AVB). Though, I am absolutely biased, because I coauthored some of the specs back in the day...

Hailey

@dickenhobelix @s0 Is there a particularly good guide or other documentation you'd recommend to learning how to configure it properly for any given site? It looks great to learn from, and I think lifting its best ideas into bark's userland stack could be a cool idea

Dickenhobelix

@hailey @s0 One of the best resources that immediately comes to mind is Maciek's talk at netdev 0x16 youtu.be/Hs7oRukMuak

The difficult thing about linuxptp is that you need to have quite a bit of knowledge about IEEE1588 or IEEE802.1as to tweak all of knobs correctly. It's a good stack, but not quite user friendly

Dickenhobelix

@hailey @s0 Ah, and one more important thing: until v4 linuxptp released new versions only ever 4 years or so, which is why most distros have terribly old versions with a few annoying bugs. Make sure to use at least v4 (they release bi quarterly starting with v4 afaik, but I don't know how long it will take Debian to pick up the latest versions). Most convenient way is to build from source...

Tommy Thorn

@hailey I haven’t looked at the source but surely sending audio from macOS should be easy enough. It doesn’t have to be integrated with macOS audio to be useful (could pipe directly from mp1g123 say)

Pepijn Bruienne

@hailey @tperfitt This reminds me of the (closed source, commercial) Skaa tech - skaastore.com/pages/aboutskaa or (very pricy) Dante - audinate.com/meet-dante/what-i. Very cool to see an OSS take on this! How well does this perform on wireless?

Hailey

@bruienne @tperfitt it is surprisingly ok on wifi! I wouldn’t rely on it, it’s too unreliable a transport, but it does work a lot better than I thought

Joel VanderWerf

@hailey Sounds a bit like snapcast, which I've been using for multiroom audio for a year or so. (Snapcast was kind of hard to set up, but that may have been more about my devices and network.) Is Bark comparable, or aiming for something different?

Hailey

@joelvanderwerf I tried snapcast but it kept segfaulting on me so I just wrote my own!

Analog Alex π

@hailey that's impressive, i look into it with joy 💜🎵

Stefano Marinelli

@hailey Well done! It looks like a very nice solution, I'll try it.

Andrew Harvey

@hailey This is cool. I’ve been looking at this stuff (along with AES67, Livewire, Dante, and friends.

Hailey

@andrewharvey I briefly looked at that stuff but in classic programmer fashion it didn’t make immediate sense to me so I just wrote my own lol

cλémentd

@hailey Nice!

I've done that with VLC in the past, but it wasn't ideal.

Electronic Eel

@hailey this looks interesting.

How do you deal with long-term clock drift between your receivers? Is there some logic to resample the audio to match the clocks or do you wait until the buffer over/underflows and then jump?

Hailey

@electronic_eel yes it uses the speex-dsp resampler and it will slew to resync for small offsets, and jump for large discontinuous offsets!

Electronic Eel

@hailey nice!

do you have plans on integrating it somehow with mpd?

I'd be especially interested in a way to use mpd to select on which devices I want to output audio. mpd has the concept of "audio_output" and most mpd clients allow you to control them.

Hailey

@electronic_eel no special integration needed! You can create a virtual duplex device in both Pipewire and Pulse, configure mpd to play to that device, and bark to capture from that device - see the readme for more info

Electronic Eel

@hailey yeah, but the issue is the multi-room control via mpd audio_outputs if I'm not mistaken.

To control which rooms should be enabled from within mpd, I need multiple audio_outputs in mpd, some are enabled and some disabled. Now these should integrate again into one bark stream to allow it to do it's multiroom magic. Or maybe some other logic to check which rooms are enabled in mpd.

This would allow me to use the many different mpd clients to control the whole stack: playlist, song, volume and rooms.

@hailey yeah, but the issue is the multi-room control via mpd audio_outputs if I'm not mistaken.

To control which rooms should be enabled from within mpd, I need multiple audio_outputs in mpd, some are enabled and some disabled. Now these should integrate again into one bark stream to allow it to do it's multiroom magic. Or maybe some other logic to check which rooms are enabled in mpd.

Hailey

@electronic_eel I see! You could achieve this by creating separate virtual devices and running multiple bark stream processes using separate multicast groups for each speaker. You'd lose the benefit of multicast, since you'd essentially be unicasting to each speaker (but in a roundabout way via multicast), but the actual synchronisation runs according to CLOCK_BOOTTIME on the source host, so provided all stream sources are running on the same machine the sync would work.

Electronic Eel

@hailey ah, cool!

I don't care about network bandwidth as all sinks have direct ethernet cables to one switch. So unicast or multicast doesn't matter for my application.

I think I will give bark a try soon.

CEO of Anti-Clock Society

@hailey @electronic_eel speex-dsp for resampling is an interesting choice. Why use a C library over Rubato?

danstowell

@hailey Congratulations. Have you made a feature comparison with Snapcast? mjaggard.github.io/snapcast/ I've tried that recently and it's nice, though it doesn't play well with laptop sleeps

Hailey

@danstowell thank you! I tried snapcast but had some issues getting it working. Some segfaults, but also annoyances setting up the pipes - that’s why bark takes a device based approach with pipewire/pulse. Bark uses CLOCK_BOOTTIME instead of CLOCK_MONOTONIC, so it should be ok with sleeps at least in that respect, but tbh I haven’t really tried it

jstsmthrgk

@hailey I wonder how easy it would be to implement the receiving end on an ESP32...

Stfmani

@hailey
Nice !
Perhaps it could be a good addon for #kodi

rfnix

@hailey That sounds super cool!

This is UDP so you don't get ACKs, right? Is the network latency determined with a backchannel of some kind that feeds back receiver timestamps to the source?

Any idea how usable/stable it can be between two hosts that are not on the same LAN?

CEO of Anti-Clock Society

@hailey using cpal for audio IO and environment variables for specifying PulseAudio or Pipewire devices is an interesting design. Do you plan to support other OSes? If not, why not use the PipeWire or PulseAudio bindings directly?

Hailey

@be yeah that part is a total hack tbh. I would like to keep it cross-platform ready, and cpal doesn’t (yet?) expose an API for selecting a particular pipewire or pulse node

CEO of Anti-Clock Society

@hailey cpal has neither a Pipewire nor Pulseaudio backend, only ALSA and JACK. Is that why you need pipewire-alsa installed?

Morten Mosgaard

@hailey awesome project! Great to hear how well it works.

CEO of Anti-Clock Society

@hailey AFAIK Pipewire has been lacking a solution for networked audio, so this is neat!

jasmin

@hailey wanna try it, just because of it's name :D

chaos ΘΔ& (it/he)

@hailey how does it compare to ROC in less than ideal conditions?

Eleanor Saitta

@hailey
What does this get over the open source aes67 implementation?

Eleanor Saitta

@hailey
(Asking because I've got a fair bit of Dante hardware, but alternatives are always interesting)

gaytabase

@hailey very cool. i had this on my todo list heh, so thank you for saving me the effort

epso 🦀

@hailey@hails love the sound of this, thank you! Gonna check it out.

DELETED

@hailey going to give it a try and thanks for your hard work

kflanagan

@hailey First thing that came to mind is that a Pi with speakers attached would be a good place to start for this. It's not the super spacial thing, but just to have decent sound around the house would be good.

DasFaultier

@hailey Sry, I'm new to this, so can you please confirm/correct?
You throw a bunch of Linux machines with speakers attached into your network, configure them all as sinks, they become visible on your source machine (e.g.Desktop PC), you connect them via CLI and audio transmission happens over Bark then? Is it really as easy as that?

DELETED

@hailey woah. I spent 3 months of weekends on a project pretty much exactly like this for an internship a few years ago, and you did it in a week? That's awesome!

The one thing I couldn't get right was packet ordering. The audio always came out garbled, I was using a handmade data structure that acted as a ring buffer that inserted packets based on a packet count. Will for sure be looking through your implementation :)

flaeky pancako

@hailey super cool project! I am still building my house out but this would be super great to have for house music!

Antoine Martin

@hailey Thank you! I'm looking for ways to get off Volumio. This gets me closer to that.

Byte

@hailey wait what’s that about Sonos remotely bricking things

Daniele

@hailey interesting! Thanks for sharing :)

aZa

@hailey thats amazing!

I'm wondering: would you be able to stream audio to the streambox, which in return distributes it to the speakers/computers?

That would be insane!

dressupgeekout 🦓

@hailey Up until a few weeks ago I was working at a company that made products with exactly this. Not Bark (heh) but we worked on multi-room and in-room audio sync stuff. So I know what it really takes to get something like this off the ground. So this Bark project is super commendable!

I had always imagined a BETTER-ENGINEERED and more lightweight solution had always existed, but I never saw it, because our codebases at work had literally decades of historical baggage and other crap on top. Maybe Bark is the answer.

@hailey Up until a few weeks ago I was working at a company that made products with exactly this. Not Bark (heh) but we worked on multi-room and in-room audio sync stuff. So I know what it really takes to get something like this off the ground. So this Bark project is super commendable!

I had always imagined a BETTER-ENGINEERED and more lightweight solution had always existed, but I never saw it, because our codebases at work had literally decades of historical baggage and other crap on top. Maybe...

Jamie Booth

@hailey
@Incognitim

Now, we need Meow! where the sound randomly comes out of a speaker for a few seconds leading you on a wild goose chase to figure out what the sound is.

Aires

@hailey This is awesome! I haven't used multi-output network streaming since the early PulseAudio days, so it's cool to see work being done to make the experience even easier/better!

Bouke van der Bijl

@hailey super cool. Turns out you can do really neat things if you synchronize clocks well!

Mikołaj Hołysz

@hailey I’d love to have the receiver part of something like this on a phone. Bluetooth audio has really high latencies, which sucks for e.g. using a computer with a screen reader, which is my primary use case here. Currently, the solutions are dedicated gaming wireless headphones (expensive, require a dongle and often shady / barely accessible software), or 10 feet of audio cable, which is the solution I’m using right now.

💉💉💉🦠JF :debian: :verbike:

@hailey
Looks very interesting. What does it need (hardware? Which kind of raspberry is enough to run it?)

Simon Eickhoff

@hailey this sounds great! Thanks for your work!

AstraLuma :blobfoxcomputer:

@hailey oh that's very cool!

I think I'm going to have to experiment with this later. Maybe combined with one of the web music UIs

Piotr Gaczkowski

@hailey out of curiosity: have you heard about OpenHome? It's based on UPnP which is kinda problematic, but I wonder how it compares to your solution.

monoxane

@coregaze Multicast is usually the best way to handle stuff like this, it's not so much an issue with just audio in a home environment but in larger live sound or broadcast environments everything is multicast, a single source often needs to be received by multiple devices at once and in sync so the bandwidth savings of multicast outdo the disadvantages of managing it. Things like PIM Sparse make it drastically more functional than just relying on IGMP doing the right thing all the time.

⚳ rapid unscheduled assembly ⚳

@monoxane The fact that multicast does not work at all on wireless makes it a massive problem. Many wireless adapters will send every multicast/broadcast frame three times, at the lowest basic rate (either 1 Mbit/sec or 6 Mbit/sec, depending on whether it's 2.4 or 5/6 GHz), because multicast/broadcast frames cannot be acked and therefore rate control cannot work on them and neither can retransmits.

This makes trying to do uncompressed audio over multicast impossible if wireless is present.

monoxane

@coregaze Oh yes you are absolutely correct there, multicast over wireless is definitely a very bad idea and no one should ever do it. But in general it has its place.

⚳ rapid unscheduled assembly ⚳

@monoxane ...and most home networks include wireless. Most notably, Sonos (which @hailey compared this to) does not transmit audio content over multicast, only synch information, which is how come it actually works over wireless networks.

Rudi (ryjelsum)

@hailey this is something i've been looking for, i'll have to give it a test! i have a google onhub wireless router which has a pretty beefy speaker built in (for some reason, the stock firmware barely uses it) and, like you mentioned to someone else, i tried snapcast but had serious issues getting it working on openwrt, and networked pulse wasn't cooperating with me either, since i don't use pulse when i can help it..

Andy Davidson
@hailey @max Bark! is such a great idea, I hope that some other nerds embed it into some music source clients and neat speaker devices. Thanks for making it.
Sean Mollet

@hailey this is awesome! Thanks, I’ve been wanting an audio distribution system in my office for a while, now I know how I’m spending next week.

Joshua Barretto

@hailey Oh, this is *extremely* cool. My house has very solid walls and my bluetooth headphones don't work in different rooms as a result. I've been looking for a setup where I can stream audio from my PC to my phone via WLAN for a while, all existing approaches I've found have pretty big deficiencies. Out of interest, do you know of a simple route to getting a client working on Android, or is it a custom protocol?

Kos

@hailey
Ooh that's an important problem to solve, thanks! As much as I like my sonos products, their vendor lock-in is nothing less than scary 🤐

David Swegen

@hailey I'm curious how this compares to logitech's squeezebox system. Both server and (software) client are open source too.

Matthew J

@hailey bloody hell that's amazing. I'm not super linux techy but if this ever hits windows I'm gunna be on it like a fat kit on a smarty

Oook

@hailey weren't you looking for something similar a while ago @solene ?

Neil Brown

@hailey I am *so* looking forward to giving this a try when I get a spare moment!

Brad Barrish

@hailey super cool! I worked at Sonos for 6+ years. Still love their gear, but hate that perfectly good gen1 speakers are a lot less useful now.

Brad Barrish

@hailey shared in the Sonos alumni Slack as well 😀

Maxime Borges @ Berlin

@hailey I've been using ROC toolkit at my hackerspace with a similar goal in mind. I started porting it to Rust but never finished it. The nice thing is that it is using a correction channel by default to avoid glitches, which is quite simple to implement in Rust with the available libraries, it's worth looking at it. It's also already available in pipewire.

αxel simon ↙︎↙︎↙︎

@hailey This is very cool! Out of curiosity, does it share design ideas (or more) with Snapcast? github.com/badaix/snapcast/ I don't think Snapcast can get to such small sync delays, but it works fine for syncing music.

jacqueline 🌟

@hailey think about it... what if lossed packet is okay. and less bandwidth.

Willow :trans_flag:

@hailey@hails.org Holy shit, this is awesome. Do you have to use any fancy networking support, like any of the time-sensitive networking extensions?

DELETED

@hailey cabbit mention spotted :3

cool project! much better than pulse tcp

Steve England

@hailey This looks really cool, I have used snapcast in the past but always found the manual sync adjustments tricky to get right

Mikey Dickerson

@hailey this sounds amazing, I have been looking for years for some way to recreate this technology that I had in 2002 "squeezebox" device

James M. Woodward

@hailey This looks fantastic. Can you elaborate on any particular differences between your project and github.com/badaix/snapcast?

DRMR

@hailey How does it compare to snapcast? (which we are currently using at our hackerspace) And I don't just mean the "it's written in Rust" part :)

Ian

That sounds super cool! Thank you @hailey!

národní prase
@hailey what devices would you use for the speakers? im imagining RPIs but it sounds amazingly wasteful (energy use and also expensive)
monoxane

@hailey Ah yes, XKCD 927'd AES67/ST 2110-30 😜

Nah that's pretty cool, not needing PTP is very nice for a home environment where clocking multiple sources isn't necessary, how are you handling clock recovery and the potential for out of order or delayed packets? Just by reconstructing the stream by timestamps from a buffer of incoming data or something spicy?

fedithom

@hailey that looks absolutely rad! I'll check it out, when I find the time.

Bart Nijbakker

@hailey I have been looking for exactly this! Will check it out.

Go Up