dev.to

I Built a Local AI Music Studio

로컬 AI 음악 스튜디오를 만들었습니다

Miso는 audio.cpp 위에서 동작하는 셀프 호스팅 음악 생성·리믹스 스튜디오입니다. 생성 결과뿐 아니라 프롬프트, 가사, 스템, MIDI, 점수와 작업 계보를 저장하며, 곡 일부를 다시 만들거나 보컬을 교체하고 멜로디를 새 편곡으로 옮길 수 있습니다.

AI 요약

Miso는 로컬 환경에서 음악을 생성하고 편집하는 셀프 호스팅 스튜디오입니다. 개발자는 명령줄 도구를 오가며 생성 파일을 정리하고, 어떤 파라미터 조합으로 원하는 결과를 얻었는지 기억해야 하는 불편에서 프로젝트를 시작했습니다. 처음에는 간단한 실험이었지만 데이터베이스, Docker Compose 구성, 작업 큐, 모델 관리자, 오디오 편집기, 파형 플레이어까지 붙었습니다. 현재는 약 40GB에 이르는 GPU 모델을 관리하는 작업 공간으로 확장됐습니다.

Miso가 저장하는 대상은 완성된 노래 하나가 아닙니다. 생성에 사용한 테이크, 프롬프트, 가사, 스템, 점수, 전사 결과와 각 결과물이 어떤 작업에서 파생됐는지 나타내는 계보를 함께 보관합니다. 특정 결과를 잃지 않고 한 가지 요소만 바꿔 다시 시도하려는 목적입니다. 전체 곡을 새로 생성하지 않고 중간의 8초만 고치거나, 보컬만 분리하거나, 가수를 바꾸거나, 같은 멜로디를 전혀 다른 스타일로 편곡하거나, 오디오를 MIDI로 바꿔 다른 도구에서 계속 작업하는 흐름을 하나의 프로젝트 안에 담습니다.

■ 여러 음악 모델을 하나의 작업 공간으로 묶기

Miso는 C++ 오디오 추론 런타임인 audio.cpp 위에서 여러 모델 계열을 연결합니다. ACE-Step 1.5는 전체 곡 생성, 커버, 기존 트랙의 특정 구간을 다시 만드는 repaint 작업을 담당하는 주력 모델입니다. YuE2는 노래를 생성하는 동시에 먼저 ABC 음악 점수를 계획하고 그 점수를 다시 돌려줍니다. MiniMax Music 3와 HeartMuLa도 별도 생성기로 제공하며, Stable Audio 3는 기악곡과 효과음 생성에 사용합니다. 여기에 스템 분리, 보컬 변환, 오디오 대 MIDI 전사를 맡는 모델이 따로 붙습니다.

모델마다 프롬프트 형식이 서로 다르다는 점도 Miso가 해결하려는 문제입니다. 어떤 모델은 프로덕션 설명문을 요구하고, 다른 모델은 짧은 설명과 쉼표로 나눈 태그를 요구합니다. ACE-Step은 스타일 정보, BPM과 조성, 가사를 서로 다른 입력으로 받습니다. Miso의 안내형 빌더는 사용자가 입력한 공통 UI 값을 선택한 모델의 문법에 맞게 변환합니다. 사용자는 ‘경쾌한 신스팝, 여성 보컬, 120 BPM’처럼 생각하면 되고, 120 BPM을 어떤 API 필드에 넣어야 하는지 모델마다 다시 외울 필요가 없습니다.

■ 파형 일부만 다시 생성하는 repaint

Miso의 중심 기능 가운데 하나는 repaint입니다. 사용자는 테이크를 불러온 뒤 파형에서 구간을 드래그하고, 선택한 부분만 새로 생성합니다. 코러스 한 곳이 마음에 들지 않는다고 곡 전체를 다시 만들 필요가 없습니다.

개발자는 ACE-Step의 repaint 경로가 텍스트 프롬프트에 기대한 만큼 반응하지 않는다는 점을 직접 실험했습니다. 주변에 남아 있는 음악이 교체 구간에 텍스트 설명보다 훨씬 강하게 영향을 줬습니다. 보컬 구간에서는 프롬프트로 스타일을 급격히 바꾸려는 시도보다 가사가 더 큰 통제력을 보였습니다. 일반 텍스트 대 음악 경로에 서로 정반대인 프롬프트를 넣었을 때 결과가 크게 달라졌지만, repaint 경로는 거의 반응하지 않았습니다. API 설명에 적힌 동작과 모델이 실제로 보이는 반응이 다를 수 있다는 점을 구현 과정에서 확인한 사례입니다.

■ 스템 분리와 보컬 교체

곡을 보컬과 반주로 나누거나, 보컬·드럼·베이스·기타 요소로 더 세밀하게 분리할 수 있습니다. 분리된 스템에는 별도 믹서가 붙습니다. 특정 스템만 들어보거나 음소거하고, 레벨을 조정하고, 보컬 변환 모델로 목소리를 바꾼 뒤 다시 믹스해 새로운 테이크로 저장합니다.

