feat: 스포티파이 곡을 Soloist(스포티파이 공식 클라이언트)로 먼저 재생, 안 되면 유튜브로
- soloist/: soloist-bridge 중계 서버(docker). 곡마다 soloist --single-track을 띄우고 PulseAudio 빈 싱크를 캡처해 MP3 스트림으로 Lavalink(http 소스)에 넘긴다. 첫 소리가 나와야 성공으로 응답, 15초 안에 소리가 없거나 오류면 실패. 한 계정 한 곡 제한 → 다른 길드가 쓰는 중이면 busy. 빌드 만료(90일) 자동 갱신, 페어링 대기 자동 진입. - bot: SOLOIST_URL 설정 시 스포티파이 곡은 재생 직전에 Soloist를 먼저 시도, 실패하면 기존 유튜브 경로. 곡 도중 끊김·위치 이동·음성 재접속은 같은 곡의 유튜브 음원으로 그 위치부터 이어 재생. 오래 걸려 실패하면 5분 동안 유튜브로만 재생. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
50
soloist/README.md
Normal file
50
soloist/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# soloist-bridge — 스포티파이 곡을 스포티파이 공식 클라이언트로 재생
|
||||
|
||||
스포티파이 곡(스포티파이 주소·재생목록·`-p` 검색·자동재생 추천곡)을 유튜브로 바꾸지 않고
|
||||
스포티파이 공식 헤드리스 클라이언트 [Soloist](https://developer.spotify.com/documentation/soloist)로 재생한다.
|
||||
Soloist가 안 되면(설정 없음·페어링 전·다른 서버가 사용 중·재생 오류) 봇이 바로 기존 유튜브 경로로 재생한다.
|
||||
|
||||
```
|
||||
봇 ── GET /prepare?track=<id>&owner=<봇:길드>&duration=<ms> ──▶ soloist-bridge(.5:8780, docker, host 네트워크)
|
||||
├ soloist --single-track spotify:track:<id>
|
||||
│ └ PulseAudio 빈 싱크 "soloist"로 출력
|
||||
├ parec(싱크 모니터) → 앞쪽 무음 제거 → ffmpeg MP3 320k
|
||||
└ 첫 소리가 나오면 {"path":"/stream/<sid>.mp3"} 응답
|
||||
Lavalink(.6) ── GET /stream/<sid>.mp3 ──▶ 곡이 끝날 때까지 실시간 MP3 스트림(http 소스로 재생)
|
||||
```
|
||||
|
||||
## 동작 규칙
|
||||
|
||||
- **한 번에 한 곡**: 스포티파이 계정 하나는 동시에 한 곳에서만 재생된다. 다른 길드(또는 다른 봇)가 쓰는 중이면
|
||||
`409 busy` → 그 길드는 유튜브로 재생한다. 같은 길드의 다음 곡 요청은 이전 곡을 끊고 시작한다.
|
||||
- **실패 판정**: 15초 안에 소리가 안 나오거나 soloist가 먼저 끝나면 실패 → 유튜브.
|
||||
- **곡 도중 끊김**(같은 계정을 휴대폰에서 재생 등): 청크 종료 없이 연결을 끊어 Lavalink가 오류로 받게 한다.
|
||||
봇은 그 위치부터 같은 곡의 유튜브 음원으로 이어서 재생한다.
|
||||
- **일시정지**: 받은 MP3를 세션에 모두 보관하므로 멈췄다 다시 재생해도 이어진다.
|
||||
- **위치 이동(seek)**: 실시간 스트림이라 직접은 안 된다. 봇이 같은 곡의 유튜브 음원으로 바꿔 그 위치부터 재생한다.
|
||||
- **빌드 만료(90일)**: 실행 파일은 `/data/bin/soloist`에 자동으로 내려받는다. 만료 7일 전이거나
|
||||
종료 코드 10(만료)이 나오면 최신 빌드로 자동 교체한다.
|
||||
|
||||
## 처음 설정 (사람이 해야 하는 일)
|
||||
|
||||
1. 스포티파이 **Premium** 계정으로 https://developer.spotify.com/dashboard 에 로그인 →
|
||||
Spotify Soloist API Key 메뉴에서 약관 동의 후 키 발급.
|
||||
2. .5에 키 저장: `/root/bot/soloist/soloist.env` 에 `SOLOIST_API_KEY=<키>` (권한 600).
|
||||
3. 컨테이너 기동: `docker compose -f /root/bot/music_bot_v2/soloist/compose.yml up -d --build`
|
||||
4. **페어링(1회)**: 키가 있고 로그인 정보가 없으면 브리지가 자동으로 페어링 대기 상태가 된다.
|
||||
서버와 **같은 네트워크(LAN)** 에 있는 휴대폰/PC의 스포티파이 앱 → 기기 목록 → `music_bot` 선택.
|
||||
`curl http://192.168.10.5:8780/health` 의 `"paired": true` 로 확인.
|
||||
5. 봇 환경변수에 `SOLOIST_URL=http://192.168.10.5:8780` 을 넣고 봇을 다시 빌드/기동.
|
||||
|
||||
페어링한 계정으로 다른 기기에서 음악을 틀면 봇 재생이 끊긴다(→ 유튜브로 이어짐). 봇 전용 계정을 권장한다.
|
||||
계정을 바꾸려면 컨테이너를 멈추고 `/root/bot/soloist/data/state` 를 지운 뒤 다시 띄워 4번을 반복한다.
|
||||
|
||||
## 상태 확인
|
||||
|
||||
- `GET /health` → `enabled`(키 있음), `paired`, `pairing`, `version`, `expiresInDays`, `busy`(지금 재생 중인 세션)
|
||||
- `docker logs soloist-bridge` → `소리 시작`, `곡 도중 끊김`, `스트림 연결 종료` 등
|
||||
|
||||
## 주의
|
||||
|
||||
- 스포티파이 약관상 개인 이용 범위를 벗어난다(디스코드 여러 명에게 송출). 계정 제재 위험은 사용자가 감수한다.
|
||||
- `/health`·`/prepare`에는 인증이 없다. LAN 밖으로 8780 포트를 열지 말 것.
|
||||
Reference in New Issue
Block a user