Meta のオーディオ生成 AI モデル、AudioGen を macOS の MPS (GPU) で動かす

Facebook でおなじみの Meta 社がリリースした AudioCraft は、英語のテキストから音楽や音声 (効果音) を生成できる AI です。2023年 6月に最初の v0.0.1 が、そして 2024年 5月には v1.3.0 がリリースされており、ローカルでも実行できます。ただし、生成に使えるのは NVIDIA GPU もしくは CPU となり、macOS では CPU のみしか正式に対応していません。悔しいですよね。いろいろ調べて試した結果、効果音を生成する AudioGen であれば Apple Silicon の GPU である MPS (Metal Performance Shaders) を使って生成速度を上げることができました。本記事ではその方法を公開します。

AudioCraft: https://ai.meta.com/resources/models-and-libraries/audiocraft

GitHub: https://github.com/facebookresearch/audiocraft

はじめに

AudioCraft のコードは MIT ライセンスでリリースされていますが、モデルの重み (Hugging Face からダウンロードされる学習済みファイル) は CC-BY-NC 4.0 という、商用利用不可のライセンスでの公開となります。生成物を何らかの形で公開する際はご注意ください。

AudioCraft には、音楽を生成する MusicGen というモデルも含まれています。また、より新しく、速く、高性能らしい MAGNeT というモデルもあるのですが、これらを MPS で動かすことはできませんでした。動きは活発ではないものの、open の issue もいくつか GitHub にあるので、そのうち正式対応するかもしれません。ただ、ローカルで無料で動かせるとは言え Stable Audio の様に使用料を払えば商用利用できるというわけでもなく、OSS プログラマーのチャレンジ精神以外の力が積極的に働くこともなさそうなので、過度な期待はできないと思っています。

環境構築

動作確認ができた環境

macOS: 14.5
ffmpeg version 7.0.1

環境構築手順

入っていなければ、ffmpeg をインストール (もちろん brew が必要です)

brew install ffmpeg

ディレクトリを作って AudioCraft リポジトリをクローン。ディレクトリ名はお好きにどうぞ

mkdir AudioCraft_MPS
cd AudioCraft_MPS
git clone https://github.com/facebookresearch/audiocraft.git .

仮想環境を構築して入る。ボクは得意のpipenvですが、これもお好きなのをお使いください。Python は 3.9 以上必須です

pipenv --python 3.11
pipenv shell

PyTorch をバージョン指定 (2.1.0) でインストール

pip install torch==2.1.0

requirements.txtxformers のバージョンを0.0.20に固定。MPS では xformers は使えませんが、このやりかたが一番簡単でした。以下例では、vimを使っていますが、お好きなテキストエディタでどうぞ

vi requirements.txt
#xformer<0.0.23
xformers==0.0.20

もろもろをインストールして、環境は完成

pip install -e .

生成に MPS を使うようにファイルを変更

下記ファイルを変更し、エンコーディングにのみ MPS を使用するようにします。

audiocraft/models/encodec.py

クローンしたリポジトリのバージョンによって行番号が異なる可能性がありますが、class EncodecModel(CompressionModel):の中のdecode()メソッドが対象です。ハイライト部分の最初のout = self.decoder(emb)をコメントアウトし、その下のif~elseのブロックを追加します

    def decode(self, codes: torch.Tensor, scale: tp.Optional[torch.Tensor] = None):
        """Decode the given codes to a reconstructed representation, using the scale to perform
        audio denormalization if needed.

        Args:
            codes (torch.Tensor): Int tensor of shape [B, K, T]
            scale (torch.Tensor, optional): Float tensor containing the scale value.

        Returns:
            out (torch.Tensor): Float tensor of shape [B, C, T], the reconstructed audio.
        """
        emb = self.decode_latent(codes)
        #out = self.decoder(emb)
        # Below if block is added based on https://github.com/facebookresearch/audiocraft/issues/31
        if emb.device.type == 'mps':
            # XXX: Since mps-decoder does not work, cpu-decoder is used instead
            out = self.decoder.to('cpu')(emb.to('cpu')).to('mps')
        else:
            out = self.decoder(emb)

        out = self.postprocess(out, scale)
        # out contains extra padding added by the encoder and decoder
        return out

↑ のコードは、偉大なる EbaraKoji 様 (お名前から、日本の方のような?) の issue ↓ からいただきました。フォークされたリポジトリそのものは動きませんでした。残念。

