Machine Learning & DeepLearning

음원 분리를 위한 Spleeter 모델 구축: 환경 구성, 학습 및 테스트 방법

gellygelly 2023. 10. 18. 23:24

Spleeter 

Spleeter는 Python 음원 분리 라이브러리로, 보컬 및 여러 악기로 이루어진 혼합 음원에서 보컬 및 각각의 악기를 분리할 수 있다.

2stems, 4stems, 5stems의 3가지 분리 방식을 제공하며 각 분리 방식별 사전 훈련된 모델을 제공한다. 

 

  • 2stems: Vocals (singing voice) / accompaniment separation
  • 4stems: Vocals / drums / bass / other separation (※2stems, 4stems 모델은 musdb dataset에서 높은 성능을 보임)
  • 5stems: Vocals / drums / bass / piano / other separation

※github link: https://github.com/deezer/spleeter

 

GitHub - deezer/spleeter: Deezer source separation library including pretrained models.

Deezer source separation library including pretrained models. - GitHub - deezer/spleeter: Deezer source separation library including pretrained models.

github.com

 

Spleeter 환경 구성

1-1. For Spleeter Separate 

conda env create -n spleeter   # 1. spleeter anaconda 환경 생성
conda activate spleeter   # 2. spleeter 가상환경 활성화
conda install -c conda-forge ffmpeg libsndfile   # 3. 필요 패키지 및 라이브러리 설치
pip install spleeter   # 4. spleeter 설치

1-2. For Spleeter train / test 

spleeter train 및 test를 위해서는 추가로 몇 가지 패키지를 더 설치해야 한다. 

Git의 Spleeter Repo에서 anaconda yaml 파일과 docker file을 모두 제공하고 있으므로 해당 파일들을 이용해서 환경 구축을 하면 된다. 

 

Anaconda

  1. 위 spleeter github link로 이동
  2. conda/spleeter 폴더로 이동
  3. meta.yaml 파일 다운로드
  4. conda env create --file meta.yaml을 통해 spleeter 환경 import하기

Docker

  1. spleeter github link로 이동
  2. docker 폴더로 이동
  3. docker 폴더에 있는 .dockerfile을 이용해서 docker 이미지 생성 - docker build [dockerfile 경로] -t [이미지 이름]
  4. docker run [이미지 이름]

Spleeter separate

spleeter separate -p spleeter:4stems -o [output folder path] [file path]

ex) spleeter separate -p spleeter:4stmes -o output audio_example.mp3

위 명령어를 실행하면 pretrained_models 폴더가 생성되며 4stems 모델을 다운로드 받고 separate를 수행한다. 

수행 결과는 4stems이므로 vocals.wav, bass.wav, drums.wav. other.wav 4개 개별 악기 음원으로 나오게 된다. 

Spleeter train / test   

1. 필요 데이터 목록 (4stems 분류 방식 기준)

  • 곡 wav 파일 및 원하는 분리 방식으로 분리된 악기별 wav 파일 - mixture.wav, vocals.wav, bass.wav, drums.wav, other.wav 

<곡별 wav 파일 디렉토리 구조>

SpleeterDataset

├── train

   └── Song1

       ├── mixture.wav

       ├── vocals.wav

       ├── drums.wav

       ├── bass.wav

       ├── other.wav

    └── Song2

      ├── mixture.wav

      ├── vocals.wav

      ├── …
  • 설정 파일 - config.json

아래 파일은 spleeter/configs/4stems의 base_config.json 파일로, 학습 및 테스트 시 필요한 설정들을 담고 있는 파일이다.

# TODO로 주석을 단 부분은 반드시 경로 설정이 필요하다.

train_csv, validation_csv는 각 csv 파일 경로에 맞게 적어주고, model_dir도 원하는 경로를 입력해주면 되고, 나머지 파라미터는 원하는 대로 조정하면 된다. 

{
    "train_csv": "path/to/train.csv", # TODO
    "validation_csv": "path/to/test.csv", # TODO
    "model_dir": "4stems", # TODO
    "mix_name": "mix",
    "instrument_list": ["vocals", "drums", "bass", "other"],
    "sample_rate":44100,
    "frame_length":4096,
    "frame_step":1024,
    "T":512,
    "F":1024,
    "n_channels":2,
    "separation_exponent":2,
    "mask_extension":"zeros",
    "learning_rate": 1e-4,
    "batch_size":4,
    "training_cache":"training_cache",
    "validation_cache":"validation_cache",
    "train_max_steps": 1500000,
    "throttle_secs":600,
    "random_seed":3,
    "save_checkpoints_steps":300,
    "save_summary_steps":5,
    "model":{
        "type":"unet.unet",
        "params":{
               "conv_activation":"ELU",
               "deconv_activation":"ELU"
        }
    }
}
  • 각 wav 파일(mixture, vocals, bass, drum, other) 경로가 담긴 csv 파일 - train_csv, validation.csv

