HiAPI
Blog

Tutoriale

Come usare qwen-audio-3.0-tts-plus tramite l'API hiapi: sintesi vocale con curl e Python

Aug 4, 2026
Come usare qwen-audio-3.0-tts-plus tramite l'API hiapi: sintesi vocale con curl e Python

qwen-audio-3.0-tts-plus è un modello di sintesi vocale accessibile tramite la coda di attività asincrona unificata della piattaforma hiapi — utilizza lo stesso endpoint POST /v1/tasks della generazione di immagini e video, non un'API audio separata. Invii il testo, ricevi immediatamente un taskId, poi esegui il polling o attendi un callback per ottenere l'URL del file audio scaricabile. Questa guida ti accompagna nella creazione di una richiesta funzionante in curl e Python (verificata end-to-end contro l'API live), per poi illustrare i pattern di produzione di cui hai davvero bisogno: callback vs. polling, retry idempotenti e le forme esatte degli errori da gestire.

Cosa costruirai

Uno script che invia il testo a qwen-audio-3.0-tts-plus, attende il completamento dell'attività e scarica l'audio generato — oltre a un riferimento dei parametri e a pattern di gestione degli errori per trasformare lo script in una vera integrazione.

Prerequisiti: una chiave API hiapi. Ottienila dalla dashboard hiapi — ogni richiesta seguente si autentica con Authorization: Bearer sk-<your-key>.

Esempio minimo funzionante

curl

Crea l'attività:

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"}

Poi esegui il polling di GET /v1/tasks/<taskId> con lo stesso bearer token finché data.status non esce da "processing". Per questo modello, nei test sono serviti circa 5 secondi:

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 è un MP3 realmente scaricabile (content-type: audio/mpeg — confermato con un download diretto). È un link temporaneo: quando storage resta al valore predefinito "temp", expireAt cade quasi esattamente 7 giorni dopo created, quindi se devi conservare l'audio a lungo termine scarica i byte e archiviali tu stesso.

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)

Pattern per l'uso in produzione

Schema completo dell'input

L'oggetto input accetta solo i seguenti campi — l'API rifiuta con 400 qualsiasi altro campo, quindi non riutilizzare nomi di parametri presi da altri fornitori TTS:

Campo Obbligatorio Tipo / valori
text Sì stringa
voice Sì uno tra "longanlingxin", "longanlufeng" (attualmente questo modello ha solo due voci disponibili)
format No uno tra "pcm", "wav", "mp3", "opus" — se omesso, il valore predefinito è mp3
sample_rate No uno tra 8000, 16000, 22050, 24000, 44100, 48000
pitch No numero, 0.5–2
volume No numero, 0–100

Ogni limite ed enumerazione riportati sopra deriva dagli errori di validazione dell'API stessa — se passi un voice non valido o un pitch fuori intervallo, hiapi ti indica esattamente i valori ammessi:

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

Questo modello non ha campi di controllo come emotion, speed o in stile SSML — le richieste che li includono falliscono con "additional properties '...' not allowed".

Callback vs. polling

Per qualsiasi scenario che va oltre un semplice script, evita il polling e lascia che hiapi invii il risultato. Aggiungi un oggetto callback alla richiesta di creazione dell'attività:

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

"final" è attualmente l'unico valore supportato per when — hiapi esegue un POST verso il tuo callback.url una sola volta, sia che l'attività riesca sia che fallisca, e dal payload leggi la stessa forma dei dettagli dell'attività che ottieni con il polling di GET /v1/tasks/<taskId>. Ometti del tutto callback e gestisci il polling da solo, come nell'esempio precedente.

Vale anche la pena sapere: l'output delle attività è per impostazione predefinita storage: "temp" (i file durano circa una settimana, come mostrato dal valore expireAt sopra). Se hai bisogno che l'audio resti recuperabile a lungo, imposta "storage": "persistent" sull'attività — l'archiviazione persistente viene fatturata in base alle dimensioni, quindi per generazioni una tantum di solito è più economico scaricare e archiviare da soli.

Idempotenza e retry

POST /v1/tasks accetta l'header Idempotency-Key (massimo 255 byte). Ripetere la stessa richiesta con la stessa chiave sotto lo stesso account crea l'attività una sola volta — il replay restituisce il taskId originale, non una seconda generazione fatturata. Usalo per ritentare dopo un timeout o un 5xx, quando non sai con certezza se la prima richiesta è arrivata:

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"}}'

Gestione degli errori

Una chiave non valida o non autorizzata restituisce HTTP 401 con la busta di errore standard di hiapi (verificata direttamente su questo modello):

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

Un payload input errato restituisce HTTP 400 con error_code: "INVALID_REQUEST" e un message che indica il campo non valido, come mostrato nella sezione schema sopra — gestisci il flusso in base a error_code / error.code, non al testo del messaggio leggibile. Se l'attività raggiunge lo stato terminale "fail" invece di fallire alla creazione, la risposta con i dettagli dell'attività riporta la stessa forma sotto data.error (code + message), non nella chiave error di primo livello.

Letture correlate

Domande frequenti

La generazione audio è diversa dall'API delle attività immagini/video di hiapi? No — stessa coda POST /v1/tasks, stesso flusso crea-poi-polling o callback, stessa forma output[0].url. Cambiano solo output[0].type (qui "audio") e lo schema input in base al modello.

Cosa succede se non imposto format? Ottieni un MP3 — nei test l'omissione lo ha confermato. Se ti serve wav, pcm o opus, imposta format esplicitamente.

Posso ricevere l'audio in streaming invece di attendere il completamento dell'attività? No. Questo modello espone solo il flusso standard creazione/polling/callback — non ci sono parametri di streaming nel suo schema di input, e la generazione è abbastanza veloce (pochi secondi per testi brevi) che un polling ogni 1-2 secondi di solito è sufficiente.

Per quanto tempo rimane valido l'URL di output? Circa 7 giorni per impostazione predefinita (storage: "temp"), in base all'intervallo tra i timestamp created ed expireAt dell'attività. Scarica l'audio per tempo, oppure imposta "storage": "persistent" sull'attività se hai bisogno di una recuperabilità più lunga.

Perché la mia richiesta fallisce con "additional properties ... not allowed"? Lo schema è rigido — questo modello accetta solo text, voice, format, sample_rate, pitch e volume. I parametri di altre API TTS (come emotion o speed) non sono riconosciuti qui e restituiscono 400.

Dove trovo i prezzi attuali? Nella pagina dei prezzi — questo tutorial evita deliberatamente di codificare un costo per carattere o per richiesta, perché i prezzi possono cambiare.

Inizia a creare con artefatti IA persistenti

Ottieni la tua chiave API e chiama modelli di immagini, video e audio tramite un'unica API basata sui task.

Leggi la documentazione API