librespot-org / librespot-java

The most up-to-date open source Spotify client
Apache License 2.0
377 stars 92 forks source link

Local media playback #208

Open ikirmitz opened 4 years ago

ikirmitz commented 4 years ago

Is there a way for librespot-jave to playback local content the same way Spotify desktop does? If yes, can you please provide a link or some instructions on how to configure it? Many thanks

devgianlu commented 4 years ago

Right now there is no way to reproduce local tracks because I never thought that would be useful. Could you describe your usa case/scenario? Just to understand how it could work.

ikirmitz commented 4 years ago

I've set up librespot-java to run as a service on a headless raspberry pi. The audio is then routed through darkice to a local icecast server that works as a mini radio station for other devices in the house. I have an extensive collection of bootlegs, mashups and recordings of live DJ sets that I would like to be able to play back along with spotify tracks. I can do that with the regular spotify desktop client and I can even create playlists with mixed content.

The actual files can reside on a network share or locally on the pi. Let me know if you need more info

devgianlu commented 4 years ago

I never thought of using a network share, but it could work this way. The problem before was that the client only communicates (I think) the name of the file which would make pretty unpractical synchronizing tracks between two devices without additional software.

I don't think there's any way to create a "custom" local track, so the user has to add the mounted network share to the local files on the desktop client and then setup librespot to search the local tracks on said network share.

Not too bad.

ikirmitz commented 4 years ago

Yes, I suppose in my case the network share should be served by the pi itself but in theory any network share will work? I'm not a JAVA dev but I do node/js/perl etc. I can help you test/debug the enhancement. My only problem is I haven't managed to compile librespot-java from source on the pi and I couldn't find any instructions on how to cross-compile on my Ubuntu desktop.

FYI I've created a simple nodejs script that runs as a service and hooks on the librespot-java api. Its role is to update the icecast metadata whenever it receives the metadataAvailable event since darkice doesn't seem to support this natively.

devgianlu commented 4 years ago

My only problem is I haven't managed to compile librespot-java from source on the pi and I couldn't find any instructions on how to cross-compile on my Ubuntu desktop.

With Java there is no need to cross-compile. Just run mvn clean package to create the JAR executables, then you can copy them over to your Pi.

ikirmitz commented 4 years ago

Oh that's nice, cheers

ikirmitz commented 4 years ago

I just wanted to add something I only just recently discovered: the ability for mobile spotify clients to "download" playlists with local files created on a desktop client. Maybe of use to you

https://support.spotify.com/us/using_spotify/features/listen-to-local-files/

Zageron commented 3 years ago

This does seem very useful, similar to how the android works. I load files on my desktop, create a playlist, then click download on a the playlist on my phone, now I can listen to those tracks on my phone through Spotify. Would be useful to have some sort of mechanism to tell this app to do this with some playlists.

devgianlu commented 3 years ago

I have not forgotten about this! I am in the process of implementing local files playback.

Zageron commented 3 years ago

I have not forgotten about this! I am in the process of implementing local files playback.

How will we get to decide which playlists or songs to download to the device?

devgianlu commented 3 years ago

How will we get to decide which playlists or songs to download to the device?

For the moment you'll have to point librespot-java to where you have your local files and it'll take them from there. Following the shared drive idea.

Having the download functionality would require to reverse engineer the transfer protocol, so that's enough for a start.

devgianlu commented 3 years ago

Turns out this is harder than what I thought, the Spotify client doesn't communicate to librespot-java where the file really is, but just some metadata (name, artist, album, duration).

Reversing the transfer protocol might be needed to understand where the files are.

ikirmitz commented 3 years ago

First of all thanks for keep looking at this, great news! I don't have much insight to offer as to how the spotify tranfer protocol really works but what I have noticed is that spotify will auto-detect if local files in a playlist are present on your system based on some kind of hash. What I mean by that is: 1) On a PC with spotify client installed, point the client to a folder with local media 2) Add some of these files in a playlist 3) Share this playlist with any other user (including yourself on a different PC). They wont be able to download or play your files local files... but 4) Share the files with the user. They need to download them to a folder and configure spotify client to play local media from that folder 5) Now spotify can play these files from the playlist. No extra config required. As long as the files are identical, it will play them

Hope that helps

devgianlu commented 3 years ago

Mhh, I wonder if the client indexes the folder and matches the files based on the metadata (that's not optimal because there's nothing preventing two tracks from having the exact same metadata). But I cannot see any identifier being transmitted with the tracks. It makes sense for it not to have the full path to file because of security reasons, but at least the filename. Or maybe I am missing some feature flag in the client configuration.

UPDATE I was indeed missing the audio/local supported type, but adding that doesn't change anything.

The Spotify Desktop app logs aren't very useful, all that is reported is Wifi Sync Connected to .... There is clearly traffic between the two devices.

ikirmitz commented 3 years ago

I can definitely do some tests and see if the match is based on metadata and/or filename. Will keep you posted