Open markferry opened 3 years ago
I would like to see the librespot-java get supported. I have just used librespot-api (it is within the librespot-java package) to replace librespot. The advantage of librespot-java is to have the cover art image and metadata available. With librespot-api, "curl -X POST http://localhost:24879/player/next , prev, pause, resume, or etc, can be sent to the spotify host app". I set up librespot-java to send output to the pipe such that I can use equaliser such as alsaequal or eqfa4p in addition to the default sound card with aplay. The aplay command line is "aplay -D eqfa4p -r raw -f cd < myLibrespot-java-pipe.raw".
It seems that there is some bigger refactoring going on with librespot (new-api branch), as you can see in this discussion, they also mention that the java implementation might be ahead in some regards:
The "new Spotify API" means moving large parts of the Spotify protocol from Mercury to HTTP. A lot of this was reverse engineered before by @devgianlu of librespot-java. It was long overdue that we started implementing it too, not in the least because new features like the upcoming Spotify HiFi depend on it.
For testing purposes I've replaced librespot
on my server with the java librespot-api
and added a glue script to retrieve metadata and control Spotify. You can find the meta_librespot-java.py script in the develop branch.
Currently I'm using the process
stream and librespot-api is wrapped in a shell script librespot-api.sh
:
#!/bin/bash
cd "$(dirname "$0")"
java -jar /home/pi/Develop/librespot-java/librespot-api-1.6.2.jar --logLevel="OFF" --player.output="MIXER" --player.enableNormalisation=false --player.preferredAudioQuality="VERY_HIGH"
logging seems to go to stdout, so I had to disable it.
The stream is setup as follows:
stream = process:////home/pi/Develop/librespot-java/librespot-api.sh?name=Spotify&sampleformat=44100:16:2&controlscript=/home/pi/meta_librespot-java.py
Feel free to test this setup and give feedback
Just for reference if someone else has an issue in the future:
The setting --player.output
should be STDOUT
, not MIXER
unless I missed something.
Otherwise it works perfectly. librespot-java seems to be more responsive regarding Spotify Connect, has much better queue compatibility and also does playback reporting.
sed -i 's/<Console name="console" target="SYSTEM_OUT">/<Console name="console" target="SYSTEM_ERR">/' api/src/main/resources/log4j2.xml
and
sed -i 's/<Console name="console" target="SYSTEM_OUT">/<Console name="console" target="SYSTEM_ERR">/' lib/src/main/resources/log4j2.xml
before building librespot-java will get you logging to stderr instead. Not sure if both are necessary. Then you can add log_stderr=true
to your source-row in snapserver.conf.
Regarding @manfreddz's tip, both log4j2.xml
changes are necessary.
You might also run into a difference in the volume control mappings between librespot-org/librespot and librespot-org/librespot-java. See patch at https://github.com/librespot-org/librespot-java/issues/373#issuecomment-1831964719 for a quick and dirty (i.e. no config) implementation of something like librespot's logarithmic volume control but for librespot-java.
Does meta_librespot-java.py still work? I can't get it to work properly with the new version of Snapweb
@ChrisIossa what exactly is not working for you, with which versions (Snapserver, Snapweb, Librespot)? Unfortunately, my Spotify premium account has expired.
I was actually having trouble getting the control script working at all. Neither the metadata nor the playback controls were showing up in the recent version of Snapweb. After doing some digging I found out it was because the script and Librespot were starting at the same time (when Snapserver comes up) and since Librespot java takes some time to spin up, the script was trying and failing to connect to the websocket (which wasn't open yet).
Adding a time.sleep
delay to the script alleviated this, but I'm not super happy with that fix since I consider it hacky. I'm going to try have it wait for the websocket to open. Once I do, I'll make a PR with my changes. I actually already have some fixes for the MPD control script that I should make a PR for once I clean it up a bit.
I already fixed the same issue in meta_mopidy.py
(42678620c672ebb5814f85a1f458afb47e5e3fa0), and applied the same change now to meta_librespot-java.py
: be083d2e8e38b0b7abae34adc598a9867caea681
Can you please try if this version fixes the probem? It simply continuously retries to open the websocket to librespot: https://github.com/badaix/snapcast/blob/develop/server/etc/plug-ins/meta_librespot-java.py
So the change to the websocket loop fixes the errors for when librespot-java
is restarted. Thank you for that! However that script doesn't work out of the box. I had to make changes to the WebSocketApp
constructor for it to work.
self.websocket = websocket.WebSocketApp(
url=f"ws://{self._params['librespot-host']}:{self._params['librespot-port']}/events",
on_message=lambda ws, msg: self.on_ws_message(ws, msg),
on_error=lambda ws, error: self.on_ws_error(ws, error),
on_open=lambda ws: self.on_ws_open(ws),
on_close=lambda ws, close_status_code, close_msg: self.on_ws_close(ws, close_status_code, close_msg)
)
Why do you need these lambdas? The constructor is the same as before, except that the url
is now a named parameter. As I understood the old version was working for you (at least when starting delayed).
The really same constructor is used in meta_mopidy.py
and it's working without a flaw on my server.
Edit: May it be related to the version of the websocket-client
library? If merged now the check for the required version from meta_mopidy.py
to meta_librespot-java.py
:
wsversion = websocket.__version__.split(".")
if int(wsversion[0]) == 0 and int(wsversion[1]) < 58:
logger.error(
f"websocket-client version 0.58.0 or higher required, installed: {websocket.__version__}, exiting."
)
exit()
librespot-java provides an API for local control of the spotify client whereas librespot does not.
I'd like to see librespot-java considered as an (autodetected?) alternative for
librespot://
or as an additionallibrespot-java://
stream source.Counter-argument that librespot-java isn't as active as librespot.
Another counter-argument: just use
process://
. (What advantage is there internally for snapcast having specific stream sources instead of justprocess://
? Is it the metadata formats?)For reference spocon packages librespot-java for Debian, etc.
Thoughts?