Nightingale: 내 음악 라이브러리로 즐기는 ML 기반 노래방 애플리케이션

Nightingale 소개

노래방을 즐기기 위해 별도의 콘텐츠를 구매하거나 특정 서비스에 가입해야 했던 경험을 한 번쯤 해보셨을 것입니다. Nightingale은 이미 보유하고 있는 음악 파일이나 영상 파일을 그대로 활용해 노래방 환경을 자동으로 구성해주는 오픈소스 애플리케이션입니다. 별도로 반주를 구하거나 가사를 입력할 필요 없이, 파일 하나만 제공하면 음원 분리(Stem Separation)부터 가사 동기화, 실시간 음정 채점까지 전 과정을 자동으로 처리합니다. Rust로 작성된 단일 실행 파일로 배포되며, 머신러닝 모델과 Python 환경까지 첫 실행 시 자동으로 설치됩니다.

Nightingale은 게임 엔진인 Bevy를 기반으로 구축된 데스크톱 애플리케이션입니다. Bevy는 Rust 생태계에서 널리 쓰이는 ECS(Entity Component System) 기반의 게임 엔진으로, GPU 셰이더를 활용한 시각적 효과 렌더링과 게임패드 입력 처리에 적합합니다. Nightingale은 이 엔진 위에서 음원 분리, 음성 인식, 실시간 마이크 입력 처리를 결합하여, 일반적인 노래방 앱과 유사한 경험을 로컬 환경에서 제공합니다. 백엔드에서는 PyTorch와 ONNX Runtime이 ML 추론을 담당하고, 프론트엔드 렌더링과 게임 로직은 Bevy가 처리하는 구조입니다. 전체 코드베이스의 80.2%가 Rust, 10.7%가 Python으로 구성되어 있으며, WGSL 셰이더 코드도 포함되어 있습니다.

Nightingale의 동작 원리

Nightingale의 처리 흐름은 다음과 같습니다:

음악/영상 파일
    │
    ▼
음원 분리 (UVR Karaoke 모델 또는 Demucs)
    │
    ├── 반주(instrumental)
    └── 보컬(vocals)
         │
         ▼
    가사 조회 (LRCLIB) → 없으면 WhisperX로 전사(Transcription) + 정렬(Alignment)
         │
         ▼
    Bevy 앱 (반주 재생 + 가사 동기화 + 음정 채점 + 배경 효과)

음원 분리 단계에서는 UVR(Ultimate Vocal Remover) Karaoke 모델을 기본으로 사용하며, Demucs로 전환하는 것도 가능합니다. UVR 모델은 ONNX Runtime을 통해 실행되며, CUDA 또는 CoreML 가속을 자동으로 감지합니다. 분리된 보컬 트랙은 가이드 보컬로 활용할 수 있고, 볼륨을 조절하여 따라 부르기 연습에 활용하거나 완전히 끌 수도 있습니다. 처리 결과는 ~/.nightingale/cache/ 디렉토리에 blake3 해시 기반으로 캐시되므로, 동일 파일을 다시 열 때는 재처리 없이 즉시 재생됩니다.

가사 동기화는 두 가지 경로로 처리됩니다. 먼저 LRCLIB에서 해당 곡의 싱크드 가사(synced lyrics)를 조회하고, 없는 경우 WhisperX(large-v3 모델)로 오디오를 직접 전사합니다. WhisperX는 OpenAI Whisper를 기반으로 단어 단위 타임스탬프 정렬(word-level alignment)을 지원하는 모델로, 가사의 각 단어가 정확히 어느 시점에 발음되는지를 추출합니다. 이를 통해 노래방의 핵심 요소인 단어별 하이라이트 가사 표시가 가능해집니다.

Nightingale의 주요 기능

음원 분리 및 가사 처리

음원 분리(Stem Separation)는 UVR Karaoke 모델 또는 Demucs를 통해 수행됩니다. 분리된 보컬의 볼륨을 조절할 수 있어, 완전한 MR 모드와 가이드 보컬이 포함된 연습 모드 사이를 자유롭게 선택할 수 있습니다.

