HiAPI
ブログ

チュートリアル

hiapi API で qwen-audio-3.0-tts-plus を使う方法:curl と Python によるテキスト読み上げの実装

Aug 4, 2026
hiapi API で qwen-audio-3.0-tts-plus を使う方法:curl と Python によるテキスト読み上げの実装

qwen-audio-3.0-tts-plus はテキスト読み上げモデルで、hiapi プラットフォームの統一された非同期タスクキューを通じてアクセスします。画像や動画の生成と同じ POST /v1/tasks エンドポイントを使用し、独立した音声 API ではありません。テキストを送信するとすぐに taskId が返り、その後ポーリングするかコールバックを待つことで、ダウンロード可能な音声ファイルの URL を取得できます。このチュートリアルでは、curl と Python で動作するリクエスト(実際の API に対してエンドツーエンドで検証済み)を完成させたうえで、実際の運用に必要なパターン、すなわちコールバックとポーリング、冪等なリトライ、そして対処すべき正確なエラー形態について解説します。

構築するもの

テキストを qwen-audio-3.0-tts-plus に送信し、タスクの完了を待って、生成された音声をダウンロードするスクリプトに加え、そのスクリプトを本格的な統合に発展させるためのパラメータリファレンスとエラーハンドリングのパターンを扱います。

前提条件:hiapi の API キーが必要です。hiapi ダッシュボード から取得してください。以下のすべてのリクエストは Authorization: Bearer sk-<your-key> で認証します。

最小限の動作例

curl

タスクを作成します:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-audio-3.0-tts-plus",
    "input": {
      "text": "Welcome to hiapi, the unified API for AI models.",
      "voice": "longanlingxin"
    }
  }'
{"code": 200, "data": {"taskId": "tk-hiapi-01KZ59B7ZJ7012PXB5J9GE1QE7"}, "message": "success"}

次に、同じ bearer トークンを使って GET /v1/tasks/<taskId> を data.status が "processing" から変わるまでポーリングします。このモデルでは、テストでおよそ 5 秒かかりました:

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KZ59B7ZJ7012PXB5J9GE1QE7 \
  -H "Authorization: Bearer $HIAPI_KEY"
{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01KZ59B7ZJ7012PXB5J9GE1QE7",
    "status": "success",
    "model": "qwen-audio-3.0-tts-plus",
    "storage": "temp",
    "created": 1785810231,
    "completed": 1785810236,
    "output": [{"type": "audio", "url": "https://temp.hiapi.ai/.../01KZ59B7ZJ7012PXB5J9GE1QE7-0.mp3", "artifactId": "66654", "expireAt": 1786415036}]
  },
  "message": "success"
}

output[0].url は実際にダウンロード可能な MP3 です(content-type: audio/mpeg。直接取得して確認済み)。これは一時リンクです。storage がデフォルト値の "temp" のままの場合、expireAt は created のほぼちょうど 7 日後になります。そのため、音声を長期保存する必要がある場合は、バイトデータをダウンロードして自身で保存してください。

Python

import os
import time
import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
headers = {"Authorization": f"Bearer {os.environ['HIAPI_KEY']}"}

resp = requests.post(
    API_BASE,
    headers={**headers, "Content-Type": "application/json"},
    json={
        "model": "qwen-audio-3.0-tts-plus",
        "input": {
            "text": "Welcome to hiapi, the unified API for AI models.",
            "voice": "longanlingxin",
        },
    },
    timeout=30,
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]

while True:
    task = requests.get(f"{API_BASE}/{task_id}", headers=headers, timeout=30).json()["data"]
    if task["status"] == "success":
        audio_url = task["output"][0]["url"]
        break
    if task["status"] == "fail":
        raise RuntimeError(task["error"])
    time.sleep(2)

audio_bytes = requests.get(audio_url, timeout=60).content
with open("output.mp3", "wb") as f:
    f.write(audio_bytes)

本番運用のパターン

完全な入力スキーマ

input オブジェクトは以下のフィールドのみを受け付けます。API はそれ以外のフィールドを 400 で拒否するため、他の TTS プロバイダーからパラメータ名を持ち込まないでください:

フィールド 必須 型 / 値
text はい 文字列
voice はい "longanlingxin"、"longanlufeng" のいずれか(このモデルで現在利用できる音色は 2 つだけです)
format いいえ "pcm"、"wav"、"mp3"、"opus" のいずれか。省略時は mp3 がデフォルトです
sample_rate いいえ 8000、16000、22050、24000、44100、48000 のいずれか
pitch いいえ 数値、0.5–2
volume いいえ 数値、0–100

上記の各境界値と列挙値は API 自身の検証エラーに由来します。無効な voice や範囲外の pitch を渡すと、hiapi は許可されている値を正確に教えてくれます:

