yt-dlp 호출 자체를 없애는 경로를 탐색해 실측했다.
[탐색 과정]
- 내부 player API 를 클라이언트별로 호출해 비교:
ANDROID_VR/TVHTML5/WEB_EMBEDDED = LOGIN_REQUIRED·ERROR, WEB = SABR 전용(직접 URL 없음)
IOS = 0.32s 로 직접 URL(itag 140) 획득했으나 뒷부분 range 요청이 403 → 이어받기 불가
- 정상 재생되는 yt-dlp URL 의 c= 파라미터가 VISIONOS 임을 확인하고 동일 클라이언트로 재현.
visitorData 없이 호출하면 LOGIN_REQUIRED, 넣으면 status=OK.
[결과] VISIONOS + visitorData 직접 호출
- 추출 0.30~0.38s (현행 상주 리졸버 1.7~2.3s, 기존 subprocess 4.2~4.7s)
- itag 251 로 yt-dlp 결과와 동일 포맷, Lavalink loadType=track
- range 0 / 1MB / 2MB / 3MB 전부 206 → 이어받기 정상(SABR·IOS 와 다름)
- 실제 재생: 90초 끊김 0/17, 일반곡·곡전환 성공. 첫 소리 2.0~2.3s
- 리졸버에 0순위로 넣고 실패 시 상주 lib → subprocess 로 폴백(경로 통계 innertube 5 / lib 1 / 실패 0)
미해결/주의: visitorData 를 정적 파일에서 읽는 프로토타입이라, 운영 적용 시 봇이 2시간마다
생성하는 visitorData 를 공유받도록 배선해야 한다. 검색어(비 URL) 입력은 영상 ID 가 없어
기존 경로로 폴백한다. 연령제한곡은 미검증(폴백 경로가 쿠키로 처리).
프로덕션(리졸버 8779, Lavalink, master)은 변경하지 않았다.
[1] 재생 중 끊김(~55초) 해결 시도 — 전부 실패
- poToken 정상 주입 + 프로덕션 동일 설정 : 55초 끊김 동일
- 클라이언트 WEB 단독(SABR 경로 강제) : 55초 끊김 동일(decode 오류)
- 프록시(.4:3128) 제거 : 55초 끊김 동일
원인: 첫 청크 재생 후 '이어받기' 요청이 실패(정적 경로 403 / SABR 경로 decode).
feat/sabr-support 는 열린 PR #229, 마지막 커밋 2026-07-27 로 미병합 진행 중 기능.
=> 우리 쪽 설정으로 고칠 수 없음. SABR 직결 보류 확정.
[2] 새 방식: yt-dlp 를 '상주 라이브러리'로 호출하는 리졸버(프로토타입 첨부)
- zipapp(/usr/local/bin/yt-dlp) 을 sys.path 에 넣어 import, YoutubeDL 인스턴스 1회 생성
- 매 요청 프로세스 기동(0.40s) 제거 + player_client=default 단독
- 실패 시 기존 subprocess 경로로 자동 폴백(안전)
리졸브 실측: 1.58~2.30s (기존 subprocess 3곡 평균 4.2~4.7s)
재생 검증(프로덕션 Lavalink .6 + 이 리졸버):
일반곡 2656ms / 해외곡 2968ms / 직접URL 1900ms / 곡전환 성공
90초 장시간: 85초 진행, 끊김 0/17 ← SABR(55초 실패) 대비 안정
프로덕션(리졸버 8779, Lavalink, master)은 변경하지 않음. 테스트는 8780 포트로만 수행.
googlevideo 재생 403(스트림 거절)은 Lavalink youtube-plugin에 유효한
poToken/visitorData가 없어서 발생. 봇이 노드 ready 시점과 2시간 주기로
poToken을 생성해 Lavalink의 POST /youtube 엔드포인트에 주입한다.
- scripts/potoken-refresh.mjs: youtubei.js+bgutils-js+jsdom로 생성 후 주입 (독립 ESM 프로세스)
- LavalinkManager: ready 이벤트 + 2h 인터벌로 자식 프로세스 실행
- deps: bgutils-js 3.2.0, jsdom, youtubei.js 추가 / Docker base node:22-alpine
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>