HiAPI
Blog

Tutoriel

Comment utiliser qwen-audio-3.0-tts-plus via l'API hiapi : synthèse vocale avec curl et Python

Aug 4, 2026
Comment utiliser qwen-audio-3.0-tts-plus via l'API hiapi : synthèse vocale avec curl et Python

qwen-audio-3.0-tts-plus est un modèle de synthèse vocale accessible via la file de tâches asynchrones unifiée de la plateforme hiapi — le même point de terminaison POST /v1/tasks que celui utilisé pour la génération d'images et de vidéos, et non une API audio dédiée. Vous soumettez le texte, recevez immédiatement un taskId, puis vous interrogez la tâche ou attendez un callback pour obtenir l'URL du fichier audio téléchargeable. Ce tutoriel vous guide à travers une requête fonctionnelle en curl et en Python (vérifiée de bout en bout contre l'API en temps réel), puis présente les modèles de production dont vous aurez réellement besoin : callbacks vs interrogation périodique, nouvelles tentatives idempotentes, et les formes d'erreur exactes à gérer.

Ce que vous allez construire

Un script qui soumet du texte à qwen-audio-3.0-tts-plus, attend la fin de la tâche et télécharge l'audio généré — avec en plus une référence des paramètres et des modèles de gestion d'erreur pour transformer ce script en véritable intégration.

Prérequis : une clé API hiapi. Obtenez-la depuis le tableau de bord hiapi — chacune des requêtes ci-dessous s'authentifie avec Authorization: Bearer sk-<your-key>.

Exemple minimal fonctionnel

curl

Créer la tâche :

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

Interrogez ensuite GET /v1/tasks/<taskId> avec le même jeton bearer jusqu'à ce que data.status quitte "processing". Pour ce modèle, cela a pris environ 5 secondes lors du test :

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 est un MP3 réel téléchargeable (content-type: audio/mpeg — confirmé par un téléchargement direct). Il s'agit d'un lien temporaire : lorsque storage conserve sa valeur par défaut "temp", expireAt se situe presque exactement 7 jours après created, donc si vous devez conserver l'audio à long terme, téléchargez les octets et stockez-les vous-même.

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)

Modèles d'utilisation en production

Schéma d'entrée complet

L'objet input n'accepte que les champs suivants — l'API rejette tout autre champ avec une erreur 400, donc ne reprenez pas les noms de paramètres d'un autre fournisseur TTS :

Champ Obligatoire Type / valeur
text Oui Chaîne de caractères
voice Oui L'une des valeurs "longanlingxin", "longanlufeng" (ce modèle ne propose actuellement que deux voix)
format Non L'une des valeurs "pcm", "wav", "mp3", "opus" — vaut mp3 par défaut si omis
sample_rate Non L'une des valeurs 8000, 16000, 22050, 24000, 44100, 48000
pitch Non Nombre, 0.5–2
volume Non Nombre, 0–100

Chaque limite et chaque valeur d'énumération ci-dessus provient de la validation de l'API elle-même — si vous passez un voice invalide ou un pitch hors limites, hiapi vous indique précisément les valeurs autorisées :

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

Ce modèle ne dispose pas de champs de contrôle de type emotion, speed ou SSML — les requêtes contenant ces champs échouent avec "additional properties '...' not allowed".

Callback vs. interrogation périodique

Pour tout ce qui dépasse le cadre d'un script rapide, abandonnez l'interrogation périodique et laissez hiapi pousser le résultat. Ajoutez un objet callback à la requête de création de tâche :

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

"final" est actuellement la seule valeur prise en charge pour when — que la tâche réussisse ou échoue, hiapi envoie une requête POST à votre callback.url, et vous lisez dans cette charge utile la même forme de détails de tâche que celle renvoyée par l'interrogation de GET /v1/tasks/<taskId>. Omettez complètement callback et interrogez vous-même la tâche, comme dans l'exemple ci-dessus.

Bon à savoir également : la sortie des tâches utilise par défaut storage: "temp" (les fichiers survivent environ une semaine, comme le montre la valeur expireAt ci-dessus). Si vous avez besoin que l'audio reste récupérable à long terme, définissez "storage": "persistent" sur la tâche — le stockage persistant est facturé à la taille, donc pour une génération ponctuelle, il est généralement moins coûteux de télécharger et de stocker vous-même.

Idempotence et nouvelles tentatives

POST /v1/tasks accepte l'en-tête Idempotency-Key (255 octets maximum). Réessayer la même requête avec la même clé sous le même compte ne crée la tâche qu'une seule fois — la relecture renvoie le taskId d'origine au lieu d'une seconde génération facturée. À utiliser pour réessayer après un délai d'attente ou un 5xx, lorsque vous ne savez pas réellement si la première requête a abouti :

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

Gestion des erreurs

Une clé invalide ou non autorisée renvoie HTTP 401 avec l'enveloppe d'erreur standard de hiapi (vérifié directement sur ce modèle) :

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

Une charge utile input incorrecte renvoie HTTP 400 avec error_code: "INVALID_REQUEST" et un message indiquant le champ en cause, comme le montre la section sur le schéma ci-dessus — branchez-vous sur error_code / error.code, pas sur le texte du message lisible par un humain. Si une tâche atteint l'état terminal "fail" plutôt que d'échouer à la création, la réponse de détails de la tâche porte la même forme sous data.error (code + message), et non sous une clé error de niveau supérieur.

Pour aller plus loin

Questions fréquentes

La génération audio diffère-t-elle de l'API de tâches image/vidéo de hiapi ? Non — même file POST /v1/tasks, même flux de création puis interrogation ou callback, même forme output[0].url. Seuls output[0].type (ici "audio") et le schéma input varient selon le modèle.

Que se passe-t-il si je ne définis pas format ? Vous obtenez un MP3 — cela a été confirmé en l'omettant lors du test. Si vous avez besoin de wav, pcm ou opus, définissez explicitement format.

Puis-je diffuser l'audio en streaming au lieu d'attendre la fin de la tâche ? Non. Ce modèle n'expose que le flux de tâches standard création / interrogation / callback — son schéma d'entrée ne comporte aucun paramètre de streaming, et la génération est suffisamment rapide (quelques secondes pour un texte court) pour qu'une interrogation toutes les 1 à 2 secondes suffise généralement.

Combien de temps l'URL de sortie reste-t-elle valide ? Environ 7 jours par défaut (storage: "temp"), d'après l'intervalle entre les horodatages created et expireAt de la tâche. Téléchargez l'audio en temps utile, ou si vous avez besoin qu'il reste récupérable plus longtemps, définissez "storage": "persistent" sur la tâche.

Pourquoi ma requête échoue-t-elle avec « additional properties ... not allowed » ? Le schéma est strict — ce modèle n'accepte que text, voice, format, sample_rate, pitch et volume. Les paramètres provenant d'autres API TTS (comme emotion ou speed) ne sont pas reconnus ici et renverront une erreur 400.

Où trouver les tarifs actuels ? Sur la page de tarification — ce tutoriel ne code volontairement pas en dur de coût par caractère ou par requête, car les tarifs peuvent évoluer.

Articles similaires

Voir tous les articles →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API