{"code": 400, "data": null, "error_code": "INVALID_REQUEST", "message": "invalid input: voice: value must be one of 'longanlingxin', 'longanlufeng'"}

このモデルには emotion、speed、SSML スタイルの制御フィールドはありません。これらのフィールドを含むリクエストは "additional properties '...' not allowed" で失敗します。

コールバック vs. ポーリング

簡単なスクリプトの範囲を超えるあらゆるケースでは、ポーリングをやめて hiapi に結果をプッシュさせましょう。タスク作成リクエストに callback オブジェクトを追加します:

{
  "model": "qwen-audio-3.0-tts-plus",
  "callback": {"url": "https://example.com/hiapi/callback", "when": "final"},
  "input": {"text": "Welcome to hiapi.", "voice": "longanlingxin"}
}

"final" は現在 when で唯一サポートされている値です。タスクの成功・失敗にかかわらず、hiapi は callback.url に 1 回 POST し、そのペイロードから GET /v1/tasks/<taskId> をポーリングしたときと同じタスク詳細の形態を読み取ることができます。callback を完全に省略し、上記の例のように自分でポーリングする方法でも構いません。

また、知っておく価値があるのは、タスクの出力はデフォルトで storage: "temp" であることです(上記の expireAt の値が示すように、ファイルは約 1 週間保持されます)。音声を長期的に取得可能にする必要がある場合は、タスクに "storage": "persistent" を設定してください。永続ストレージはサイズに応じて課金されるため、一度きりの生成ではダウンロードして自身で保存するほうが通常は安価です。

冪等性とリトライ

POST /v1/tasks は Idempotency-Key リクエストヘッダー(最大 255 バイト)を受け付けます。同じアカウントで同じキーを使って同じリクエストをリトライしても、タスクは 1 回しか作成されません。再生時は元の taskId が返り、2 回目の課金対象の生成にはなりません。タイムアウトや 5xx の後、最初のリクエストが到達したかどうか確実にわからない場合のリトライに使用します:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: tts-job-42" \
  -d '{"model": "qwen-audio-3.0-tts-plus", "input": {"text": "...", "voice": "longanlingxin"}}'

エラーハンドリング

無効または未認証のキーは HTTP 401 を返し、hiapi の標準エラーエンベロープが付きます(このモデルに対して直接検証済み):

{"error": {"code": "permission_denied", "message": "This API key cannot use the selected model...", "request_id": "...", "type": "hiapi_error"}}

誤った input ペイロードは HTTP 400 を返し、error_code: "INVALID_REQUEST" と、上記のスキーマのセクションに示した違反フィールドを指す message が付きます。人間が読めるメッセージ本文ではなく、error_code / error.code で分岐してください。タスクが作成時に失敗するのではなく終端状態の "fail" に達した場合、タスク詳細のレスポンスはトップレベルの error キーではなく、data.error(code + message)の下に同じ形態を格納します。

関連記事

よくある質問

音声生成は hiapi の画像/動画タスク API と異なりますか? いいえ。同じ POST /v1/tasks キュー、同じ作成後のポーリングまたはコールバックのフロー、同じ output[0].url の形態です。異なるのは output[0].type(ここでは "audio")と、モデルごとの input スキーマだけです。

format を設定しないとどうなりますか? MP3 が返ります。テストで省略して確認済みです。wav、pcm、opus が必要な場合は、format を明示的に設定してください。

タスクの完了を待たずに音声をストリーミングできますか? いいえ。このモデルは標準的な作成/ポーリング/コールバックのタスクフローのみを公開しており、入力スキーマにストリーミング用のパラメータはありません。また生成は十分に高速(短いテキストなら数秒)なので、1〜2 秒ごとのポーリングで通常は十分です。

出力 URL はどのくらい有効ですか? デフォルトでは約 7 日間です(storage: "temp")。これはタスクの created と expireAt のタイムスタンプの間隔に基づきます。音声は早めにダウンロードするか、より長期に取得可能にする必要がある場合はタスクに "storage": "persistent" を設定してください。

なぜリクエストが "additional properties ... not allowed" で失敗するのですか? スキーマは厳格です。このモデルは text、voice、format、sample_rate、pitch、volume のみを受け付けます。他の TTS API のパラメータ(emotion や speed など)はここでは認識されず、400 が返ります。

現在の価格はどこで確認できますか? 価格ページ です。本チュートリアルでは価格が変わる可能性があるため、文字単位やリクエスト単位のコストを意図的にハードコードしていません。

永続的なAIアーティファクトで開発を始める

APIキーを取得して、タスクベースの1つのAPIで画像・動画・音声モデルを呼び出せます。

APIドキュメントを読む