
AI로 BGM을 생성하는 앱을 만들어 보았다
요약
Gemini를 활용하여 자연어 프롬프트로 BGM을 생성하는 ABMM 앱 개발 사례를 소개합니다. MIDI 데이터 생성부터 DAW 연동까지 이어지는 2단계 파이프라인과 음악적 품질을 높이기 위한 알고리즘 해결 과정을 다룹니다.
핵심 포인트
- Gemini 기반의 2단계 음악 생성 파이프라인 구축
- 악기 및 섹션별 멀티트랙 MIDI 생성으로 DAW 편집 효율 극대화
- 물리 파라미터(Brightness, Energy 등)를 통한 직관적 음악 조정
- 옥타브 되돌림 알고리즘을 통한 MIDI 음역대 문제 해결
「영상 편집이나 게임 개발에 저작권 프리이면서 분위기에 딱 맞는 BGM이 필요해」
「명곡의 코드 진행이나 분위기를 베이스로 하여, 다른 장르풍으로 어레인지한 음악을 AI로 만들어 보고 싶어」
그래서 Gemini를 사용하여, ABMM (AI Background Music Maker) 을 만들어 보았습니다.
예를 들어 「Wonderwall을 EDM 풍으로 어레인지해 줘」라고 지시하면, AI가 코드 진행 검색부터 MIDI 작곡을 거쳐 GarageBand로 즉시 내보내기까지 할 수 있습니다.
아직 만족스러운 수준은 아니지만, 꽤 재미있는 것이 완성되었습니다.
이하는 코드를 작성한 Gemini가 만들어 준 아키텍처 등의 해설입니다.
본 기사에서는 ABMM의 개요, 기술 스택, 그리고 「AI 작곡 특유의 벽」을 어떻게 극복했는지에 대한 아키텍처와 고안점을 소개합니다.
ABMM은 **「Phase 1: 고속 MIDI 프리뷰」**와 **「Phase 2: 본편 음성 내보내기」**의 2단계 구성을 채택한 이단 구성의 음악 생성 파이프라인을 갖추고 있습니다.
[ 사용자 프롬프트 ] ───▶ [ 온라인 코드 검색 / DB 매치 ]
│
▼
...
자연어 프롬프트 + 온라인 코드 해석
「비틀즈의 곡을 EDM 풍으로」, 「Chillhop 스타일의 작업용 BGM」 등의 지시를 받으면, 온라인에서 실제 코드 진행을 자동으로 취득합니다. 없다면 LLM이 음악 이론에 기반하여 자동으로 생성합니다. -
DAW 편집에 최적화된 섹션별 멀티트랙 MIDI
생성되는 MIDI 데이터는 Dist. Guitar - Verse나 Pick Bass - Chorus와 같이, **악기 × 섹션 종류 (Intro / Verse / Chorus / Bridge)**별로 트랙이 분할됩니다. GarageBand나 Logic Pro, Ableton 등에 드래그 앤 드롭했을 때의 편집 효율이 극적으로 향상됩니다. -
감각적인 물리 파라미터 조정
템포나 키뿐만 아니라, Brightness (밝기), Energy (음량·다이내믹스), Density (음수·리미트) 슬라이더로 악곡의 뉘앙스를 조정할 수 있습니다. -
GarageBand 원클릭 연동 (macOS)
프리뷰를 듣고 마음에 들면, 버튼 한 번으로 GarageBand가 실행되며 생성된 멀티트랙 MIDI가 즉시 로드됩니다.
GUI / Frontend: Vanilla HTML5 / CSS3 / JavaScript (pywebview) - 다크 모드 기반의 모던 CSS + WKWebView 연동
- Backend Core: Python 3.14 -
AI / LLM Integrations: Ollama (로컬 LLM) / Online APIs (Gemini, Claude 등) -
Audio Synthesis / MIDI:mido,pretty_midi,FluidSynth(SoundFont rendering) -
Testing & Quality Assurance: pytest (60개 이상의 자동 테스트·디그레션 방지 스위트)
개발 프로세스에서 특히 음악 생성의 품질 측면에서 몇 가지 기술적 과제에 직면했습니다. 이를 어떻게 해결했는지 소개합니다.
【과제】
MIDI 생성 시, 고음역대의 튀어나옴을 방지하려고 min(raw_pitch, 84)와 같은 상한 클립(upper clip)을 설정했더니, 계산된 고음(D5, E5, G5 등)이 모두 최고음인 84 (C6)로 뭉개져서, 어떤 곡을 만들어도 「C6의 단조로운 멜로디」가 되어버리는 현상이 발생했습니다.
【해결책】
단순한 상한 컷이 아니라, **음악적인 옥타브 되돌림 알고리즘 (fit_pitch_in_range)**을 도입했습니다.
def fit_pitch_in_range(pitch: int, min_p: int = 60, max_p: int = 84) -> int:
"""음정 차(멜로디의 기복·도수)를 유지한 채 옥타브를 상하로 이동하여 표준 음역대에 수용함"""
while pitch > max_p:
...
이를 통해 코드 진행의 도수와 음정 차이를 100% 유지한 채, 보컬이나 리드 기타로서 가장 듣기 편한 음역대(C4~C6)로 자연스럽게 매핑되어, 곡마다 기복이 있는 아름다운 선율이 생성되게 되었습니다.
【과제】
"Wonderwall을 Nirvana 스타일로"라고 입력했을 때, 로컬 DB에 "Nirvana = Rock"이라는 정의가 존재하면 온라인 검색이 스킵되어, Wonderwall 본래의 코드 진행이 아닌 DB에 고정된 코드로 대체되어 버리는 문제가 있었습니다.
【해결책】
처리 플로우를 정리하여, "DB 매치는 스타일의 힌트로 활용하되, 온라인 코드 검색을 항상 병행 실행하여 곡 본래의 코드를 우선적으로 반영하는" 로직으로 개수하였습니다. 또한, 취득한 방대한 양의 코드를 중복 제거 및 섹션 분할(Verse/Chorus)함으로써, 곡의 코드 진행과 어레인지 스타일의 완전한 양립을 실현했습니다.
【과제】
macOS 상의 pywebview (WKWebView) 환경에서, CSS의 .hidden 클래스 전환을 통한 UI 표시 변경이 발화되지 않거나, 정적 파일의 강력한 캐시로 인해 변경 사항이 반영되지 않는 트러블이 발생했습니다.
【해결책】
- 클래스 조작에서 인라인 제어로 이행:
exportCard.style.display = "flex"와 같이 직접 쓰는 방식으로 전환. - 우측 패널 스크롤 대응:
.panel에overflow-y: auto를 부여하여, 넘치는 카드를 확실하게 렌더링하고 스크롤할 수 있도록 조치. - 캐시 버스터(Cache Buster) 도입:
style.css?v=6이나app.js?v=6과 같이 쿼리 파라미터를 추가하여 캐시를 무효화.
ABMM은 단순히 "AI가 곡을 만드는" 것에 그치지 않고, "인간 크리에이터가 DAW에서 이차 활용 및 편곡하기 쉬운 형태로 출력하는" 실천적인 워크플로우를 중시하여 설계되었습니다.
향후에는 뉴럴 음성 합성 (HQ Neural Renderer)의 추가적인 고속화 및 사용자별 프리셋 공유 기능의 확충을 진행할 예정입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기