インタラクティブな音楽アプリ、ゲーム NPC の自動歌唱、またはバーチャル配信者(VTuber)向けのオーディオ合成システムを構築する開発者にとって、ブラウザ上の手動操作画面は大きなボトルネックになります。手動の UI 操作では、本番環境の自動化ワークフローや高並列バッチ合成に対応できません。Uberduck は公式の REST API を提供しており、エンジニアがコードから直接、リズムと音程を持ったボーカル音声を自動生成できる環境を整えています。
Uberduck API を用いてラップや歌唱ボーカルを生成するには、HTTP Basic 認証、用途に応じた生成エンドポイントの選定(ビート同期型の /tts/freestyle、ピッチ制御型の /speak、または音声変換 /tts/convert)、そして /speak-status による非同期ポーリング処理の 3 つの要素を設計する必要があります。
1. 認証方式とリクエストの基本構造
Uberduck の REST API は、標準的な HTTP Basic 認証を採用しています。ダッシュボードで取得した API Key(ユーザー名)と API Secret(パスワード)をコロンで連結し、Base64 エンコードした文字列をリクエストヘッダーに設定します。
認証ヘッダーの構成
- Uberduck のアカウント設定画面で
API KeyとAPI Secretを発行します。 - HTTP の
Authorizationヘッダーを以下のように構築します:Authorization: Basic base64(API_KEY:API_SECRET) - API のベース URL は
https://api.uberduck.aiです。
import base64
import os
API_KEY = os.getenv("UBERDUCK_API_KEY", "your_api_key")
API_SECRET = os.getenv("UBERDUCK_API_SECRET", "your_api_secret")
def get_auth_headers():
token = base64.b64encode(f"{API_KEY}:{API_SECRET}".encode("utf-8")).decode("utf-8")
return {
"Authorization": f"Basic {token}",
"Content-Type": "application/json"
}
2. 3 種類のボーカル合成モード
リズム重視のラップとメロディアスな歌唱では必要な制御が異なります。Uberduck は以下の 3 つのアプローチを提供しています:
| 合成モード | 主要エンドポイント | 主なパラメータ | 最適なユースケース |
|---|---|---|---|
| テキスト・トゥ・ラップ(Freestyle) | POST /tts/freestyle | lyrics, bpm, backing_track, voice または voicemodel_uuid | ビートに同期したラップ楽曲の生成;即興フリースタイル;インタラクティブな歌詞演出 |
| パラメータ指定型ピッチ・時間軸合成 | POST /speak | speech, voicemodel_uuid, pitch, duration, pace | MIDI データや譜面情報に基づき、音素ごとのピッチ曲線と長さを精密制御する楽曲合成 |
| 音声変換(Voice-to-Voice) | POST /tts/convert | voicemodel_uuid, input(音声 URL), pitch_shift | 自然なビブラートや抑揚を保ったメロディ歌唱;ガイドボーカル音源からのキャラクター声変換 |
3. テキスト・トゥ・ラップ(Freestyle)パイプラインの構築
/tts/freestyle はラップに特化したエンドポイントであり、設定したテンポ(BPM)とバッキングトラックのリズムに合わせて歌詞を自動的にアラインメントします。
ステップ 1:利用可能なバッキングトラックの取得
公式に提供されているビート音源と歌詞を同期させたい場合は、一覧取得エンドポイントを呼び出します:
import requests
def list_backing_tracks():
url = "https://api.uberduck.ai/reference-audio/backing-tracks?detailed=true"
response = requests.get(url, headers=get_auth_headers())
response.raise_for_status()
return response.json() # トラック UUID、BPM、ジャンル情報を含むリスト
ステップ 2:(任意)押韻歌詞の自動生成
ユーザーの入力テーマから即座にラップ歌詞を生成したい場合は、/tts/lyrics エンドポイントを利用できます(または LLM の出力を 2 次元配列形式に整形します):
def generate_lyrics(subject, lines=4):
url = "https://api.uberduck.ai/tts/lyrics"
payload = {
"subject": subject,
"lines": lines
}
response = requests.post(url, json=payload, headers=get_auth_headers())
response.raise_for_status()
return response.json() # 構造化された歌詞行
ステップ 3:Freestyle 生成リクエストの送信
二次元配列として構成した歌詞、目標 BPM、トラック UUID、ボイスモデル ID を API に送信します:
def generate_rap_vocal(lyrics_matrix, bpm=90, backing_track_uuid=None, voice="zwf"):
url = "https://api.uberduck.ai/tts/freestyle"
payload = {
"lyrics": lyrics_matrix, # 例: [["コードが走るビートの波に乗って", "APIコールが響き渡るフロア"]]
"bpm": bpm,
"voice": voice,
"format": "json"
}
if backing_track_uuid:
payload["backing_track"] = backing_track_uuid
response = requests.post(url, json=payload, headers=get_auth_headers())
response.raise_for_status()
data = response.json()
return data["uuid"] # 非同期タスクの UUID を取得
4. ピッチ時間軸と歌唱ボーカルの設定
メロディを伴う歌唱では、滑らかな音高遷移と音素の持続時間が不可欠です。Uberduck では 2 つの方法でこれを実現できます:
アプローチ A:/speak によるピッチ配列と持続時間の制御
詳細な制御に対応したボイスモデル(GET /voices/{voicemodel_uuid}/detail のレスポンスで controls: true となっているモデル)では、/speak エンドポイントに pitch(音高配列)と duration(時間配列)を渡すことができます:
def generate_singing_notes(speech_text, voicemodel_uuid, pitch_curve, duration_curve):
"""
pitch_curve: 各音素の目標ピッチ(F0 または半音単位)の数値配列
duration_curve: 各音素の継続時間を表す数値配列
"""
url = "https://api.uberduck.ai/speak"
payload = {
"speech": speech_text,
"voicemodel_uuid": voicemodel_uuid,
"pitch": pitch_curve,
"duration": duration_curve,
"pace": 1.0
}
response = requests.post(url, json=payload, headers=get_auth_headers())
response.raise_for_status()
return response.json()["uuid"]
アプローチ B:音声変換(V2V)による高品質な歌唱生成
テキストから直接音素単位のピッチ曲線を算出するのは複雑であり、機械的な響きになりやすい傾向があります。そのため、商用音楽アプリでは Voice-to-Voice(音声変換) が広く使われています。
MIDI 音源や人間の仮歌(ガイドボーカル)を入力として POST /tts/convert に渡し、pitch_shift でキーを調整することで、自然な歌声を再現できます:
def convert_guide_vocal_to_singer(guide_audio_url, target_voice_uuid, semitone_shift=0):
url = "https://api.uberduck.ai/tts/convert"
payload = {
"input": guide_audio_url,
"voicemodel_uuid": target_voice_uuid,
"pitch_shift": semitone_shift
}
response = requests.post(url, json=payload, headers=get_auth_headers())
response.raise_for_status()
return response.json()["uuid"]
5. 非同期処理とステータスポーリングの仕組み
音声ニューラルネットワークのレンダリングには数秒〜十数秒の演算を要するため、API はリクエスト時に即座にジョブ ID(uuid)を返します。バックエンド側で /speak-status エンドポイントを定期的にポーリングする必要があります。
import time
def poll_render_completion(job_uuid, max_attempts=30, delay_seconds=2):
status_url = f"https://api.uberduck.ai/speak-status?uuid={job_uuid}"
headers = get_auth_headers()
for attempt in range(max_attempts):
response = requests.get(status_url, headers=headers)
response.raise_for_status()
data = response.json()
# 失敗判定
if data.get("failed_at"):
raise RuntimeError(f"ボーカル生成に失敗しました: {data}")
# 完了判定
if data.get("finished_at"):
audio_url = data.get("path")
return audio_url # 生成された WAV ファイルの CDN URL
time.sleep(delay_seconds)
raise TimeoutError("音声生成がタイムアウトしました。")
6. エンドツーエンドの統合スクリプト例
認証、リクエスト送信、ステータスポーリング、ファイル保存までを網羅した Python スクリプトは以下のとおりです:
import requests
import base64
import time
import os
UBERDUCK_API_KEY = os.getenv("UBERDUCK_API_KEY")
UBERDUCK_API_SECRET = os.getenv("UBERDUCK_API_SECRET")
HEADERS = {
"Authorization": f"Basic {base64.b64encode(f'{UBERDUCK_API_KEY}:{UBERDUCK_API_SECRET}'.encode()).decode()}",
"Content-Type": "application/json"
}
def create_rap_track(lyrics, bpm=95, voice="zwf", output_file="vocal_output.wav"):
# 1. ラップ生成ジョブの送信
print("ボーカル生成リクエストを送信中...")
freestyle_url = "https://api.uberduck.ai/tts/freestyle"
payload = {
"lyrics": lyrics,
"bpm": bpm,
"voice": voice,
"format": "json"
}
resp = requests.post(freestyle_url, json=payload, headers=HEADERS)
resp.raise_for_status()
task_id = resp.json()["uuid"]
print(f"ジョブ開始 UUID: {task_id}")
# 2. 完了ポーリング
status_url = f"https://api.uberduck.ai/speak-status?uuid={task_id}"
audio_url = None
for _ in range(40):
time.sleep(2)
status_resp = requests.get(status_url, headers=HEADERS)
status_resp.raise_for_status()
status_data = status_resp.json()
if status_data.get("failed_at"):
raise RuntimeError("サーバー側でレンダリングエラーが発生しました。")
if status_data.get("finished_at"):
audio_url = status_data.get("path")
print(f"生成完了 URL: {audio_url}")
break
if not audio_url:
raise TimeoutError("処理が 80 秒を超過したため中止しました。")
# 3. 音声ファイルのダウンロード
audio_data = requests.get(audio_url).content
with open(output_file, "wb") as f:
f.write(audio_data)
print(f"ファイルを保存しました: {output_file}")
return output_file
if __name__ == "__main__":
bars = [
["自動生成ラインが描くグルーヴの軌道", "コードがつなぐ新しい音楽の波動"],
["完璧なテンポで駆け抜けるBPM", "Uberduck APIが切り拓くサウンドの地平"]
]
create_rap_track(lyrics=bars, bpm=95)
7. 本番環境での運用ポイントと技術的トレードオフ
システムを本番稼働させる際は、以下の考慮事項が重要です:
- 音節密度と BPM の整合性:1 行あたりの歌詞の音節数は、テンポとバランスをとる必要があります。110 BPM を超える高速なテンポで歌詞を詰め込みすぎると、発音の乱れやクリッピングが発生しやすくなります。
- キューイングと非同期化:生成には 4〜15 秒程度を要します。Web サーバーの同期リクエスト内で直接待機せず、Celery や BullMQ などのメッセージキューを活用してバックグラウンドワーカーで処理してください。
- 商用ライセンスとプラン要件:API 利用および商用プロダクトへの組み込みには、Pro または Enterprise などの有償プラン契約が前提となります。無料枠は非商用に限定され、利用規約に従った運用が必要です。
- 後処理エフェクト(DSP):API から出力される音声はドライな状態です。楽曲としての完成度を高めるため、後段のパイプラインでイコライザー、コンプレッサー、リバーブ処理を適用することをお勧めします。
参考文献
- Uberduck API Documentation
- Generate Freestyle - Uberduck Text To Speech API
- Generate Lyrics - Uberduck Text To Speech API
- Generate Speech - Uberduck Text To Speech API
- Voice To Voice Conversion - Uberduck Text To Speech API
- Get text-to-speech request status - Uberduck Text To Speech API
- List Backing Tracks - Uberduck Text To Speech API
- Uberduck AI Pricing and Plans