owntone / owntone-server

Linux/FreeBSD DAAP (iTunes) and MPD audio server with support for AirPlay 1 and 2 speakers (multiroom), Apple Remote (and compatibles), Chromecast, Spotify and internet radio.
https://owntone.github.io/owntone-server
GNU General Public License v2.0
2.07k stars 236 forks source link

Airplay 2 Enhanced Audio Buffering #1577

Closed hoiz closed 1 year ago

hoiz commented 1 year ago

Hello! OwnTone is the heart of my multiroom solution. All my receivers are now Airplay 2 capable but I still have some dropouts. Therefore it would be great if OwnTone would support the Enhanced Audio Buffering of Airplay 2. As far as I understand, larger audio segments are sent to the clients in advance and then the playback position is synchronized. See https://devstreaming-cdn.apple.com/videos/wwdc/2017/509v96e4gd96rlqyq/509/509_introducing_airplay_2.pdf for details. Since it is supported by the latest versions of Shairport Sync, I assume that the protocol is reverse engineered by now.

I understand that this is a bigger issue, because audio data can only be sent in advance if it is also known to OwnTone in advance. So all realtime streams and pipe solutions actually are out, or large latencies are added. The best solution would be to integrate librespot or similar directly, so that the complete audio stream can be accessed.

I know, lots of stuff. What are the chances of such an enhancement?

ejurgensen commented 1 year ago

Thanks for your suggestion, good to hear you enjoy OwnTone. Actually, OwnTone already sends the audio in advance. It did this already with Airplay 1. The buffer is about two seconds, which is why there is a delay when starting your music. Internally, OwnTone will also read the source ahead by quite a bit more (except sources like http streams, which can't be read ahead).

The two seconds give the speaker enough time to detect missing packets and request them to be resent. Without having looked at your link, I think what Apple did with Airplay 2 was adding methods to dynamically buffer, so that Airplay could also be used in situations where a two second delay is not an feasible. I'm not so much into those methods, however.

The bottom line is that I think the dropouts you have could be due to something else. If you set the log level to debug, you can check in the log if the dropouts are associated with log messages that say "Got retransmit request from...". That means that the speaker is missing audio packets.

There are other possible reasons, but they are more difficult to troubleshoot.

hoiz commented 1 year ago

Thanks for the quick and detailed reply. The enhanced audio buffering is Apple's ideal vision of multiroom audio. It's supposed to be more robust and (if enough buffering has been done) also it should react faster to position changes in the stream. It also now supports formats like AAC or mp3.

Because changes have to be made to the apps, this mode is not yet widely supported, though: Apple's own Music app uses it, but Spotify, for example, still uses the so-called "AP2 Realtime Audio Stream" mode. (With the log of Shairport Sync, you can easily see which mode is used for streaming).

I'll have a look at the logs to see if the dropouts are associated with this message.

hoiz commented 1 year ago

Sorry, a few more questions for clarification:

  1. You write:
    [...] OwnTone will also read the source ahead by quite a bit more (except sources like http streams, which can't be read ahead).
    I currently use OwnTone only with radio streams and Spotify Connect via pipe. So this way I can't have the robustness that is theoretically already possible, right?
  2. Would I have that robustness with the built-in Spotify integration?
  3. If so, can't Spotify Connect be supported directly as well? I know there's a separate issue for that, but that's more focused on pipe integration for a while now. Don't get me wrong. I have great respect for your volunteer work and it's most likely due to lack of time. I just want to understand the boundaries of OwnTone.

Thank you very much!

ejurgensen commented 1 year ago

I currently use OwnTone only with radio streams and Spotify Connect via pipe. So this way I can't have the robustness that is theoretically already possible, right?

That was an important detail. With those sources OwnTone can run out of data to read (e.g. due to clock differences between OwnTone and the source), and the log (normal log level) will say something like "Source is not providing sufficient data, temporarily suspending playback".

Would I have that robustness with the built-in Spotify integration?

Yes, the built-in integration reads ahead by quite a lot. As I remember it builds a buffer of maybe 10-20 MB.

If so, can't Spotify Connect be supported directly as well?

It could, just haven't done it. The current Spotify solution meets my own needs, but I acknowledge that it would improve the WAF a lot if Connect was supported.

hoiz commented 1 year ago

Thanks for the clarification! I saw that you wrote a C implementation of librespot. So I understand that it takes some effort to support Spotify Connect as well.

One last question about this because I'm curious: I'm a complete layman in this area, but some quick googling showed me that it is theoretically possible to call Rust functions from C code. Could librespot also be used directly if it offered C bindings?

ejurgensen commented 1 year ago

That was actually my initial plan before I wrote the C version, but despite quite some attempts I couldn't make it work properly. Contrary to the name, librespot isn't really a library. Also, I'm not too strong with Rust.

It would also have made installing OwnTone more complicated. Distribution of librespot with OwnTone isn't straightforward, and it's not readily available in the major distros. I think logging into Spotify would also have been more complicated for the user, because librespot doesn't support Spotify OAuth (I think...). So two logins would be required.

Then there is also the advantage of being in full control, e.g. being able to fix things when Spotify makes shenanigans, like they did some months ago.

hoiz commented 1 year ago

Thank you very much!