2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

高火力 DOKでAI音楽生成する(Stable Audio 3.0 Medium)

2
Posted at

概要

背景

めざましい進化を遂げるAI技術。
話題に挙がるのはコーディングや画像・動画生成が主だが、作曲の分野においても高い水準に達しつつある。
今回は令和8年5月に公開された音楽生成AIシリーズ「Stable Audio 3.0」のうち、オープンウェイトの最高水準モデルMediumを高火力 DOKで動かして、音楽生成を試してみた。

成果物

構成はいたって単純。
Hugging FaceからAIモデルを取得して、スクリプトを含めてコンテナイメージ化し、コンテナレジストリに格納する。
高火力 DOKでそのコンテナイメージを動かしてAI音楽生成を実行し、成果物はオブジェクトストレージに格納する。
image.png
Dockerイメージ作成用サーバー構築についてはこちらの記事で解説しているので、今回は割愛する。モデルが重いので、4コア16GB・ディスク100GBのサーバーを用いた。

構築

コンテナレジストリ・オブジェクトストレージの準備

あらかじめ、コンテナレジストリを作成しておく。
さくらのクラウドのコントロールパネルから作成し、ユーザ登録も済ませておく。
image.png
コンテナレジストリのユーザ登録が完了した時点で、高火力 DOKのレジストリ認証情報も登録できる。
image.png
成果物を格納するオブジェクトストレージのバケットとそのアクセスキーIDも作成しておく。詳しくはマニュアルを参照されたし。
image.png
これでさくらのクラウド側の準備は完了だ。

コンテナイメージの準備

以下のようなDockerfileを記述した。
Pythonバージョンの要件からUbuntu22.04、依存パッケージの要件からnumpyを2未満のバージョンで採用している。
文献が少なく、依存ライブラリを洗い出すのに何度か試行錯誤を迫られた。
個人閉域利用なので、モデル取得時に使うHugging Faceのアクセストークンはビルド時に--build-argで渡す方式としている(Hugging Faceのアカウントがない方は作成されたし)。

FROM nvidia/cuda:13.0.0-runtime-ubuntu22.04
LABEL jp.sakuracr.t-shirotani-airepo.version="1.0.0"
LABEL jp.sakuracr.t-shirotani-airepo.release-date="2026-07-28"
ENV DEBIAN_FRONTEND=noninteractive \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8
ENV PIP_BREAK_SYSTEM_PACKAGES=1