학습 및 테스트 데이터들의 경로 및 duration(음원 길이) 정보를 csv 파일로 만들어 제작해야 한다.

곡별 mix_path, vocals_path, drums_path, bass_path, other_path, duration으로 열을 구성하여 각 곡별 정보를 넣어 train.csv, validation.csv 파일을 구성한다.

csv 파일을 제작한 후엔 해당 csv 파일의 경로를 config.json 파일에 반영한다. 

musdb_train.csv

참고로 wav 파일의 duration은 아래 코드를 통해 간단하게 구할 수 있다. 

# use wave lib
import wave
def get_wave_duration(audio_path):
    audio = wave.open(audio_path)
    frames = audio.getnframes()
    rate = audio.getframerate()
    duration = frames / float(rate)
    return duration

# use librosa lib
import librosa
def get_wav_duration(audio_path):
    y, sr = librosa.load(audio_path)
    wav_duration = librosa.get_duration(y=y, sr=sr)

    return wav_duration

 

2. wav 데이터 전처리

1) stereo type 변환

mono type의 wav는 학습 시 오류가 발생하여 중단되므로, 반드시 사전에 모든 wav(악기별 분리 wav 포함)를 stereo 타입으로 변환해야 한다. 

 

# mono2stereo

from pydub import AudioSegment

def mono2stereo(file_path):
    left_channel = AudioSegment.from_wav(file_path)
    right_channel = AudioSegment.from_wav(file_path)

    stereo_sound = AudioSegment.from_mono_audiosegments(left_channel, right_channel)
    stereo_sound = stereo_sound.set_frame_rate(44100)
    stereo_sound = stereo_sound.set_sample_width(2)
    stereo_sound.export(file_path, format='wav')

 

2) 곡별 wav 파일 길이 맞추기

곡 폴더 내 5개 wav의 길이는 동일해야 한다. 중요한 점은, 파일 탐색기 상으로 볼 때의 길이가 아니라 wav 의 frame 수가 완전히 동일해야 한다. 

위 이미지와 같이 길이가 모두 3:46초로 동일하더라도 각 wav의 frame 수는 조금씩 차이날 수 있다. frame 수를 1의 자리까지 동일하게 맞춰줘야 모델 evaluate 시 에러가 발생하지 않는다. 

wav 음원의 frame 수가 맞지 않을 시 발생하는 에러 메시지

wav의 frame 수는 wave 라이브러리의  getparams() 함수로 확인하거나 다른 audio 라이브러리로 읽어들였을 때 data type이 ndarray인 경우 np.shape로도 확인 가능하다. 

import wave

wav = wave.open('song.wav')
print(wav.getparams())

# output
# _wave_params(nchannels=2, sampwidth=2, framerate=48000, nframes=11906909, comptype='NONE', compname='not compressed')

※참고: nframes = duration(오디오 파일의 길이) * sampligRate

 

3) 무음 wav 처리

학습 및 테스트를 진행할 때 간혹 특정 곡에는 drums, bass, vocals, other 중 어느 하나 혹은 여러 악기가 없을 수도 있다. 학습 및 테스트를 위해서는 반드시 원곡 wav 및 각 악기별 분리 wav 파일이 필요하므로 이럴 경우 해당 악기를 무음으로 처리해서 넣어줘야 한다. 다만 이럴 경우 아래와 같은 에러 메시지가 뜰 수 있으므로, 해당 에러가 발생할 시 audio 라이브러리를 이용해 해당 무음 wav 파일을 로드한 후 전부 0으로 되어있는 ndarray 데이터의 일부를 0.00001 등 아주 작은 숫자로 일부 변경해준 뒤 테스트를 진행하면 된다. 

 

3. train

  • spleeter train -p [config.json 파일 경로] -d [데이터셋 폴더 경로]

4. Test

  • spleeter evaluate -p [config.json 파일 경로] --mus_dir [데이터셋 폴더 경로] -o [결과 폴더 경로] --mwf