claude code로 바이브 코딩
"오토튠 직접 만들 수 있을까?"
FL Studio나 Auto-Tune Pro 같은 상용 소프트웨어 없이, Python과 AI 코딩 어시스턴트만으로 실시간 오토튠 노래방을 만들어보기로 했다. 하드웨어는 Focusrite Scarlett 2i2 오디오 인터페이스와 마이크 하나. 소프트웨어는 Claude Code 하나.
하루 만에 완성했다.
"YouTube에서 비트를 MP3로 받을 수 있게 해줘."
Claude Code가 yt-dlp+ ffmpeg 조합으로 download_mp3.py 를 생성했다. 첫 실행에서 403 에러가 났는데, yt-dlp 버전이 오래된 거였다.
brew upgrade yt-dlp
로 해결.
비트를 받았으면 키를 알아야 한다. 처음에는 librosa+ Krumhansl-Schmuckler 알고리즘으로 구현했다. 작동은 했지만 신뢰도가 낮았다 (Mac Miller 곡에서 0.51).
Claude Code에게 "더 정확한 라이브러리 없나?" 물었더니 4개를 비교 분석해줬다:
Essentia로 갈아탔더니 결과가 확 달라졌다:
단, Essentia가 Python 3.14에서 빌드가 안 돼서 Python 3.12 가상환경(.venv)을 만들어야 했다. 이 .venv 패턴은 이후 프로젝트 전체에서 계속 쓰게 된다.
이게 핵심이었다. Claude Code에게 이렇게 말했더니, 먼저 Plan Mode에 들어가서 설계부터 했다.
아키텍처 결정:
피치 감지: YIN 알고리즘 (FFT 가속 자기상관)
피치 보정: TD-PSOLA (Time-Domain Pitch-Synchronous Overlap-Add)
오디오 I/O: sounddevice (PortAudio 래퍼)
실시간 처리: 256 샘플 블록 (~5.8ms 데드라인 @ 44100Hz)
설계가 끝나고 구현에 들어갔다.
핵심 클래스들:
YINDetectorFast: 2048 샘플 윈도우, 80-600Hz 범위, parabolic interpolation
ScaleQuantizer: 7개 스케일 지원 (chromatic, major, minor, pentatonic 등)
RetuneSmoother: speed 0.0(T-Pain 효과) ~ 1.0(자연스러운 보정)
PSOLAShifter: 포먼트 보존 피치 시프팅
440Hz 사인파 테스트에서 A4로 정확히 감지됐다. ~6Hz 오차가 있었는데, 2048 윈도우에서의 이론적 해상도 한계(~4.4Hz steps)였다. 실제 사람 목소리에서는 고조파 정보 덕에 더 정확해진다.
터미널에서 쓰는 건 불편했다. "미니멀 웹으로 띄워줘."
Claude Code가 Flask 없이 Python stdlib만으로 웹 서버를 만들었다.
http.server + ThreadingMixIn 조합.
HTML, CSS, JavaScript가 전부 autotune_web.py 단일 파일에 들어갔다. 다크 테마, 음악 프로덕션 스타일. 첫 번째 버그: Start 버튼을 눌러도 아무 반응이 없었다. 원인은 SSE(Server-Sent Events) 연결이 단일 스레드 서버를 블로킹하고 있었던 것. ThreadingMixIn 추가로 해결.
두 번째 버그: 브라우저 새로고침 시 ConnectionResetError. SSE 연결이 끊길 때 나는 정상적인 에러라 handle_error 오버라이드로 무시 처리.
이게 가장 야심찬 단계였다. Claude Code가 웹 서치로 Travis Scott의 보컬 프로덕션 기법을 조사한 후, 상용 플러그인들을 순수 Python으로 재구현하는 계획을 세웠다.
10개 이펙트 체인:
구현하고 Start를 눌렀더니... 멈췄다.
프로파일링 결과, 이펙트 체인 총 처리 시간이 16.86ms. 데드라인은 5.8ms. 290% 초과.
범인: StereoDelay가 혼자 14.1ms를 먹고 있었다. 매 블록마다 22,050 샘플짜리 딜레이 버퍼 전체에 Python per-sample biquad를 돌리고 있었던 것.
Claude Code가 5개 이펙트를 집중 최적화했다:
핵심 교훈: Python per-sample 루프는 오디오 DSP의 적이다.
scipy.signal.lfilter (C 구현)와 numpy 벡터화로 바꾸면 수십 배 빨라진다.
이 시점에서 갭 분석을 했다. "지금 뭐가 부족해?"
MR 재생 + 보컬 믹싱 ← 가장 중요
보컬 제거 (Vocal Removal)
MR 키 변경
녹음 기능
가사 싱크
YouTube URL 입력 → 자동 다운로드 → Essentia 키/BPM 분석 → 오토튠 키 자동 설정 + YouTube iframe 임베드
MR 재생 + 녹음 기능을 단 3분만에 구현. 기존 오디오 콜백에 MR 배열을 직접 믹싱하는 방식이라 새 스트림 없이 가능했다.
녹음 결과물: 보이스 전용 WAV + MR+보이스 믹스 WAV 두 파일 저장.
무료 가사 API를 조사했다. LRCLIB이 압도적이었다:
인증 불필요, 완전 무료
LRC 포맷 (타임스탬프 동기화) 지원 — 노래방의 핵심
한국어 가사 포함
파이프라인:
문제 1: YouTube 제목 꼬리말
"Rick Astley - Never Gonna Give You Up (Official Music Video)" 같은 제목에서 (Official Music Video) 를 제거하지 않으면 LRCLIB에서 404가 난다. _clean_track_name() 정규식으로 해결.
문제 2: Race Condition
분석 상태가 "done" 이 된 시점에 가사 검색이 아직 "idle" 이라 프론트엔드가 가사를 트리거하지 못했다. 상태 설정 순서를 바꿔서 해결.
이게 마지막 퍼즐 조각이었다. LLM API로 웹서치해서 곡별 믹싱 기법을 찾고, 그걸 현재 이펙트 체인의 파라미터로 구조화하는 것.
2단계 호출 전략:
/v1/responses + web_search → 믹싱 기법 리서치
/v1/chat/completions + response_format (JSON Schema) → 프리셋 JSON 변환
Grok API 대신 Claude가 직접 28개 장르/서브장르를 웹서치해서 프리셋 표준을 만들었다:
Hip-Hop, R&B, Pop, Rock, EDM, Trap, Jazz, Country, K-Pop, Lo-fi, Metal, Gospel, Reggaeton, Drill, Ballad, Future Bass, Rage Beat, Deep House, Hyperpop, Phonk, Afrobeat, Synthwave, Dreampop, Pluggnb, Techno, Neo Soul, Punk, City Pop, Ambient...
기존 4개(clean, subtle, pop, kpop) + 28개 신규 = 총 32개 프리셋을 effects_core.py 에 하드코딩. API 호출 없이 즉시 사용 가능.
파일 4개. 외부 프레임워크 제로. Flask도 React도 없다.
.
Essentia가 Python 3.14에서 안 돌아가서 .venv (3.12)를 만들었고, 이후 거의 모든 세션에서 "venv 활성화 잊음 → ModuleNotFoundError → venv로 재실행" 패턴이 반복됐다.
Grok API 호출 시 기본 User-Agent로는 403이 난다. "Mozilla/5.0..." 헤더 추가로 해결.
단일 스레드 HTTP 서버에서 SSE 연결이 다른 모든 요청을 막았다. ThreadingMixIn 한 줄로 해결.
16.86ms → 1.75ms. Python per-sample 루프를 C 구현(lfilter) + numpy 벡터화로 교체.
하루 만에 만든 건 솔직히 AI 코딩 어시스턴트 없이는 불가능했을 것이다. YIN 알고리즘이나 FDN 리버브의 수학을 직접 구현하려면 며칠은 걸렸을 것이다.
AI가 만능은 아니었다. 모든 세션에서 버그가 나왔고, 성능 문제가 있었고, 환경 설정이 꼬였다. AI가 잘하는 건 "첫 번째 동작하는 버전을 빠르게 만드는 것"이고, 그 뒤의 디버깅과 최적화는 결국 사람이 "이거 안 되는데?" "Start 누르면 멈추는데?"라고 피드백을 줘야 했다.
최종 결과물:
4개 Python 파일 (외부 프레임워크 제로)
실시간 오토튠 (5.8ms 데드라인 내 처리)
10개 이펙트 체인 (Travis Scott 스타일)
32개 장르 프리셋 + AI 프리셋 생성기
노래방 모드 (YouTube MR + 가사 싱크 + 녹음)
웹 UI (단일 파일, stdlib only)