지원 오디오 형식은 mp3, flac, ogg, wav, m4a, aac, wma이며, 영상 파일(mp4, mkv, avi, webm, mov, m4v)도 직접 지원하여 뮤직비디오나 라이브 영상에서 오디오를 추출해 처리할 수 있습니다. 전사(Transcription) 결과는 캐시에 저장되므로, 처음 처리 이후에는 빠르게 재생을 시작할 수 있습니다.

실시간 음정 채점

마이크로 부른 음정을 실시간으로 감지하여 채점하는 기능이 내장되어 있습니다. 채점 결과는 별(star) 등급으로 표시되며, 곡마다 점수 기록이 저장됩니다. 여러 플레이어 프로필을 생성하여 각자의 점수 히스토리를 독립적으로 관리할 수 있어, 여럿이 함께 즐기는 환경에서도 개인별 기록을 추적할 수 있습니다. 점수판(scoreboard)은 곡별로 관리됩니다.

배경 테마 및 시각 효과

7가지 배경 테마를 제공합니다. Plasma, Aurora, Waves, Nebula, Starfield 등 5가지는 GPU 셰이더로 렌더링되는 실시간 그래픽 효과이며, Pixabay의 영상 배경도 지원합니다. 영상 파일을 재생할 경우 해당 영상 자체를 배경으로 사용하는 것도 가능합니다. UI는 4K 해상도까지 적응형 스케일링을 지원합니다.

게임패드 지원 및 자급자족 구조

게임패드로 전체 UI를 탐색하고 제어할 수 있어, TV에 연결된 환경에서도 편리하게 사용할 수 있습니다. D-패드, 아날로그 스틱, 페이스 버튼 모두 지원합니다. 특히 Nightingale의 중요한 설계 특징 중 하나는 완전한 자급자족(self-contained) 구조입니다. ffmpeg, Python 3.10, uv 패키지 매니저, 가상 환경, PyTorch, ML 모델 등 모든 의존성이 첫 실행 시 ~/.nightingale/vendor/ 디렉토리에 자동으로 다운로드되어 설치됩니다. 사용자가 별도로 Python이나 ffmpeg를 설치할 필요가 없습니다.

하드웨어 지원

백엔드 디바이스 비고
CUDA NVIDIA GPU 가장 빠름
MPS Apple Silicon WhisperX 정렬 단계는 CPU 폴백
CPU 모든 환경 가장 느림

GPU 환경에서는 곡당 약 2~5분, CPU 환경에서는 약 10~20분의 처리 시간이 소요됩니다. 처리 결과는 캐시되므로 이후 재생 시에는 이 대기 시간이 발생하지 않습니다.

Nightingale 설치 및 사용

Nightingale 설치를 위해서는 GitHub Releases 페이지에서 각 플랫폼에 맞는 바이너리를 다운로드합니다. 지원 플랫폼은 Linux x86_64, Linux aarch64, macOS ARM(Apple Silicon), macOS Intel, Windows x86_64입니다.

macOS에서는 Gatekeeper의 격리 속성을 제거해야 정상 실행됩니다.

xattr -cr Nightingale.app

첫 실행 시 ML 모델과 의존성 도구들이 자동으로 다운로드됩니다(약 2~5분 소요). 이후에는 앱을 열고 음악 파일을 선택하면 자동으로 음원 분리와 가사 처리가 시작됩니다.

소스 코드에서 직접 빌드하려면 Rust 1.85 이상이 필요합니다. Linux에서는 추가로 libasound2-dev, libudev-dev, libwayland-dev, libxkbcommon-dev 패키지가 필요합니다.

git clone https://github.com/rzru/nightingale
cd nightingale
cargo build --release

라이선스

Nightingale 프로젝트는 GPL-3.0 라이선스로 공개되어 있습니다. GPL-3.0은 카피레프트(copyleft) 라이선스로, 이 소프트웨어를 수정하거나 기반으로 한 파생 저작물을 배포할 경우 동일한 GPL-3.0 라이선스를 적용해야 합니다.

:house: Nightingale 공식 홈페이지

:github: Nightingale 프로젝트 GitHub 저장소

더 읽어보기




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다! (기본은 Weekly지만 Daily로 변경도 가능합니다.)

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: