JA ▾

音声パイプライン向け無検閲テキストAPI

uncensoredhttps://api.xtts.cc/v1

TTS API デモ:ライブリクエストとレスポンスの例

このデモでは、1分で実行できる実際のリクエストと、返ってくるレスポンス形式を示します。このAPIはテキストモデルなので、出力はスクリプトテキスト、JSON、および別の音声エンジンが読み上げるためのtool_calls形式の指示です。

更新日:

テキスト、データ、関数呼び出しストリームを出力するターミナルのアイソメトリックイラスト

実行する前に

再生ボタンを押して音声が出ることを期待している方には公平な警告:このTTS APIデモでは音は出ません。サービスはuncensoredモデルからPOST /v1/chat/completions経由でテキストを返します。GET /v1/modelsという別のエンドポイントがあり、利用可能なモデルの一覧を取得できます。音声、画像、埋め込みベクトルは返されません。

なぜデモなのか?それは、多くの音声プロジェクトでまさにこの部分が必要だからです:スクリプト作成、テキストのクリーニング、誰が何を言うかを判断する分割処理など。以下の例ではそれらの処理を示しており、出力形式は音声コードが解析する対象となります。

キーが必要です。Google またはメールアドレスとパスワードで API キーページ にサインアップし、ワンクリックで $0.50 のトライアルクレジットを請求してください。これは 7 日間有効で、カードは不要です。コマンドがキーを読み込めるようにキーをエクスポートしてください:

export XTTS_API_KEY="paste-your-key-here"
curl -s https://api.xtts.cc/v1/models -H "Authorization: Bearer $XTTS_API_KEY" | grep uncensored

その呼び出しが uncensored を含む JSON 配列を返す場合、キーは有効であり、続行できます。

デモ1:通常のリクエスト

最小限の実用的な呼び出しは、短い口頭調のパラグラフをリクエストします:

curl -s https://api.xtts.cc/v1/chat/completions \
  -H "Authorization: Bearer $XTTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "messages": [
      {"role": "system", "content": "You write short lines for a voice actor. No stage directions."},
      {"role": "user", "content": "Welcome listeners to a show about lighthouses. Two sentences."}
    ],
    "temperature": 0.7,
    "max_tokens": 120
  }'

返信は以下のサンプルのようになります。content 内のテキストは実行ごとに異なるため、これは構造の例示として扱い、録音された出力として扱わないでください。

{
  "id": "chatcmpl-example",
  "object": "chat.completion",
  "model": "uncensored",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Welcome to the show. Tonight we climb the stairs of the world's loneliest lighthouses."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 38, "completion_tokens": 21, "total_tokens": 59}
}

あなたのスピーチコードはchoices[0].message.contentを読み取ります。finish_reasonは生成が終了した理由を示します:自然な終了の場合はstop、max_tokensによって切り捨てられた場合はlengthです。max_tokensを指定しない場合、完了テキストはプロンプトと完了テキストを合わせた100,000トークンのウィンドウの残りをすべて使用することがあります。

ヘッダーが示す内容

curl コマンドに -i を追加すると、X-Request-Id、X-Balance-USD、X-RateLimit-Limit-Requests と X-RateLimit-Limit-Concurrency が表示されます。残高ヘッダーはデモで有用です。各呼び出し後にわずかな金額が減少する様子を見ることができるためです。このリクエストの場合、上記の使用量は 38 x $0.15 / 1,000,000 に 21 x $0.50 / 1,000,000 を加えたもので、$0.0000057 に $0.0000105 を加えたものとなり、約 $0.0000162 です。

デモ2:ストリーミングによるスクリプト出力

音声では、全文が到着するまで待たないことがほとんどです。"stream": trueを追加すると、APIはサーバー送信イベントを逐次送信します。以下のNode.jsの例では、テキストが到着次第それを出力しており、ここで文ごとのキューに供給するのが一般的です。

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.xtts.cc/v1",
  apiKey: process.env.XTTS_API_KEY,
});

const stream = await client.chat.completions.create({
  model: "uncensored",
  stream: true,
  messages: [
    { role: "user", content: "Read a four-line weather report for a coastal town." },
  ],
});

