API ドキュメント

読み上げクラウド API は REST ベースで、Authorization ヘッダーによる API キー認証を採用しています。

クイックスタート

3 ステップで音声を生成できます:

  1. ダッシュボードで API キーを発行
  2. POST /api/v1/synthesize を叩く
  3. レスポンスの音声バイナリを保存・再生
curl -X POST https://yomiage.cloud/api/v1/synthesize \
  -H "Authorization: Bearer yom_live_xxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "こんにちは、読み上げクラウド です。",
    "voice": "ja-JP-Chirp3-HD-Aoede"
  }' \
  --output hello.mp3

認証

すべての API リクエストには Authorization ヘッダーで API キーを送信します:

Authorization: Bearer yom_live_xxxxxxxxxxxxxxxxxxxxxx

API キーは ダッシュボードのキー管理画面 から発行できます。

API キーは作成時の1回だけ表示されます。安全な場所に保管してください。漏洩した場合は即時失効させて新規発行してください。

POST /api/v1/synthesize

テキストから音声を生成します。

リクエストボディ (JSON)

フィールド必須説明
textstringYes読み上げるテキスト。最大 5,000 字
voicestringYes音声 ID(例: ja-JP-Chirp3-HD-Aoede)
enginestringNo"google" (デフォルト) または "voicevox"
speednumberNo速度 0.5〜2.0(デフォルト 1.0)
pitchnumberNoピッチ -10〜+10(デフォルト 0)

レスポンス

