blaa / WaveSync

Multi-room synchronised audio playback over shaky network connections and cheap (rasbperry pi) hardware.
MIT License
64 stars 13 forks source link

Android receiver possible? #5

Open tadly opened 5 years ago

tadly commented 5 years ago

I like this project for its simplicity/minimalism and think a android client would be kinda neat. Even though I don't really want to get back into android development, this could be something I might actually tackle.

Before doing so I thought I'd ask if there are any major concerns from your side. I do know python quite well and think that re-implementing the client logic in java/kotlin shouldn't be to hard (I say that without having read the code yet).

The only immediate concern I have is the whole NTP thing. On android there's no "easy" way of changing the NTP server in use. Apparently it can be done through adb but that's not really user-friendly.

Do you think it would be possible to extend wavesync in such a manner that clients´:

  1. request the time from the server
  2. given the server-time, request-time and local-time calculate an offset
  3. using the offset to reconstruct the chunks

I've never worked on anything which requires perfect synchronization so I'm not sure if there's a fatal flaw in my logic.

blaa commented 5 years ago

First thing: Would you like to stream audio from the mobile to the wavesync (to get multiroom audio controlled conveniently from mobile) - or receive the audio on the mobile and play it.

I would seriously LOVE the ability to stream from my mobile - I currently use a bluetooth dongle, capture it's output and synchronise audio using rpis - hacky. Bluetooth dongle is simpler to use for my family than mobile-controlled sound daemons - which can hook up to spotify or play local collection.

I don't have a usecase for streaming TO THE android really - but can imagine it might be useful. Both cases have different problems. ;-)

Android as a source

NTP is not problem in this case at all. System adds a delay to have enough time to synchronise audio in a laggy network. Mobile connected to any NTP should be accurate to within +/- 50ms without problems - probably better. System uses higher delay (200ms, or 1 second) - and this could be increased and work with mobile accuracy of even +/- 1s.

The problem might be with intercepting the audio stream on a non-rooted Android device - but that might have got better since I've checked it. "HiFy" app for example (not really popular) is supposed to connect spotify (not sure why explicitly that) to AirPlay. There's a "AirAudio" app - but requires root.

If accepting "root" requirement - this is certainly doable. If not - it needs some checks. It would still be usable for me with required root. It's certainly doable as a music "player" but I'm not sure you'd want to write own player; that would rather be counterproductive, it has to be simple and integrate with the environment.

I considered porting this to "termux" and staying with Python too, but there's problem with interception and audio at all.

Android could talk directly to receivers (be a wavesync server) or talk to the server (which currently talks to Pulseaudio using Unix socket - this could be changed easily) - and let the server chunk the audio.

Android as a player / receiver

The receivers need to have the time synchronised much more accurately. In local environment you could probably force NTP packets leaving on port 123 to reach your server instead. Still I believe most mobiles are synchronized to within 1-5ms and this should suffice in most natural conditions.

No problems with intercepting audio though - not sure if no problems with output buffer control.

Android control

I considered adding REST interface to wavesync server and doing a simple app to control volume in different rooms. My volume knob in kitchen is quite unreachable. I manage with SSH, my wife not really.

blaa commented 5 years ago

When receiving, the working root solution, could be to use AirAudio, do a DLNA server on pulseaudio and push audio to wavesync...

When streaming TO the android: Receivers currently receive the server time automatically every 1-second in status frame - in local network this MIGHT be just enough (pings will be usually <1ms anyway). Adding a time-ping feature is not a big problem probably, but maybe not necessary. Server currently doesn't receive data from receivers.

tadly commented 5 years ago

Thanks for the big write-up, really appreciated :)

Also, sorry for not being super clear about it but yeah, I was thinking *Android as a player / receiver". My use-case is: I have a baller HTPC setup in the living-room and a android tablet in the bathroom. As my HTPC is running all the time (and playing music), I'd love to just hit a button on the tablet and have the music playing in the bathroom as well.

The app could also include a simple control interface, that shouldn't be to big of a deal especially if you provide a nice REST interface.

As you aren't to concerned about NTP and seem to not have any other immediate concerns for a receiver I guess this will be a upcoming project of mine unless someone else wants to work on it. I have very limited private time so it's not like I have to work on this :sweat_smile:

As such I can't promise to have something to show off anytime soon. Just wanted to get an initial idea on how things might be looking :)

blaa commented 5 years ago

No prob at all. Glad you found it somehow useful. I won't be able to pickup a Android project by myself but can offer any help necessary.

Weird solutions include also https://github.com/termux/play-audio and https://steemit.com/utopian-io/@rufans/how-to-play-mp3-files-from-command-line-with-termux If mpv can do it - so could wavesync in a console with audio interface changed.