# Kord - YouTube 음악 재생 기능 기획안 (YouTube Music Playback) ## 체인지로그 (Changelog) - **2026-03-30**: 최초 기획안 작성 --- ## 1. 개요 YouTube 음악 재생 기능은 사용자가 텍스트 기반 명령으로 음악을 검색하거나 YouTube 링크를 입력하면, 현재 참여 중인 음성 채팅방에 봇이 입장하여 재생 목록(플레이리스트)을 관리하고 오디오를 재생하는 기능입니다. 이 기능은 서버 유틸리티를 넘어서 실시간 상호작용 기능으로 확장되는 첫 사례이며, 음성 연결, 큐 관리, UI 컨트롤, 외부 미디어 소스 처리까지 포함하는 비교적 큰 범위의 기능입니다. ### 목표 - 문자열 검색으로 YouTube 영상을 찾아 재생 목록에 추가할 수 있어야 함 - YouTube 링크를 입력해 직접 재생 목록에 추가할 수 있어야 함 - 현재 재생 목록을 조회할 수 있어야 함 - 인덱스 기반으로 재생 목록 항목을 삭제할 수 있어야 함 - 재생 중지 / 스킵 / 일시정지 / 재개 등 기본 컨트롤을 버튼 또는 이모지 기반 UI로 제공해야 함 - 음악 추가 요청 시, 요청자가 있는 음성 채팅방에 봇이 자동 입장하고 재생을 시작해야 함 - 마지막에 봇을 음성 채팅방에서 내보내는 기능이 있어야 함 --- ## 2. 지원 범위 (MVP) ### 포함 - `/music add query:<문자열>` - `/music add url:` - `/music queue` - `/music remove index:<번호>` - `/music skip` - `/music stop` - `/music leave` - 재생 컨트롤 메시지 (버튼 또는 이모지 라벨 기반) - 음성 채널 자동 입장 및 큐 기반 연속 재생 ### 제외 (초기 범위 외) - Spotify, SoundCloud 등 타 플랫폼 연동 - 반복 재생 / 셔플 / 볼륨 조절 - 길드별 DJ 역할 분리 - 재생 이력 저장 - 노래 가사 표시 --- ## 3. 사용자 시나리오 ### 시나리오 A: 검색어로 곡 추가 1. 사용자가 음성 채널에 입장한 상태에서 `/music add query:아이유 좋은날` 실행 2. 봇이 검색 결과 1위를 선택하거나 선택 UI를 제공 3. 재생 목록에 곡을 추가 4. 봇이 음성 채널에 자동 입장 5. 현재 재생 중이 없다면 즉시 재생 시작 ### 시나리오 B: 링크로 곡 추가 1. 사용자가 `/music add url:https://www.youtube.com/watch?v=...` 실행 2. 봇이 링크 메타데이터를 파싱 3. 재생 목록에 항목 추가 4. 이미 재생 중이면 큐 뒤에 대기 ### 시나리오 C: 큐 조회 및 삭제 1. 사용자가 `/music queue` 실행 2. 봇이 현재 재생곡과 대기열을 인덱스와 함께 Embed로 표시 3. 사용자가 `/music remove index:3` 실행 4. 3번 항목이 큐에서 제거됨 ### 시나리오 D: 컨트롤 UI 사용 1. 재생 시작 시 봇이 "지금 재생 중" 메시지를 게시 2. 메시지에는 ⏸️, ▶️, ⏭️, ⏹️ 같은 버튼이 포함됨 3. 사용자가 버튼을 눌러 재생 상태를 제어 --- ## 4. 명령 구조 제안 ### `/music add` 입력 방식: - `query`: YouTube 검색 문자열 - `url`: YouTube 링크 규칙: - 두 옵션 중 하나만 입력 - 사용자는 반드시 음성 채널에 있어야 함 ### `/music queue` 출력: - 현재 재생 중 항목 - 대기열 목록 - 각 곡의 인덱스, 제목, 길이, 요청자 ### `/music remove` 입력: - `index`: 큐에서 제거할 번호 ### `/music skip` - 현재 곡을 스킵하고 다음 곡 재생 ### `/music stop` - 재생 중지 - 현재 곡 정지 및 대기열 비움 여부는 정책 선택 필요 ### `/music leave` - 봇을 음성 채널에서 퇴장시킴 - 기본 정책은 큐도 함께 정리 --- ## 5. 재생 컨트롤 UI ### 컨트롤 메시지 구성 재생 시작 시 텍스트 채널에 Embed + 버튼 메시지 생성 권장 버튼: - `⏸️` 일시정지 - `▶️` 재개 - `⏭️` 스킵 - `⏹️` 정지 - `📜` 큐 보기 ### 정책 - 한 길드당 활성 컨트롤 메시지 1개 유지 - 곡이 바뀔 때 동일 메시지를 업데이트하거나 새 메시지를 생성할지 결정 필요 - MVP에서는 새 메시지 생성보다 기존 메시지 업데이트가 로그 노이즈를 줄이는 데 유리 --- ## 6. 큐 및 재생 상태 설계 ### 핵심 개념 - 재생 상태는 길드 단위로 분리 - 각 길드는 하나의 음성 연결과 하나의 큐를 가짐 - 큐는 메모리 기반으로 시작하고, 필요 시 DB 영속화 확장 가능 ### 추천 구조 ```ts interface MusicQueueItem { id: string; title: string; url: string; durationSec?: number; requestedByUserId: string; } interface GuildMusicSession { guildId: string; voiceChannelId: string; textChannelId: string; nowPlaying: MusicQueueItem | null; queue: MusicQueueItem[]; paused: boolean; controlMessageId?: string; } ``` ### 초기 전략 - 메모리 기반 세션 관리 - 봇 재시작 시 큐는 초기화됨 - 안정화 이후 DB 저장 여부 검토 --- ## 7. 음성 입장 및 재생 흐름 ### 자동 입장 - `/music add` 실행 시 사용자의 음성 채널을 확인 - 봇이 해당 채널에 없으면 자동 입장 - 이미 다른 채널에 있으면 정책 필요 ### 기본 정책 제안 - 같은 길드 내에서 봇이 이미 재생 중이면 다른 채널 요청은 거부 - "현재 다른 음성 채널에서 사용 중" 메시지 제공 ### 자동 퇴장 - `/music leave`로 수동 퇴장 가능 - 추가 정책 후보: - 큐가 끝나고 1분 뒤 자동 퇴장 - 음성 채널에 봇만 남으면 자동 퇴장 --- ## 8. YouTube 검색 및 스트리밍 전략 > [!IMPORTANT] > YouTube 관련 기능은 라이브러리 안정성, 차단 이슈, 서비스 정책을 반드시 검토해야 합니다. ### 검색 가능한 접근: - YouTube 공식 API 사용 - 서드파티 검색 라이브러리 사용 ### 오디오 스트리밍 가능한 접근: - `@discordjs/voice` 기반 음성 재생 - YouTube 스트림 추출 라이브러리 사용 ### 기술 리스크 - YouTube 구조 변경 시 스트림 추출 라이브러리 고장 가능 - 지역 제한 / 연령 제한 / 라이브 영상 처리 문제 - 긴 재생 목록에서 메모리 및 연결 안정성 문제 --- ## 9. 권한 및 운영 정책 ### 봇 권한 - `Connect` - `Speak` - `View Channel` - 텍스트 채널의 `Send Messages`, `Embed Links` ### 사용자 권한 - 기본적으로 일반 사용자도 곡 추가 가능 - `skip`, `stop`, `leave`, `remove`는 다음 중 하나로 제한 가능 - 관리자 전용 - 요청자 또는 관리자 - 같은 음성 채널 참여자 전원 허용 ### 추천 MVP 정책 - `add`, `queue`: 같은 음성 채널 참여자 누구나 가능 - `skip`, `stop`, `remove`, `leave`: 관리자 또는 같은 음성 채널 참여자 허용 --- ## 10. 에러 처리 필수 안내 케이스: - 사용자가 음성 채널에 없음 - 유효하지 않은 YouTube 링크 - 검색 결과 없음 - 재생 목록 인덱스 범위 오류 - 봇 음성 권한 부족 - 스트림 로드 실패 에러 메시지는 기존 Error Guidance 체계와 연결하는 것이 좋습니다. --- ## 11. 구현 단계 (Phased Implementation) | 단계 | 내용 | |------|------| | **Phase 1** | `@discordjs/voice` 기반 음성 연결, 메모리 큐, `/music add`, `/music queue`, `/music skip`, `/music leave` | | **Phase 2** | 링크 기반 추가 + 검색 기반 추가 분리, `/music remove`, `/music stop` | | **Phase 3** | 컨트롤 메시지(⏸️ ▶️ ⏭️ ⏹️) 및 상호작용 처리 | | **Phase 4** | 자동 퇴장, 권한 정책 세분화, 예외 처리 고도화 | | **Phase 5** | 반복 재생, 셔플, DJ 역할, 재생 이력 등 확장 기능 | --- ## 12. 검증 계획 ### 수동 테스트 1. 음성 채널 입장 후 검색어로 곡 추가 2. 링크로 곡 추가 3. 큐 조회 및 인덱스 삭제 4. 스킵 / 정지 / 퇴장 동작 확인 5. 곡 종료 후 다음 곡 자동 재생 확인 6. 권한 부족 환경에서 적절한 에러 표시 확인 ### 자동 테스트 - 큐 삽입 / 삭제 / 스킵 로직 단위 테스트 - 길드별 세션 분리 테스트 - 인덱스 유효성 검사 테스트 - 컨트롤 인터랙션 핸들러 테스트 --- ## 13. 관련 문서 | 문서 | 링크 | |------|------| | 기능 로드맵 | [`Feature_Roadmap.md`](./Feature_Roadmap.md) | | 임시 음성 채널 기획 | [`Temp_Voice_Channel_Plan.md`](./Temp_Voice_Channel_Plan.md) | | 에러 안내 기획 | [`Error_Guidance_Plan.md`](./Error_Guidance_Plan.md) |