HiAPI
Blogue

Tutorial

Como usar qwen-audio-3.0-tts-plus via API hiapi: conversão de texto em fala com curl e Python

Aug 4, 2026
Como usar qwen-audio-3.0-tts-plus via API hiapi: conversão de texto em fala com curl e Python

qwen-audio-3.0-tts-plus é um modelo de conversão de texto em fala, acessado por meio da fila unificada de tarefas assíncronas da plataforma hiapi — o mesmo endpoint POST /v1/tasks usado para geração de imagens e vídeos, e não uma API de áudio separada. Você envia o texto, recebe imediatamente um taskId e então faz polling ou aguarda um callback para obter a URL do arquivo de áudio para download. Este tutorial vai te levar por uma requisição funcional em curl e Python (validada de ponta a ponta com a API em tempo real) e, em seguida, apresenta os padrões de produção que você realmente precisa: callback vs. polling, retentativas idempotentes e as formas exatas de erro que precisam ser tratadas.

O que você vai construir

Um script que envia texto para qwen-audio-3.0-tts-plus, aguarda a conclusão da tarefa e baixa o áudio gerado — além da referência de parâmetros e de padrões de tratamento de erros, para transformar esse script em uma integração de verdade.

Pré-requisitos: uma chave de API hiapi. Obtenha-a no painel da hiapi — cada requisição abaixo é autenticada com Authorization: Bearer sk-<your-key>.

Exemplo mínimo funcional

curl

Crie a tarefa:

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

Em seguida, faça polling de GET /v1/tasks/<taskId> com o mesmo token bearer até que data.status saia de "processing". Para este modelo, os testes levaram cerca de 5 segundos:

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 é um MP3 real e baixável (content-type: audio/mpeg — confirmado com uma requisição direta). Trata-se de um link temporário: quando storage mantém o valor padrão "temp", expireAt fica quase exatamente 7 dias após created, então, se você precisar reter o áudio por mais tempo, baixe os bytes e armazene por conta própria.

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)

Padrões de uso em produção

Esquema completo de entrada

O objeto input aceita apenas os campos abaixo — a API rejeita qualquer outro campo com 400, então não reaproveite nomes de parâmetros de outros provedores de TTS:

Campo Obrigatório Tipo / valor
text Sim String
voice Sim Um de "longanlingxin", "longanlufeng" (este modelo atualmente só tem dois timbres disponíveis)
format Não Um de "pcm", "wav", "mp3", "opus" — o padrão quando omitido é mp3
sample_rate Não Um de 8000, 16000, 22050, 24000, 44100, 48000
pitch Não Número, 0.5–2
volume Não Número, 0–100

Cada limite e valor de enumeração acima vem dos próprios erros de validação da API — se você enviar um voice inválido ou um pitch fora do intervalo, a hiapi informa exatamente os valores permitidos:

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

Este modelo não tem campos de controle como emotion, speed ou estilo SSML — requisições que os incluam falham com "additional properties '...' not allowed".

Callback vs. polling

Para qualquer caso que vá além de scripts rápidos, dispense o polling e deixe a hiapi enviar o resultado. Adicione um objeto callback à requisição de criação de tarefa:

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

"final" é atualmente o único valor suportado para when — seja a tarefa concluída com sucesso ou com falha, a hiapi fará um POST em callback.url, e você lê desse payload o mesmo formato de detalhes da tarefa que obteria via polling de GET /v1/tasks/<taskId>. Se preferir, omita totalmente o callback e faça polling por conta própria, como nos exemplos acima.

Também vale saber: a saída da tarefa usa storage: "temp" por padrão (os arquivos duram cerca de uma semana, como mostra o valor de expireAt acima). Se você precisa que o áudio permaneça recuperável por mais tempo, defina "storage": "persistent" na tarefa — o armazenamento persistente é cobrado por tamanho, então, para gerações pontuais, geralmente sai mais barato baixar e armazenar por conta própria.

Idempotência e retentativas

POST /v1/tasks aceita o cabeçalho Idempotency-Key (até 255 bytes). Repetir a mesma requisição com a mesma chave na mesma conta cria a tarefa apenas uma vez — o reenvio retorna o taskId original, em vez de uma segunda geração cobrada. Use isso para retentar após timeouts ou 5xx, quando você não sabe ao certo se a primeira requisição chegou:

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

Tratamento de erros

Uma chave inválida ou não autorizada retorna HTTP 401, com o envelope de erro padrão da hiapi (validado diretamente neste modelo):

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

Um payload input incorreto retorna HTTP 400, com error_code: "INVALID_REQUEST" e uma message que indica o campo infrator, como mostrado na seção de esquema acima — faça o branching com base em error_code / error.code, e não no texto legível da mensagem. Se a tarefa atingir o estado terminal "fail" em vez de falhar na criação, a resposta de detalhes da tarefa carrega o mesmo formato em data.error (code + message), em vez da chave error no nível superior.

Leituras relacionadas

Perguntas frequentes

A geração de áudio é diferente da API de tarefas de imagem/vídeo da hiapi? Não — é a mesma fila POST /v1/tasks, o mesmo fluxo de polling ou callback após a criação e o mesmo formato output[0].url. Apenas output[0].type (aqui, "audio") e o esquema de input variam por modelo.

O que acontece se eu não definir format? Você recebe um MP3 — confirmado nos testes ao omiti-lo. Se precisar de wav, pcm ou opus, defina format explicitamente.

Posso transmitir o áudio em streaming em vez de esperar a tarefa concluir? Não. Este modelo só expõe o fluxo padrão de tarefas criar/polling/callback — não há parâmetro de streaming no esquema de entrada, e a geração é rápida o suficiente (alguns segundos para textos curtos), então fazer polling a cada 1–2 segundos normalmente basta.

Por quanto tempo a URL de saída permanece válida? Cerca de 7 dias por padrão (storage: "temp"), com base no intervalo entre os timestamps created e expireAt da tarefa. Baixe o áudio logo, ou defina "storage": "persistent" na tarefa se precisar de recuperação por mais tempo.

Por que minha requisição falha com "additional properties ... not allowed"? O esquema é estrito — este modelo aceita apenas text, voice, format, sample_rate, pitch e volume. Parâmetros vindos de outras APIs de TTS (como emotion ou speed) não são reconhecidos aqui e retornam 400.

Onde encontro o preço atual? Na página de preços — este tutorial deliberadamente não fixa custos por caractere ou por requisição, já que os preços podem mudar.

Artigos relacionados

Ver todos os artigos →

Comece a criar com artefactos de IA persistentes

Obtenha a sua chave de API e chame modelos de imagem, vídeo e áudio através de uma única API baseada em tasks.

Ler a documentação da API