[pop2piano] AIでピアノカバーを生成する

2022年11月5日土曜日

Artificial Intelligence

本記事では、pop2pianoと呼ばれる機械学習手法を用いて、任意の音楽からピアノカバーを生成する方法をご紹介します。

アイキャッチ

pop2piano

概要

pop2pianoは、音楽(pop)からピアノカバーを生成するpop piano coverタスクを実現する技術です。

従来技術では、popとpiano coverのペアデータセットが不足しており、最新のデータ集約型ディープラーニング手法の適用が困難でした。

このため本研究では、pop, piano coverのデータセットを自動生成するパイプラインを構築し、これらのデータセットを用いてTransformerベースのpop2pianoでトレーニングしています。

論文中では、メロディーとコード抽出モジュールなしでpopオーディオから直接ピアノカバーを生成する初めてのモデルであると示されています。

Architecture
出典: Pop2Piano : Pop Audio-based Piano Cover Generation

詳細はこちらの論文をご参照ください。

本記事では上記手法を用いて、任意の音楽からピアノカバーを生成していきます。

デモ(Colaboratory)

それでは、実際に動かしながらピアノカバーを生成します。
ソースコードは本記事にも記載していますが、下記のGitHubでも取得可能です。
GitHub - Colaboratory demo

また、下記から直接Google Colaboratoryで開くこともできます。
Open In Colab

なお、このデモはPythonで実装しています。
Pythonの実装に不安がある方、Pythonを使った機械学習について詳しく勉強したい方は、以下の書籍やオンライン講座などがおすすめです。

環境セットアップ

それではセットアップしていきます。 Colaboratoryを開いたら下記を設定しGPUを使用するようにしてください。

「ランタイムのタイプを変更」→「ハードウェアアクセラレータ」をGPUに変更

初めにGithubからソースコードを取得します。
安定動作のため本ブログ記載時のcommitをチェックアウトします。

!git clone https://github.com/sweetcocoa/pop2piano/

# Commits on Nov 3, 2022
!cd /content/pop2piano
!git checkout e79dcf312d436fecf2a065f6d5a5f65c31b03479

次にライブラリをインストールします。

%cd /content/pop2piano

!apt-get install -y fluidsynth
!pip install pretty-midi==0.2.9 omegaconf==2.1.1 youtube-dl==2021.12.17 transformers==4.16.1 pytorch-lightning essentia==2.1b6.dev609 note-seq==0.0.3 pyFluidSynth==1.3.0

!pip install moviepy==0.2.3.5 imageio==2.4.1
!pip install yt-dlp

最後にライブラリをインポートします。

%cd /content/pop2piano

import os 
import sys

import glob
import random

import torch
import torchaudio
import librosa
import numpy as np
import pandas as pd
import IPython.display as ipd
import soundfile as sf
from google.colab import files

from tqdm.auto import tqdm
from omegaconf import OmegaConf
import note_seq

from utils.dsp import get_stereo
from utils.demo import download_youtube
from transformer_wrapper import TransformerWrapper
from midi_tokenizer import MidiTokenizer, extrapolate_beat_times
from preprocess.beat_quantizer import extract_rhythm, interpolate_beat_times

from yt_dlp import YoutubeDL
from moviepy.video.fx.resize import resize
from moviepy.editor import VideoFileClip

device = "cuda" if torch.cuda.is_available() else "cpu"
print("using device:", device)

以上で環境セットアップは完了です。

学習済みモデルのセットアップ

ここでは、論文発表元が公開する事前学習済みモデルをGoogle Colaboratoryにダウンロードします。

%cd /content/pop2piano

!wget -c https://github.com/sweetcocoa/pop2piano/releases/download/dpi_2k_epoch/model-1999-val_0.67311615.ckpt \
      -O model-1999-val_0.67311615.ckpt

ダウンロードしたモデルをメモリ上にロードします。

%cd /content/pop2piano

