로컬 AI 음악 생성은 창의성의 제약을 없애줍니다. ACE-Step 1.5와 같은 도구는 Mac에서 완전히 실행될 수 있으며, 클라우드 크레딧이나 업로드 대기열 없이 몇 분 만에 텍스트 프롬프트를 완전한 곡으로 바꿔줍니다. 하지만 이러한 자유는 '양'이라는 새로운 문제를 야기합니다. 생성이 저렴하고 즉각적이 되면, 노래를 만들 수 있는지 묻는 대신 드라이브에 쌓인 수십 개의 버전 중 어떤 것이 간직할 만한 가치가 있는지 고민하게 됩니다.
저는 이를 뼈저리게 배웠습니다. 보통 하루에 ACE-Step 1.5로 한 곡의 결과물을 건지려면 약 네 번의 테이크가 필요합니다. 하지만 평균은 거짓말을 합니다. 최근 한 세션에서는 단 하나의 편곡을 완성하기 위해 32개의 테이크를 생성했습니다. 2분짜리 노래 32곡을 듣는 것은 한 시간이 넘는 집중적인 청취 과정을 요구합니다. 일곱 번째 트랙쯤 되면 귀는 뭉개진 모음을 너그럽게 넘기기 시작합니다. 열다섯 번째 트랙에 이르면 단어를 완전히 놓치면서도 멜로디에 맞춰 고개를 까닥이고 있는 자신을 발견합니다. 청취 피로는 게으름이 아니라, 지각적 정확도가 실제로 무너지는 현상입니다. 제 귀가 작동하기 전에 먼저 작동할 수 있는 필터가 필요했습니다.
그래서 저는 OpenAI의 음성 인식 모델을 Apple Silicon에 최적화하여 포팅한 mlx-whisper를 기반으로 로컬 QA 파이프라인을 구축했습니다. 아이디어는 간단했습니다. 모든 테이크를 자동으로 전사(transcribe)하고 이를 원래 가사와 비교할 수 있다면, 객관적인 가사 일치율을 얻을 수 있다는 것이었습니다. 그 수치를 통해 32개의 테이크를 관리 가능한 소수로 분류할 수 있습니다.
파이프라인 작동 방식
워크플로우는 네 단계로 구성되며, 저는 각 단계를 타협할 수 없는 원칙으로 다룹니다.
생성(Generate). ACE-Step 1.5로 원본 오디오를 만듭니다. 이 단계에서는 아무것도 판단하지 않습니다. 목표는 양을 확보하는 것입니다.
전사(Transcribe). 모든 WAV 파일은 Mac의 mlx-whisper로 입력됩니다. MLX는 Apple의 Metal과 뉴럴 엔진(neural engine)에 최적화되어 구축되었기 때문에 이 과정은 완전히 로컬에서 실행됩니다. API 비용도, 네트워크 지연도 없으며, 원본 오디오를 원격 서버로 전송하는 것에 대한 개인정보 보호 문제도 없습니다. 커피를 내리는 동안 32개의 파일 배치가 전사됩니다.
점수 매기기(Score). Whisper의 전사 결과와 원래 가사 프롬프트를 비교합니다. 일치율은 충실도를 측정합니다. 가수가 모든 단어를 정확히 불렀는지, 아니면 줄을 건너뛰거나 구절을 흐리거나 음절을 환각(hallucinate)했는지 확인합니다. 저는 퍼센트 단위의 중첩도를 계산합니다. 이것은 미적 판단이 아니라, 텍스트 정확도에 대한 엄격한 계산입니다.
필터링(Filter). 일치율에 따라 테이크를 정렬합니다. 상위 20%가 오디션 후보군이 됩니다. 나머지는 보조 폴더로 이동합니다. 점수가 낮은 것들을 아직 삭제하지는 않았지만, 그것들에 소중한 청취 시간을 낭비하지는 않습니다.
심사위원의 독립성 유지
저는 한 가지 엄격한 규칙을 따릅니다. 생성 모델이 자신의 숙제를 직접 채점하게 해서는 안 된다는 것입니다. ACE-Step 1.5가 ACE-Step 1.5의 결과물을 평가하지 않습니다. 저는 전사를 위해 완전히 별개의 프로세스를 사용하는데, 스스로를 검사하는 모델은 항상 너무 관대하기 때문입니다. 모델은 동일한 사각지대를 공유합니다. 만약 생성 모델이 복수 표지를 생략하거나 강한 자음을 약하게 발음하는 경향이 있다면, 자기 평가 루프는 그 결함을 무시하도록 학습될 것입니다. 독립적인 음성 인식 모델은 음악에 대한 충성심이 없습니다. 그 보고가 아무리 가혹할지라도, 모델은 그저 들리는 대로 보고할 뿐입니다.
수치가 보여준 것
32개의 테이크 배치를 대상으로 파이프라인을 돌린 결과, 진지하게 검토할 가치가 있는 8개의 후보로 범위가 좁혀졌습니다. 이 8개는 평균 83.9%의 가사 일치율을 보였습니다. 이 곡들을 제대로 듣고 저만의 품질 기준에 따라 점수를 매긴 결과, 평균 100점 만점에 94.1점을 기록했습니다. 이 격차가 모든 것을 말해줍니다. 기계라는 관문이 가사 누락, 타이밍 붕괴, 보컬 아티팩트와 같은 명백한 구조적 실패를 걸러내 주었기에, 저의 인간적인 채점은 이미 정제된 세트를 대상으로 수행될 수 있었습니다. 자동화가 저의 판단을 대체한 것이 아니라, 판단력을 보존해 준 것입니다.
기계가 오작동할 때
낮은 점수가 항상 나쁜 노래를 의미하는 것은 아닙니다. 제가 정말 좋아했던 트랙이 커트라인보다 훨씬 낮은 점수를 받았을 때 이 사실을 일찍 깨달았습니다. 그 가사는 단순한 알파벳 찬트였습니다. 개별 글자를 독립된 소리로 노래하는 방식이었죠. Whisper는 자연스러운 문장 구조로 학습되었습니다. "A B C D"를 입력하면 모델은 종종 단어를 환각하거나, 관사를 삽입하거나, 글자들을 엉망진창인 음소로 뭉개버립니다. 전사는 실패했지만, 보컬 퍼포먼스는 실제로는 매우 선명했습니다.
그 사례를 통해 실질적인 한계를 배웠습니다. 일치율은 최종 판결이 아니라 사전 필터입니다. 점수가 낮게 나온 테이크라도 버리기 전에 10초간은 직접 들어보는 인간 오디션을 거칩니다. 수치는 확실성이 아닌 확률을 가리킬 뿐입니다. 점수를 나침반이 아닌 판사의 의사봉처럼 다룬다면, 좋은 음악을 버리게 될 것입니다.
기술적 난관
Apple Silicon에서 MLX를 실행 중이라면, 대량의 배치를 처리하기 전에 Python 아키텍처를 확인하세요. 흔히 하는 설정 실수 중 하나는 Rosetta 에뮬레이션을 통해 Python 바이너리를 실행하는 것입니다. 스크립트는 여전히 실행되지만, 로컬 전사를 원활하게 만들어 주는 하드웨어 가속을 사용할 수 없게 됩니다.
터미널에서 다음을 실행하세요:
python3 -c "import platform; print(platform.machine())"
arm64가 출력되어야 합니다. 만약 x86_64가 출력된다면, 현재 환경이 에뮬레이션 중인 것입니다. 네이티브 Python 빌드나 네이티브 conda 환경으로 전환한 다음, mlx-whisper를 다시 설치하세요. 긴 배치 작업의 경우, 에뮬레이션 실행과 네이티브 실행의 차이는 점심시간 전에 끝내느냐, 저녁시간 전에 끝내느냐의 차이만큼 큽니다.
진정한 가치
생성형 오디오는 끈기를 요구하지만, 인간의 주의력은 한정되어 있습니다. 단순히 철저함을 증명하기 위해 평범한 테이크 32개를 일일이 듣는 것에는 아무런 영광도 없습니다. 생성기와 제 귀 사이에 mlx-whisper를 배치함으로써, 저는 집중할 수 있는 창작 시간을 몇 시간이나 확보했습니다. 어떤 곡을 살리고 어떤 곡을 버릴지는 여전히 제가 결정합니다. 기계는 단지 제가 최선의 후보들에게 그 판단을 내릴 수 있도록 도와줄 뿐입니다.
이 파이프라인에 대한 자세한 내용은 여기에서 확인할 수 있습니다. 유사한 로컬 QA 도구를 구축하고 있다면, GyaanSetu community에서 정보를 나누기에 좋습니다.