https://github.com/facebookresearch/audiocraft/issues/31#issuecomment-1705769295

音声生成コード

どこかからいただいてきたコードに少し手を加えたものです。保存場所はどこでもいいのですが、一応他の実行用コードと一緒にdemosディレクトリに入れておきましょう。

from audiocraft.models import AudioGen
from audiocraft.data.audio import audio_write
import argparse
import time

model = AudioGen.get_pretrained('facebook/audiogen-medium', device='mps') # mps で Apple Silicon の GPU を指定
model.set_generation_params(duration=5)  # [duration] 秒のファイルを生成

start = time.time()
def generate_audio(descriptions):
  wav = model.generate(descriptions)  # 引数として与えられたテキスト全ての音声を生成
  
  for idx, one_wav in enumerate(wav):
      # {idx}.wav というファイルを生成。音の大きさ loudness は -14 db LUFS で平準化
      audio_write(f'{idx}', one_wav.cpu(), model.sample_rate, strategy="loudness", loudness_compressor=True)
      print(f'{idx}.wav を生成')
      print(f'かかった時間: {round(time.time()-start, 2)} 秒')

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Generate audio based on descriptions.")
    parser.add_argument("descriptions", nargs='+', help="List of descriptions for audio generation")
    args = parser.parse_args()
    
    generate_audio(args.descriptions)

6行目のdevice='mps'がキモです。これで GPU で生成してくれます。これを'cpu'にすると生成速度が遅くなりますが、メモリは消費されません。また、学習済み音声モデルは他にもfacebook/audiogen-smallがあります (ボクは試していません)。

7行目のduration=5は、生成する音声の長さを 5秒に指定しています。

使い方

注意: 初回実行時には学習済み音声モデルがダウンロードされるので、その分時間がかかります。

以下のように、欲しい効果音の内容を英語で引数として渡してあげると、0.wav, 1.wav,... と音声ファイルが生成されます。引数は一つでも複数渡しても生成速度はほとんど増えないので、一度にいくつか作ってもらうのが良いと思います。

python demos/audiogen_mps_app.py "text 1" "text 2"

実行例:

python demos/audiogen_mps_app.py "heavy rain with a clap of thunder" "knocking on a wooden door" "people whispering in a cave" "racing cars passing by"
/Users/handsome/Documents/Python/AudioCraft_MPS/.venv/lib/python3.11/site-packages/torch/nn/utils/weight_norm.py:30: UserWarning: torch.nn.utils.weight_norm is deprecated in favor of torch.nn.utils.parametrizations.weight_norm.
  warnings.warn("torch.nn.utils.weight_norm is deprecated in favor of torch.nn.utils.parametrizations.weight_norm.")
0.wav を生成
かかった時間: 61.05 秒
1.wav を生成
かかった時間: 61.1 秒
2.wav を生成
かかった時間: 61.16 秒
3.wav を生成
かかった時間: 61.22 秒

M2 Max 32GB RAM だと、メモリプレッシャーが低い状態から始めれば、5秒のファイルは 60秒前後、10秒のファイルは 100秒前後で生成されます。

実行直後 warning が出ますが、動いているので深追いしてません。PyTorch (torch) のバージョンを上げることがなければ無視してかまわないかと思います。

音楽の生成 MusicGen や MAGNeT は MPS を使えず

音楽を生成する MusicGen も MPS で動かせないかと試したのですが、同じ様な方法では無理でした。CPU であれば動くので、python demos/musicgen_app.pyで GUI を試せます。

MAGNeT はよりイケてるバージョンらしいのですが、CPU でも動かすことはできませんでした。こちら ↓ の issue を見ると、リンクされている commit で動くっぽいのですが、ボクはできませんでした。

https://github.com/facebookresearch/audiocraft/issues/396

というわけで、今回はここまで。

Image by Stable Diffusion (Mochi Diffusion)
毎回書いているこの部分は、今回から開いた人だけ見れるようにします。本文とあまり関係ないので。
今回は簡単なプロンプトでいくつも良いのを作ってくれました。その中で一番集合恐怖症の人への影響が小さそうなのをピックアップしました。

Date:
2024年7月22日 1:52:43

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
future realistic image of audio generative AI

Exclude from Image:

Seed:
751124804

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

© Peddals.com