成功時: 音声バイナリ(audio/mpeg または audio/wav

エラー時: JSON

{
  "error": "monthly_limit_exceeded",
  "message": "Monthly character limit (50000) exceeded.",
  "limit": 50000,
  "used": 100013,
  "remaining": 0
}

レスポンスヘッダー

ヘッダー説明
Content-Typeaudio/mpeg (Google) または audio/wav (VOICEVOX)
X-Audio-Engine使用エンジン(google / voicevox)
X-RateLimit-Limit月間上限文字数
X-RateLimit-Remaining残り文字数

GET /api/v1/voices

利用可能な音声の一覧を取得します。

curl https://yomiage.cloud/api/v1/voices \
  -H "Authorization: Bearer yom_live_xxxxxxxxxxxxxxxxxxxxxx"
{
  "voices": [
    {
      "engine": "google",
      "id": "ja-JP-Chirp3-HD-Aoede",
      "name": "ja-JP-Chirp3-HD-Aoede",
      "group": "Chirp3-HD",
      "gender": "FEMALE"
    },
    ...
  ]
}

エラーコード

HTTPerror説明
400missing_text / text_too_long / invalid_voice / invalid_jsonリクエスト不正
401unauthorizedAPI キー無効/未指定
403plan_disabled_api現在のプランで API 利用不可(要アップグレード)
429monthly_limit_exceeded月間文字数超過
500synthesis_failed音声合成エンジンエラー(upstream 障害等)

レート制限

現在は月間文字数のみで制限しており、秒間 / 分間のリクエスト制限はありません。

大量のリクエスト(毎秒 100 件以上)を継続的に送る場合は、事前に business@yomiage.cloud までご連絡ください。

長文の扱い

1 リクエストあたりの上限: 5,000 字

text フィールドの最大長は 5,000 字です。 これを超えると HTTP 400 / error: "text_too_long" が返ります。

朗報: 5,000 字以内なら、どんなに長い文や句読点無しの文章でも自動分割します。 「、で区切らないとエラーになる」というのは Chirp3-HD の素の仕様で、読み上げクラウド 側で透過的に解決しています。 クライアント側で句読点ベースの事前分割は不要です。

5,000 字超の場合の対処

5,000 字を超える長文(ブログ記事全文、台本、書籍など)は、クライアント側で文単位に分割して複数回リクエストし、生成した音声を連結してください。

Python サンプル(10,000+ 字を一括音声化)

import os
import requests

API_KEY = os.environ["YOMIAGE_API_KEY"]
ENDPOINT = "https://yomiage.cloud/api/v1/synthesize"
MAX_CHARS_PER_REQUEST = 4500  # 5,000 の安全マージン

def chunk_japanese_text(text: str, max_chars: int = MAX_CHARS_PER_REQUEST) -> list[str]:
    """日本語テキストを「。」優先で安全に分割。max_chars 以下のチャンクに分ける。"""
    chunks = []
    current = ""
    for sentence in text.replace("\n", "").split("。"):
        if not sentence:
            continue
        candidate = current + sentence + "。"
        if len(candidate) > max_chars and current:
            chunks.append(current)
            current = sentence + "。"
        else:
            current = candidate
    if current.strip():
        chunks.append(current)
    return chunks

def synthesize_long(text: str, voice: str = "ja-JP-Chirp3-HD-Aoede",
                    output_path: str = "output.mp3") -> None:
    """長文テキストを音声化(自動分割 + 連結)"""
    chunks = chunk_japanese_text(text)
    print(f"Splitting into {len(chunks)} chunks")
    with open(output_path, "wb") as f:
        for i, chunk in enumerate(chunks):
            res = requests.post(
                ENDPOINT,
                json={"text": chunk, "voice": voice},
                headers={"Authorization": f"Bearer {API_KEY}"},
            )
            res.raise_for_status()
            f.write(res.content)
            print(f"  [{i+1}/{len(chunks)}] {len(chunk)} chars → ok")
    print(f"Done: {output_path}")

# 使用例
long_text = open("article.txt").read()  # 10,000+ 字
synthesize_long(long_text)

Node.js サンプル

import fs from "fs";
import path from "path";

const API_KEY = process.env.YOMIAGE_API_KEY;
const ENDPOINT = "https://yomiage.cloud/api/v1/synthesize";
const MAX_CHARS = 4500;

function chunkJapaneseText(text, maxChars = MAX_CHARS) {
  const chunks = [];
  let current = "";
  for (const sentence of text.replace(/\n/g, "").split("。")) {
    if (!sentence) continue;
    const candidate = current + sentence + "。";
    if (candidate.length > maxChars && current) {
      chunks.push(current);
      current = sentence + "。";
    } else {
      current = candidate;
    }
  }
  if (current.trim()) chunks.push(current);
  return chunks;
}

export async function synthesizeLong(text, {
  voice = "ja-JP-Chirp3-HD-Aoede",
  outputPath = "output.mp3",
} = {}) {
  const chunks = chunkJapaneseText(text);
  console.log(`Splitting into ${chunks.length} chunks`);

  const buffers = [];
  for (let i = 0; i < chunks.length; i++) {
    const res = await fetch(ENDPOINT, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${API_KEY}`,
      },
      body: JSON.stringify({ text: chunks[i], voice }),
    });
    if (!res.ok) throw new Error(`Chunk ${i+1} failed: ${res.status}`);
    const buf = Buffer.from(await res.arrayBuffer());
    buffers.push(buf);
    console.log(`  [${i+1}/${chunks.length}] ${chunks[i].length} chars → ok`);
  }

  fs.writeFileSync(outputPath, Buffer.concat(buffers));
  console.log(`Done: ${outputPath}`);
}

// 使用例
const longText = fs.readFileSync("article.txt", "utf-8");
await synthesizeLong(longText);

FAQ

Q: 「、」で事前分割しないと長文エラーになる?
A: 不要です。5,000 字以内なら 読み上げクラウド 側で自動分割します。 Chirp3-HD の「sentence too long」エラーは内部で透過的に処理されます。 ただし 5,000 字超は API ハード制限に当たるため、上記サンプルのような文単位分割が必要です。
Q: チャンク間の音声が不自然に途切れる?
A: 文末(句点)でチャンク分割していれば、ほぼ自然につながります。 どうしても気になる場合は ffmpeg で結合後にクロスフェード処理 (約 0.05 秒) を入れると滑らかになります。
Q: 月間文字数の上限を超えそうなとき
A: 事前に X-RateLimit-Remaining ヘッダーで残量を確認、もしくは ダッシュボード で使用量を見られます。 残量超えると HTTP 429 / monthly_limit_exceeded が返るので、 その時点でプランアップグレード or 翌月リセット待ちです。

サンプルコード

Node.js (axios)

import axios from "axios";
import fs from "fs";

const response = await axios.post(
  "https://yomiage.cloud/api/v1/synthesize",
  {
    text: "こんにちは、読み上げクラウド です。",
    voice: "ja-JP-Chirp3-HD-Aoede",
  },
  {
    headers: {
      Authorization: `Bearer ${process.env.YOMIAGE_API_KEY}`,
    },
    responseType: "arraybuffer",
  },
);

fs.writeFileSync("hello.mp3", response.data);

Python (requests)

import os
import requests

response = requests.post(
    "https://yomiage.cloud/api/v1/synthesize",
    json={
        "text": "こんにちは、読み上げクラウド です。",
        "voice": "ja-JP-Chirp3-HD-Aoede",
    },
    headers={"Authorization": f"Bearer {os.environ['YOMIAGE_API_KEY']}"},
)
response.raise_for_status()

with open("hello.mp3", "wb") as f:
    f.write(response.content)

cURL(ダウンロード付き)

curl -X POST https://yomiage.cloud/api/v1/synthesize \
  -H "Authorization: Bearer $YOMIAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"こんにちは","voice":"ja-JP-Chirp3-HD-Aoede"}' \
  --output hello.mp3
API ドキュメント — 読み上げクラウド 音声合成 API リファレンス | 読み上げクラウド