# 依存関係のインストール。
RUN apt-get update && \
    apt-get install -y \
        ca-certificates \
        python3 \
        python3-pip \
        libsndfile1 && \
    rm -rf /var/lib/apt/lists/* && \
    pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu130 && \
    pip install \
        "numpy<2.0.0" \
        boto3 \
        einops \
        huggingface_hub \
        pytorch-lightning \
        soundfile \
        stable_audio_tools \
      && \
    pip cache purge && \
    mkdir /stable-audio-3-medium /opt/artifact

# モデルの取得。
WORKDIR /stable-audio-3-medium

ARG access_token
RUN hf auth login --token $access_token && \
    hf download stabilityai/stable-audio-3-medium --local-dir . && \
    rm -rf ~/.cache/huggingface

# 実行用スクリプト等の配置
COPY runner*.py /stable-audio-3-medium/
COPY docker-entrypoint*.sh /
RUN chmod +x /docker-entrypoint*.sh

ENTRYPOINT [ "/docker-entrypoint.sh" ]

エントリーポイントとなるシェルスクリプトとPythonスクリプトは以下の通り。

#!/bin/bash
set -ue
shopt -s nullglob

export TZ=${TZ:-Asia/Tokyo}

if [ -z "${SAKURA_ARTIFACT_DIR:-}" ]; then
      	echo "Environment variable SAKURA_ARTIFACT_DIR is not set" >&2
      	exit 1
fi

if [ -z "${SAKURA_TASK_ID:-}" ]; then
      	echo "Environment variable SAKURA_TASK_ID is not set" >&2
	exit 1
fi

if [ -z "${PROMPT:-}" ]; then
      	echo "Environment variable PROMPT is not set" >&2
	exit 1
fi

if [ -z "${DURATION_SECONDS:-}" ]; then
      	echo "Environment variable DURATION_SECONDS is not set" >&2
	exit 1
fi

pushd /stable-audio-3-medium

python3 runner.py \
  --output="${SAKURA_ARTIFACT_DIR}" \
  --prompt="${PROMPT}" \
  --seconds="${DURATION_SECONDS:-380}" \
  --steps="${STEPS:-8}" \
  --objst-key="${OBJST_KEY:-stable_audio_output.wav}" \
  --objst-bucket="${OBJST_BUCKET:-}" \
  --objst-endpoint="${OBJST_ENDPOINT:-}" \
  --objst-secret="${OBJST_SECRET:-}" \
  --objst-token="${OBJST_TOKEN:-}"
popd
import argparse
import boto3
import json
import logging
import torch
import torchaudio
from einops import rearrange
from huggingface_hub import login
from stable_audio_tools.models.factory import create_model_from_config
from stable_audio_tools.models.utils import load_ckpt_state_dict
from stable_audio_tools.inference.generation import generate_diffusion_cond_inpaint
from pathlib import Path

logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')

# 環境変数からパラメータを取得
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--output', default='/opt/artifact', help='出力先ディレクトリを指定します。')
arg_parser.add_argument('--prompt', type=str, default="A dream-like Synthpop instrumental that would accompany, a dream-sequence in a surrealist movie 120 BPM", help='プロンプトを指定します。')
arg_parser.add_argument('--seconds', type=int, default=380, help='生成する音楽の長さ(秒)を指定します。')
arg_parser.add_argument('--steps', type=int, default=8, help='拡散ステップ数を指定します。')
arg_parser.add_argument('--objst-key', type=str, default="stable_audio_output.wav", help='オブジェクトストレージのオブジェクトキーを指定します。')
arg_parser.add_argument('--objst-bucket', help='オブジェクトストレージのバケットを指定します。')
arg_parser.add_argument('--objst-endpoint', help='オブジェクトストレージ互換エンドポイントのURLを指定します。')
arg_parser.add_argument('--objst-secret', help='オブジェクトストレージのシークレットアクセスキーを指定します。')
arg_parser.add_argument('--objst-token', help='オブジェクトストレージのアクセスキーIDを指定します。')
args = arg_parser.parse_args()

device = "cuda"

logging.info(f"{device}にモデルをロードします。")
# model, model_config = get_pretrained_model("/stable-audio-3-medium")
config_path = "/stable-audio-3-medium/model_config.json"
weights_path = "/stable-audio-3-medium/model.safetensors"

# 設定ファイルを読み込む
with open(config_path, "r") as f:
    model_config = json.load(f)

# 設定からモデルを初期化し、重みをロードする
model = create_model_from_config(model_config)
model.load_state_dict(load_ckpt_state_dict(weights_path))

sample_rate = model_config["sample_rate"]
sample_size = model_config["sample_size"]

model = model.to(device)
model = model.to(torch.float16)

logging.info(f"{args.seconds}秒の音楽を生成します。")
conditioning = [{
    "prompt": args.prompt,
    "seconds_total": args.seconds
}]

output = generate_diffusion_cond_inpaint(
    model,
    steps=args.steps,
    cfg_scale=1.0,
    conditioning=conditioning,
    sample_size=sample_size,
    sampler_type="pingpong",
    device=device
)

output = rearrange(output, "b d n -> d (b n)")
logging.info("生成が完了しました。ローカルに保存します。")

output = output.to(torch.float32).div(torch.max(torch.abs(output))).clamp(-1, 1).mul(32767).to(torch.int16).cpu()
output_path = Path(args.output) / Path(args.objst_key).name

torchaudio.save(output_path, output, sample_rate)
logging.info(f"生成した音楽を{output_path}に保存しました。")

# ==========================================
# さくらのオブジェクトストレージへのアップロード処理
# ==========================================
if all([args.objst_key, args.objst_bucket, args.objst_endpoint, args.objst_secret,args.objst_token]):
    logging.info(f"オブジェクトストレージに成果物をアップロードします: {args.objst_bucket}/{args.objst_key}")
    
    # さくらのオブジェクトストレージ(S3互換)向けのBoto3クライアント設定
    objst_client = boto3.client(
        's3',
        endpoint_url=args.objst_endpoint,
        aws_access_key_id=args.objst_token,
        aws_secret_access_key=args.objst_secret,
    )
    
    try:
        objst_client.upload_file(
            Filename=str(output_path),
            Bucket=args.objst_bucket,
            Key=args.objst_key,
            ExtraArgs={
                "ContentType": "audio/wav",
            })
        logging.info("アップロードが完了しました。")
    except Exception as e:
        logging.error(f"アップロードに失敗しました: {e}")
else:
    logging.warning("ストレージの認証情報が環境変数に完全に提供されていません。アップロードを省略しました。")

動作時に必要な環境変数は後述する。
上記3ファイルを同ディレクトリ配下に配置し、Dockerイメージをbuild、pushする。

sudo docker login -t  <作成したレジストリのホスト名>.sakuracr.jp -u <作成したユーザ> -p <作成したユーザのパスワード>
sudo docker build --build-arg access_token=Hugging Faceのアクセストークン -t <作成したレジストリのホスト名>/stable-audio-3-medium:latest .
sudo docker image push <作成したレジストリのホスト名>.sakuracr.jp/stable-audio-3-medium:latest

大容量のモデルなので少し時間がかかる。作曲でもしながら待とう。

実行

pushできたら、高火力 DOKでタスクを実行していく。
image.png
イメージは

<作成したレジストリのホスト名>.sakuracr.jp/stable-audio-3-medium:latest

レジストリ認証情報は先ほど登録したものを選択する。
プロンプトやファイルの保存先等は環境変数で受けるように設計している。以下の設定が必要である。

環境変数 役割
PROMPT 音楽生成を支持するプロンプト。英語で記述することが望ましい。
DURATION_SECONDS 音楽の長さ(秒)。
STEPS ステップ数。高ければ品質が上がるが処理時間も増える。
OBJST_KEY オブジェクトストレージに格納する成果物のキー。
OBJST_ENDPOINT オブジェクトストレージのエンドポイント。「https://」が必要。
OBJST_BUCKET オブジェクトストレージのバケット名。
OBJST_TOKEN オブジェクトストレージのアクセスキーID。
OBJST_SECRET オブジェクトストレージのシークレットアクセスキー。
HF_TOKEN Hugging Faceのトークン。

Stable Audio 3.0 Mediumのモデルはコンテナ内部に格納されているが、テキストエンコーダの初期化処理時にHugging Faceと通信するため、Hugging Faceのトークンも必要である。
これらを登録して、タスク登録を行う。
今回は以下のような内容で2分のピアノ曲を生成させてみた。

A cinematic piano solo, sentimental and emotional soundtrack, nostalgic mood, slow tempo, delicate and expressive melody, soft dynamics, atmospheric reverb, high quality, stereo.

1分ほどで処理が完了し、オブジェクトストレージに成果物が格納された。
image.png
image.png
出力された音源は、素材として使うには申し分ない品質だった。

まとめ

今回は高火力 DOK上で音楽生成AI「Stable Audio 3.0 Medium」を動かしてみた。
この記事では2分の楽曲を1曲だけ生成したが、H100のスペックであれば大量の音楽生成を走らせることが可能だ。より重量級のモデルにも挑戦できる。
ぜひ試してみて欲しい。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?