for await (const chunk of stream) {
  const piece = chunk.choices[0]?.delta?.content ?? "";
  process.stdout.write(piece);
}
process.stdout.write("\n");

ESモジュールとして実行します(demo.mjsとして保存し、npm install openai後にnode demo.mjsを実行)。ネットワーク上では、各イベントはdata:で始まりJSONに続く行であり、ストリームは最終マーカーで終了します。トークン使用量はストリームの末尾で報告されます。計画において重要な点があります:ストリーミングリクエストはストリームが終了するまで同時接続枠を保持するため、低速な消費者は次のリクエストをブロックする可能性があります。

デモ3:音声ルーターとしてのツール呼び出し

ツール呼び出しにより、モデルは文章の代わりに構造化された指示を返すことができます。音声プロジェクトでは、各行ごとに配信スタイルを選択するためのクリーンな方法となります。say という関数を定義し、モデルがその引数を埋めます。その後、あなたのコードがそれらの引数に対して何を行うかを決定します。モデル自体は何かを実行しません。

import json
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.xtts.cc/v1", api_key=os.environ["XTTS_API_KEY"])

tools = [{
    "type": "function",
    "function": {
        "name": "say",
        "description": "Queue one line for the voice engine.",
        "parameters": {
            "type": "object",
            "properties": {
                "text": {"type": "string"},
                "style": {"type": "string", "enum": ["calm", "urgent", "whisper"]},
            },
            "required": ["text", "style"],
        },
    },
}]

messages = [
    {"role": "system", "content": "Always answer by calling say, once per line."},
    {"role": "user", "content": "The alarm sounds. The guard tells everyone to leave."},
]

r = client.chat.completions.create(
    model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)

msg = r.choices[0].message
for call in msg.tool_calls or []:
    args = json.loads(call.function.arguments)
    print(args["style"], "->", args["text"])

引数は JSON 文字列として到着するため、使用する前に解析と検証を行ってください。モデルは列挙型外のスタイルを生成したり、フィールドを省略したりする可能性があり、チェックされていない値がエンジンに到達してはいけません。会話を継続したい場合は、アシスタントメッセージと role: "tool" および一致する tool_call_id を含む返信を追加し、API を再度呼び出します。

ストリーミング中は、ツール呼び出しは断片として到着します。関数名が最初に来るため、引数文字列はチャンク全体にわたって構築されます。ストリームが終了するまでインデックスで断片を収集し、一度に解析してください。

デモ 4:キャストリスト用の JSON モード

関数の定義をスキップしたい場合は、JSON モードがメッセージコンテンツ内に有効な JSON を提供します。これは、大まかなシーンを話者ごとの行に変換するのに適しています。

curl -s https://api.xtts.cc/v1/chat/completions \
  -H "Authorization: Bearer $XTTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "response_format": {"type": "json_object"},
    "temperature": 0.2,
    "messages": [
      {"role": "system", "content": "Return JSON: {\"lines\": [{\"speaker\": string, \"text\": string}]}"},
      {"role": "user", "content": "Ana asks Ben to hold the ladder. Ben agrees reluctantly."}
    ]
  }'

JSONモードは出力が解析可能であることを保証しますが、形状が一致することを保証するわけではありません。上記のようにプロンプトで形状を記述し、コードでキーを確認してください。低い温度設定は構造を安定に保ちます。

デモ 5:1 つのリクエストで長いドキュメント

コンテキストウィンドウは 100,000 トークンで、プロンプトと完了で共有されます。これは、長いトランスクリプトや短い物語全体を送信し、耳に最適化されたバージョンを依頼するのに十分な大きさです。リクエストボディは最大 8 MB まで可能なので、サイズは通常制限になりません。トークン数が制限となります。

ここでは重い呼び出しのコストを示します。80,000トークンを送信して2,000トークンを取得すると仮定します。入力:80,000 x $0.15 / 1,000,000 = $0.012。出力:2,000 x $0.50 / 1,000,000 = $0.001。合計は$0.013なので、$0.50のトライアルでは約38回のこのような呼び出しをカバーできます。長い入力は長い出力と比較して安価であるため、大きなテキストの要約や書き換えは手頃な価格ですが、一度に小説全体を生成するのは高コストになります。

長い入力のための実用的なヒント:指示を最初に置き、重要なルールを最後に繰り返してください。モデルは最新の指示を最もよく従う傾向があり、80,000トークンのソーステキストの後に1行の補足を追加しても、コストはほぼかかりません。

デモのエラーの読み方

意図的に一度壊して、後で識別できるようにしてください。間違ったキーでリクエストを送信すると、完了(生成結果)の代わりに認証エラーが返されます。トライアルキーから同時に 10 件のリクエストを送信すると、いくつかは HTTP 429 として返されます。

429 には 3 つの原因があり、エラーコードでそれらを区別できます:

  • rate_limited は、1 分あたりのリクエストが多すぎます:トライアルキーでは 60、フルキーでは 300 です。
  • concurrency は、同時に実行中のリクエストが多すぎます:トライアルキーでは 2、フルキーでは 8 です。
  • Retry-After: 5 ヘッダーを含む 429 は、サービスが一時的に過負荷状態だったことを意味します。5 秒待ってから再度送信してください。

失敗または拒否されたリクエストは課金されないため、エラーにはコストがかかりません。キーの制限を確認するには、通常のレスポンスの X-RateLimit-Limit-Requests と X-RateLimit-Limit-Concurrency を読み取ってください。Retry-After の値、またはそれが欠落している場合は 5 秒間待機する小さなリトライループは、デモスクリプトにとって必要なすべてです。

次に試すこと

これら 4 つの呼び出しが動作するようになれば、スクリプトパイプラインの部品が揃います。通常のリクエストを関数でラップし、ストリーミングループをキューに流し、キューを選択した音声エンジンに接続してください。エンジンは価格、ライセンス、品質が異なるため、現在の利用規約をお読みください。このサービスはエンジンを提供せず、それらについて何らかの声明も出していません。

実験中はコストが小さく抑えられます。入力トークン 100 万あたり $0.15、出力トークン 100 万あたり $0.50 で、典型的なデモ呼び出しのコストはセントの分数であり、$0.50 のトライアルで数百回をカバーできます。ボーナスは 5% から 15% で、暗号資産で支払い可能で、$20 から $500 のチャージについては 料金ページ を参照してください。ドキュメント には、パラメータの完全なリスト、レート制限(フルキーで同時 8、1 分あたり 300)、エラーコードが記載されています。プロンプトはトレーニングには使用されません。

最初の午後のための合理的な順序:トーンが適切になるまでプレーンなリクエストを実行し、ストリーミングに切り替えて完了した文を出力し、その後、スピーチコードの入力方法に一致するツール呼び出しまたはJSONモードのいずれかを追加します。すべてのプロンプトをバージョン管理下のファイルに保持します。最終的な音声で1行が間違っているように聞こえた場合、それを生成した正確な指示まで遡って追跡し、一度に1つずつ変更することができます。

質問と回答

このデモでサンプルボイスを聴けますか?

いいえ。API はテキスト、JSON、関数呼び出しのみを返します。テキストを音声に変換するには、別途音声合成エンジンをご用意ください。

どのモデルIDを送信すればよいですか?

モデル値に uncensored を指定し、ベース URL https://api.xtts.cc/v1 と Authorization: Bearer ヘッダーに API キーを設定して送信してください。

トライアルキーでもデモは動作しますか?

はい。トライアルキーでは同時 2 リクエスト、1 分あたり 60 リクエストまで許可されており、これらの例を実行するには十分です。一度に一つずつ実行してください。

429 レスポンスが返されるのはなぜですか?

1 分あたりのリクエスト数(レート制限)を超えたか、同時に開いているリクエストが多すぎたか、サービスが一時的に過負荷状態になったためです。Retry-After ヘッダーが指定されている場合は、その時間待ってから再試行してください。

キーはフォーム 1 つで手に入ります

アカウントを作成し、キーをコピーし、ベースURLを変更します。これでセットアップは完了です。