config = OmegaConf.load("./config.yaml")
wrapper = TransformerWrapper(config)
wrapper = wrapper.load_from_checkpoint("model-1999-val_0.67311615.ckpt", config=config).to(device)
model = "dpipqxiy"
wrapper.eval()

入力音声のセットアップ

ここでは、モデルに入力するpop audioをセットアップします。

本ブログではYoutubeDLライブラリを用いて、Youtube上の動画から音声を取得します。
まず、以下の通り任意のURLを切り抜き範囲を指定します。

video_url = 'https://www.youtube.com/watch?v=Qd01-6xVSHk' #@param {type:"string"}

#@markdown 動画の切り抜き範囲(秒)を指定してください。\
#@markdown 30秒以上の場合OOM発生の可能性が高いため注意
start_sec =  56#@param {type:"integer"}
end_sec =  88#@param {type:"integer"}

(start_pt, end_pt) = (start_sec, end_sec)

設定に従い動画をダウンロードします。

%cd /content/pop2piano

!mkdir -p test_video test_audio

download_resolution = 720
full_video_path = './test_video/full_video.mp4'
input_clip_path = './test_video/clip_video.mp4'
input_audio_path = './test_audio/clip_audio.mp3'

# 動画ダウンロード
ydl_opts = {'format': f'best[height<={download_resolution}]', 'overwrites': True, 'outtmpl': full_video_path}
with YoutubeDL(ydl_opts) as ydl:
    ydl.download([video_url])

# 指定区間切り抜き
with VideoFileClip(full_video_path) as video:
    subclip = video.subclip(start_pt, end_pt)
    subclip.write_videofile(input_clip_path)

取得した動画から音声のみ抽出します。

# 動画から音声を切り抜き
videoclip = VideoFileClip(input_clip_path)

audioclip = videoclip.audio
audioclip.write_audiofile(input_audio_path)

audioclip.close()
videoclip.close()

pop2piano

ここでは、用意した音声ファイルをモデルに入力しピアノカバーを生成します。
まずアレンジャーのタイプを選択します。特にこだわりがなければcomposer1が最もベーシックな出力結果が得られます。

# @markdown set Arranger
composer = "composer1" #@param['composer1', 'composer2', 'composer3', 'composer4', 'composer5', 'composer6', 'composer7', 'composer8', 'composer9', 'composer10', 'composer11', 'composer12', 'composer13', 'composer14', 'composer15', 'composer16', 'composer17', 'composer18', 'composer19', 'composer20', 'composer21']

pop2pianoを実行します。

pm, composer, mix_path, midi_path = wrapper.generate(
    audio_path=input_audio_path, 
    composer=composer, 
    model=model,
    show_plot=True, 
    save_midi=True, 
    save_mix=True, 
)
note_seq.plot_sequence(note_seq.midi_to_note_sequence(pm))

出力結果は以下の通りです。
pop audioとpiano coverのmix
piano coverのみ
pop audioのみ
の計3種類が出力されます。

まとめ

本記事では、pop2pianoを用いて、popオーディオからピアノカバーを生成する方法をご紹介しました。
データセットの充実と共に、様々なカバータイプなど発展していきそうな分野です。

また本記事では、機械学習を動かすことにフォーカスしてご紹介しました。
もう少し学術的に体系立てて学びたいという方には以下の書籍などがお勧めです。ぜひご一読下さい。


また動かせるだけから理解して応用できるエンジニアの足掛かりに下記のUdemyなどもお勧めです。

参考文献

1.  論文 - Pop2Piano : Pop Audio-based Piano Cover Generation

2. GitHub - sweetcocoa/pop2piano

AIで副業ならココから!

まずは無料会員登録

プロフィール

メーカーで研究開発を行う現役エンジニア
組み込み機器開発や機会学習モデル開発に従事しています

本ブログでは最新AI技術を中心にソースコード付きでご紹介します


Twitter

カテゴリ

このブログを検索

ブログ アーカイブ

TeDokology