@@ -17,9 +17,13 @@ This repository is a maintained fork focused on keeping YouTube playback working
1717
1818Important differences from the original project:
19191 . This fork supports YouTube OAuth playback fallback.
20- 2 . If you want reliable playback for blocked or age-restricted videos, you should use a dedicated burner Google account.
21- 3 . Do not use your main Google account.
22- 4 . If the burner account cannot play a video in the normal YouTube browser UI, the bot will usually not be able to play it either.
20+ 2 . This fork supports direct Spotify playback through a local ` go-librespot ` backend.
21+ 3 . Spotify support is per-bot and can be enabled or disabled independently at startup.
22+ 4 . If two bots use the same Spotify account, they will compete for the same Spotify Connect session.
23+ 5 . For parallel Spotify playback on two bots, use two separate Spotify accounts.
24+ 6 . If you want reliable playback for blocked or age-restricted videos, you should use a dedicated burner Google account.
25+ 7 . Do not use your main Google account.
26+ 8 . If the burner account cannot play a video in the normal YouTube browser UI, the bot will usually not be able to play it either.
2327
2428## YouTube OAuth Setup For This Fork
2529
@@ -143,6 +147,175 @@ Container-specific behavior:
1431472 . Relative state paths are resolved from ` JMUSICBOT_HOME ` , which defaults to ` /data ` in the container.
1441483 . Each bot keeps its own ` config.txt ` , ` serversettings.json ` , and ` Playlists/ ` under its own instance directory.
145149
150+ ## Spotify Direct Playback
151+
152+ This fork can play Spotify tracks, albums, and playlists directly without YouTube conversion.
153+
154+ ### What this does
155+
156+ 1 . Spotify URLs are resolved as Spotify content, not mapped to YouTube.
157+ 2 . Playback is done through a local ` go-librespot ` backend plus an ` ffmpeg ` bridge to Discord voice.
158+ 3 . The feature is enabled per bot instance, not globally for the whole host.
159+
160+ ### What this does not do
161+
162+ 1 . It does not use the official Spotify Web API for full audio playback.
163+ 2 . It does not allow two bots on the same Spotify account to play different things at the same time.
164+ 3 . It does not bypass normal Spotify account limits or Spotify Connect session rules.
165+
166+ ### Requirements
167+
168+ 1 . Spotify playback is optional and disabled by default.
169+ 2 . It requires the Docker image or runtime environment to start the bundled ` go-librespot ` sidecar.
170+ 3 . It requires a Spotify Premium account for playback.
171+ 4 . The bot instance must have persistent writable storage under its data directory.
172+
173+ ### Integration overview
174+
175+ For one bot instance with Spotify enabled, the runtime does the following:
176+ 1 . starts the Java bot process
177+ 2 . starts a local ` go-librespot ` daemon
178+ 3 . creates a local PCM pipe under the bot data directory
179+ 4 . authenticates the selected Spotify account
180+ 5 . uses that backend for Spotify URLs while keeping normal lavaplayer behavior for non-Spotify URLs
181+
182+ ### Per-bot enable or disable
183+
184+ Spotify is controlled per bot instance through environment variables.
185+
186+ Example:
187+
188+ ``` env
189+ SPOTIFY_ENABLED=true
190+ SPOTIFY_DEVICE_NAME=devshmusic-test1-spotify
191+ SPOTIFY_CALLBACK_PORT=0
192+ ```
193+
194+ If ` SPOTIFY_ENABLED=false ` or unset:
195+ 1 . the Spotify sidecar is not started
196+ 2 . direct Spotify playback is disabled for that bot
197+ 3 . the bot continues to work as a normal YouTube/lavaplayer bot
198+
199+ This means you can run:
200+ 1 . one bot with Spotify enabled
201+ 2 . another bot with Spotify disabled
202+ 3 . both at the same time on the same host
203+
204+ ### Minimal bot env for Spotify
205+
206+ The smallest useful setup in ` bot.env ` is:
207+
208+ ``` env
209+ BOT_TOKEN=replace_with_discord_bot_token
210+ BOT_OWNER=replace_with_discord_owner_id
211+ SPOTIFY_ENABLED=true
212+ SPOTIFY_DEVICE_NAME=devshmusic-spotify-1
213+ SPOTIFY_CALLBACK_PORT=0
214+ ```
215+
216+ Notes:
217+ 1 . ` SPOTIFY_DEVICE_NAME ` should be unique per bot.
218+ 2 . ` SPOTIFY_CALLBACK_PORT=0 ` lets the backend choose a free local callback port automatically.
219+ 3 . If Spotify is disabled for a bot, you can omit all Spotify variables entirely.
220+
221+ ### First-time Spotify setup from scratch
222+
223+ When ` SPOTIFY_ENABLED=true ` and no prior Spotify state exists:
224+ 1 . pick the bot instance that should get Spotify support
225+ 2 . set ` SPOTIFY_ENABLED=true ` in that bot's ` bot.env `
226+ 3 . make sure the instance has its own persistent data directory
227+ 4 . start or restart that bot container
228+ 5 . watch the logs for the Spotify authorization URL
229+ 6 . open the URL in a browser
230+ 7 . log into the Spotify Premium account intended for that bot
231+ 8 . finish the callback flow
232+ 9 . let the bot finish initialization
233+ 10 . test a Spotify track, album, or playlist URL on Discord
234+
235+ After that, restarts should reuse the stored Spotify session state.
236+
237+ ### Where Spotify state is stored
238+
239+ For a bot instance running with ` JMUSICBOT_HOME=/data ` , the Spotify runtime stores:
240+ 1 . Spotify auth and daemon state under ` /data/spotify `
241+ 2 . the PCM pipe under ` /data/spotify.pipe `
242+
243+ This means:
244+ 1 . deleting the instance data directory will force a fresh Spotify login
245+ 2 . moving the instance to another host requires moving the bot's data volume as well
246+
247+ ### Recommended deployment patterns
248+
249+ #### One bot with Spotify, one bot without Spotify
250+
251+ This is the cleanest production split.
252+
253+ Example:
254+ 1 . ` bot-a ` : ` SPOTIFY_ENABLED=true `
255+ 2 . ` bot-b ` : ` SPOTIFY_ENABLED=false `
256+
257+ Result:
258+ 1 . ` bot-a ` can handle Spotify URLs and normal YouTube URLs
259+ 2 . ` bot-b ` stays a normal non-Spotify bot
260+ 3 . only one container pays the operational cost of the Spotify sidecar
261+
262+ #### Two bots with Spotify enabled
263+
264+ This is valid only if you understand the account model.
265+
266+ 1 . If both bots use the same Spotify account, they will fight over one Spotify Connect session.
267+ 2 . If you want both bots to play Spotify independently, use two separate Spotify accounts.
268+ 3 . Give each bot a unique ` SPOTIFY_DEVICE_NAME ` .
269+
270+ ### Multiple bots and account isolation
271+
272+ 1 . Two bots can both have Spotify enabled.
273+ 2 . If both bots use the same Spotify account, they will fight over one Spotify Connect session.
274+ 3 . If you need two bots to play different Spotify content at the same time, use two separate Spotify accounts.
275+
276+ ### Production checklist
277+
278+ Before enabling Spotify on a production bot:
279+ 1 . verify the bot can still play a normal YouTube URL
280+ 2 . verify the bot can play a Spotify track URL
281+ 3 . verify the bot can play a Spotify playlist URL
282+ 4 . verify ` skip ` , ` pause ` , ` resume ` , ` seek ` , ` volume ` , and ` queue `
283+ 5 . confirm the instance data directory is persistent
284+ 6 . confirm no second bot is using the same Spotify account unless that is intentional
285+
286+ ### Troubleshooting
287+
288+ #### The bot ignores Spotify URLs
289+
290+ Check:
291+ 1 . ` SPOTIFY_ENABLED=true ` is actually present in that bot's runtime env
292+ 2 . the bot instance was restarted after editing env
293+ 3 . the Spotify sidecar started successfully in logs
294+
295+ #### The bot asks for Spotify login every restart
296+
297+ Check:
298+ 1 . the bot is using persistent storage
299+ 2 . ` /data/spotify ` is not being discarded between restarts
300+ 3 . the container is not mounting a fresh empty instance directory
301+
302+ #### Two Spotify bots keep interrupting each other
303+
304+ Cause:
305+ 1 . both bots are logged into the same Spotify account
306+
307+ Fix:
308+ 1 . use one Spotify-enabled bot and one non-Spotify bot
309+ 2 . or use two separate Spotify accounts
310+
311+ #### Spotify works but YouTube stops working
312+
313+ This should not happen by design. The fork keeps Spotify and lavaplayer on separate playback paths.
314+ If this happens:
315+ 1 . test a plain YouTube URL on the same bot
316+ 2 . check bot logs for the failure path
317+ 3 . verify the bot is not stuck in an active Spotify session that should first be stopped
318+
146319## GHCR Container Publishing
147320
148321GitHub Actions now builds the Docker image from this repository and publishes it to GHCR.
0 commit comments