보컬 변환에는 서로 다른 특성을 가진 두 도구를 남겼습니다. RVC는 음질이 더 좋지만 함께 제공되는 음성 선택지가 적습니다. Vevo2는 출력 대역폭이 더 낮지만 프로젝트 안의 다른 보컬을 사실상 자유롭게 참조로 사용할 수 있습니다. 한 도구를 정답으로 내세우기보다 서로 다른 절충점을 가진 두 기능을 모두 노출하는 방식입니다.

■ MIDI 전사와 YuE2 점수 연결

버전 1.4.0에서는 기존에 따로 존재하던 기능을 하나의 흐름으로 연결했습니다. 이제 곡을 스템으로 나누고, 보컬 스템을 MIDI 음표로 전사하고, 음표 이벤트를 ABC 멜로디로 변환하고, 감지된 템포와 조성을 확인한 뒤 필요하면 수정할 수 있습니다. 그 결과를 YuE2에 넘겨 완전히 다른 스타일의 곡을 만들 수 있습니다. 녹음에서 멜로디를 추출해 새 편곡의 기반으로 삼는 과정입니다.

기능이 실제로 작동하는지 확인하기 위해 ‘반짝반짝 작은 별(Twinkle Twinkle Little Star)’의 단순한 버전을 만들고, 분리·전사·점수 변환 과정을 다시 통과시켰습니다. 녹음 전체에서 예상한 음높이를 되찾았지만 리듬은 음높이보다 덜 정확했습니다. 실제 보컬에서는 짧게 이어지거나 쪼개진 음표가 생기기도 했습니다. 그래도 YuE2가 사용할 수 있는 결과를 얻었습니다.

■ 시스템 구성과 일반 오디오 편집

Miso는 두 개의 Docker 컨테이너로 실행합니다. 하나는 Miso 애플리케이션을 실행하고, 다른 하나는 GPU 모델을 소유한 audio.cpp 서버를 실행합니다. 브라우저가 audio.cpp에 직접 연결하지 않고 Miso를 거쳐 추론 백엔드와 통신하는 구조입니다. 덕분에 모델 백엔드가 중단돼도 프로젝트, 가져오기, 재생, 내보내기와 편집 기능은 계속 동작합니다. GPU가 있는 다른 컴퓨터에서 audio.cpp를 실행하고 Miso는 별도 위치에서 실행하는 구성도 가능합니다.

애플리케이션은 React, TypeScript, Vite, Node, Hono, SQLite로 구성했습니다. 자르기, 페이드, 게인 조절, 정규화, 분할, WAV 변환과 MP3 내보내기처럼 거대한 AI 모델이 필요하지 않은 작업은 대부분 브라우저에서 처리합니다. 모든 오디오 작업을 서버 작업 큐로 보내지 않고 일반적인 편집 기능은 일반적인 방식으로 실행합니다.

가사 작성과 프롬프트 확장에는 선택적으로 OpenAI 호환 API 또는 로컬 llama.cpp 서버를 연결할 수 있습니다. 다만 이 언어 모델 기능은 음악 모델과 분리되어 있습니다. Miso가 프롬프트를 몰래 고쳐 쓰지 않고, 제안 내용을 먼저 보여준 뒤 사용자가 채택 여부를 결정합니다. 확장된 프롬프트를 사용하면 원래 입력과 실제 생성에 사용한 버전을 둘 다 보관합니다. 생성 결과가 달라진 이유를 추적할 수 있도록 하기 위한 설계입니다.

■ 구현 과정에서 다룬 문제

개발자가 실제로 부딪힌 문제는 모델을 호출하는 코드 자체보다 주변 시스템에 많았습니다. 모델마다 필요한 샘플레이트가 달랐고, 한 번에 여러 개의 큰 오디오 파일을 반환했습니다. VRAM에 맞추기 위해 여러 구성 요소를 순서대로 로드해야 하는 모델도 있었습니다. 작업 하나가 몇 분씩 걸리며, 브라우저 탭이 닫혀도 업로드가 유지돼야 했습니다. API가 특정 파라미터를 받는다고 명시해도 요청의 잘못된 위치에 넣으면 조용히 무시하는 경우가 있었습니다. 재현 가능한 결과를 위해 충분한 생성 이력을 남겨야 했고, 비싼 작업 하나만 실행할 수 있는 백엔드의 제약도 처리해야 했습니다. UI, Miso 서버, 추론 런타임 가운데 어느 계층에 각 동작을 배치할지도 직접 정해야 했습니다.

Miso는 오픈 소스로 공개됐습니다. 현재는 개발자 자신의 Linux 환경과 RTX 4090 노트북 GPU에서 주로 테스트했습니다. 모든 GPU, 드라이버, 운영체제와 모델 조합을 검증했다고 주장하지는 않습니다. 작은 로컬 음악 모델 실험 도구에서 출발해 생성, 부분 재생성, 스템 믹싱, 음성 교체, 멜로디 전사와 결과 추적을 한곳에 담은 스튜디오로 커졌습니다.

원문: dev.to / 번역·요약: Trawling