DEV Community

Cover image for Como Usar Qwen3.5-Omni: Texto, Áudio, Vídeo e Clonagem de Voz via API
Lucas
Lucas

Posted on • Originally published at apidog.com

Como Usar Qwen3.5-Omni: Texto, Áudio, Vídeo e Clonagem de Voz via API

TL;DR

Qwen3.5-Omni aceita texto, imagens, áudio e vídeo como entrada e retorna texto ou fala em tempo real. Acesse-o através da API DashScope da Alibaba Cloud ou execute-o localmente via HuggingFace Transformers. Este guia abrange a configuração da API, exemplos de código funcionais para cada modalidade, clonagem de voz e como testar suas solicitações com o Apidog.

Experimente o Apidog hoje mesmo

Com o que você está trabalhando

Qwen3.5-Omni é um modelo que lida com texto, imagens, áudio e vídeo simultaneamente, retornando texto ou fala natural conforme sua configuração.

Qwen3.5-Omni

Arquitetura Thinker-Talker com backbone MoE. O Thinker processa a entrada multimodal; o Talker converte a saída em fala via sistema multi-codebook que transmite áudio antes da resposta completa.

Três variantes:

  • Plus: Qualidade máxima, ideal para raciocínio e clonagem de voz
  • Flash: Equilíbrio entre velocidade e qualidade; recomendado para produção
  • Light: Latência mínima, indicado para edge/mobile

Este guia utiliza Flash como padrão. Troque para Plus para máxima qualidade.

Acesso à API via DashScope

A maneira principal de usar o Qwen3.5-Omni em produção é via API DashScope da Alibaba Cloud. Você precisará de uma conta e chave de API.

Passo 1: Crie uma conta DashScope

Acesse dashscope.aliyuncs.com e faça cadastro ou login com sua conta Alibaba Cloud.

Passo 2: Obtenha sua chave de API

  1. Faça login no console DashScope
  2. Clique em API Key Management na barra lateral
  3. Clique em Create API Key
  4. Copie a chave no formato sk-...

Passo 3: Instale o SDK

pip install dashscope
Enter fullscreen mode Exit fullscreen mode

Ou use o endpoint compatível com OpenAI:

pip install openai
Enter fullscreen mode Exit fullscreen mode

O DashScope expõe uma API compatível com OpenAI em https://dashscope.aliyuncs.com/compatible-mode/v1. Basta trocar seu base_url e usar a mesma lógica dos exemplos OpenAI.

Entrada e saída de texto

Envie texto e receba texto como resposta:

from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    messages=[
        {
            "role": "user",
            "content": "Explique a diferença entre APIs REST e GraphQL em termos simples."
        }
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Troque para qwen3.5-omni-plus para tarefas mais complexas ou qwen3.5-omni-light para priorizar latência.


Entrada de áudio: transcrição e compreensão

Envie um arquivo de áudio (URL ou base64) e o modelo transcreve, compreende e raciocina sobre o conteúdo.

import base64
from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

with open("meeting_recording.wav", "rb") as f:
    audio_data = base64.b64encode(f.read()).decode("utf-8")

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "input_audio",
                    "input_audio": {
                        "data": audio_data,
                        "format": "wav"
                    }
                },
                {
                    "type": "text",
                    "text": "Resuma as principais decisões desta reunião e liste os itens de ação."
                }
            ]
        }
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode
  • Suporte a 113 idiomas (detecção automática)
  • Formatos: WAV, MP3, M4A, OGG, FLAC

Saída de áudio: conversão de texto em fala

Defina modalities e configure a saída de áudio para obter resposta falada:

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    modalities=["text", "audio"],
    audio={"voice": "Chelsie", "format": "wav"},
    messages=[
        {
            "role": "user",
            "content": "Descreva os passos para autenticar uma API REST usando OAuth 2.0."
        }
    ],
)

text_content = response.choices[0].message.content
audio_data = response.choices[0].message.audio.data

with open("response.wav", "wb") as f:
    f.write(base64.b64decode(audio_data))

print(f"Texto: {text_content}")
print("Áudio salvo em response.wav")
Enter fullscreen mode Exit fullscreen mode
  • Vozes: Chelsie (feminina) e Ethan (masculina)
  • TTS disponível em 36 idiomas

Entrada de imagem: compreensão visual

Envie uma imagem (URL ou base64) e uma pergunta:

from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://example.com/api-diagram.png"
                    }
                },
                {
                    "type": "text",
                    "text": "Descreva este diagrama de arquitetura de API e identifique possíveis gargalos."
                }
            ]
        }
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Para imagens locais (base64):

import base64

with open("screenshot.png", "rb") as f:
    image_data = base64.b64encode(f.read()).decode("utf-8")

image_url = f"data:image/png;base64,{image_data}"

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": image_url}
                },
                {
                    "type": "text",
                    "text": "Qual erro aparece nesta captura de tela?"
                }
            ]
        }
    ],
)
Enter fullscreen mode Exit fullscreen mode

Entrada de vídeo: compreensão de gravações

Qwen3.5-Omni processa vídeo (visual e áudio) simultaneamente.

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

response = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "video_url",
                    "video_url": {
                        "url": "https://example.com/product-demo.mp4"
                    }
                },
                {
                    "type": "text",
                    "text": "Descreva o que o desenvolvedor está construindo neste demo e escreva o código equivalente."
                }
            ]
        }
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Vibe Coding: geração de código via gravação de tela

with open("screen_recording.mp4", "rb") as f:
    video_data = base64.b64encode(f.read()).decode("utf-8")

response = client.chat.completions.create(
    model="qwen3.5-omni-plus",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "video_url",
                    "video_url": {
                        "url": f"data:video/mp4;base64,{video_data}"
                    }
                },
                {
                    "type": "text",
                    "text": "Assista a esta gravação de tela e gere o código completo que replica o que está sendo construído, incluindo todos os componentes de UI e interações."
                }
            ]
        }
    ],
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode
  • Janela de contexto: 256K tokens (~400s de vídeo 720p com áudio)
  • Para vídeos longos, corte ou divida em partes menores

Clonagem de voz

Disponível em Plus e Flash via API. Envie uma amostra de voz (10-30s) para clonar.

import base64
from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

with open("voice_sample.wav", "rb") as f:
    voice_sample = base64.b64encode(f.read()).decode("utf-8")

response = client.chat.completions.create(
    model="qwen3.5-omni-plus",
    modalities=["text", "audio"],
    audio={
        "voice": "custom",
        "format": "wav",
        "voice_sample": {
            "data": voice_sample,
            "format": "wav"
        }
    },
    messages=[
        {
            "role": "user",
            "content": "Bem-vindo ao portal do desenvolvedor Apidog. Como posso ajudar?"
        }
    ],
)

audio_data = response.choices[0].message.audio.data
with open("cloned_response.wav", "wb") as f:
    f.write(base64.b64decode(audio_data))
Enter fullscreen mode Exit fullscreen mode

Dicas de qualidade:

  • Use gravação limpa, sem ruído
  • 15-30s de áudio, formato WAV 16kHz+
  • Prefira fala natural

Respostas em streaming

Para voz em tempo real ou UI interativa, utilize streaming:

from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

stream = client.chat.completions.create(
    model="qwen3.5-omni-flash",
    modalities=["text", "audio"],
    audio={"voice": "Ethan", "format": "pcm16"},
    messages=[
        {
            "role": "user",
            "content": "Explique como WebSocket difere do HTTP polling."
        }
    ],
    stream=True,
)

audio_chunks = []
text_chunks = []

for chunk in stream:
    delta = chunk.choices[0].delta
    if hasattr(delta, "audio") and delta.audio:
        if delta.audio.get("data"):
            audio_chunks.append(delta.audio["data"])
    if delta.content:
        text_chunks.append(delta.content)
        print(delta.content, end="", flush=True)

print()  # Quebra de linha após o texto

if audio_chunks:
    import base64
    full_audio = b"".join(base64.b64decode(chunk) for chunk in audio_chunks)
    with open("streamed_response.pcm", "wb") as f:
        f.write(full_audio)
Enter fullscreen mode Exit fullscreen mode
  • PCM16 é recomendado para streaming: pode ser enviado ao buffer de áudio diretamente.

Conversa multi-turno com modalidades mistas

Gerencie histórico e múltiplas modalidades na conversa:

from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
)

conversation = []

def send_message(content_parts):
    conversation.append({"role": "user", "content": content_parts})
    response = client.chat.completions.create(
        model="qwen3.5-omni-flash",
        messages=conversation,
    )
    reply = response.choices[0].message.content
    conversation.append({"role": "assistant", "content": reply})
    return reply

# Turno 1: texto
print(send_message([{"type": "text", "text": "Minha API retorna erro 503 constantemente."}]))

# Turno 2: imagem
import base64
with open("error_log.png", "rb") as f:
    img = base64.b64encode(f.read()).decode()

print(send_message([
    {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img}"}},
    {"type": "text", "text": "Segue o log de erro. O que está causando isso?"}
]))

# Turno 3: texto
print(send_message([{"type": "text", "text": "Como corrijo a exaustão do pool de conexões mencionada?"}]))
Enter fullscreen mode Exit fullscreen mode
  • Contexto de 256K tokens: mantenha conversas longas, multimodais, sem truncamento.

Implantação local com HuggingFace

Execute Qwen3.5-Omni localmente:

pip install transformers==4.57.3
pip install accelerate
pip install qwen-omni-utils -U
pip install -U flash-attn --no-build-isolation
Enter fullscreen mode Exit fullscreen mode
import soundfile as sf
from transformers import Qwen3OmniMoeForConditionalGeneration, Qwen3OmniMoeProcessor
from qwen_omni_utils import process_mm_info

model_path = "Qwen/Qwen3-Omni-30B-A3B-Instruct"

model = Qwen3OmniMoeForConditionalGeneration.from_pretrained(
    model_path,
    device_map="auto",
    attn_implementation="flash_attention_2",
)
processor = Qwen3OmniMoeProcessor.from_pretrained(model_path)

conversation = [
    {
        "role": "system",
        "content": [
            {"type": "text", "text": "Você é Qwen, humano virtual da Alibaba, capaz de processar entrada auditiva e visual e gerar texto e fala."}
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "audio", "audio": "path/to/your/audio.wav"},
            {"type": "text", "text": "Sobre o que é este áudio?"}
        ],
    },
]

text = processor.apply_chat_template(
    conversation,
    add_generation_prompt=True,
    tokenize=False,
)
audios, images, videos = process_mm_info(conversation, use_audio_in_video=True)
inputs = processor(
    text=text,
    audio=audios,
    images=images,
    videos=videos,
    return_tensors="pt",
    padding=True,
)
inputs = inputs.to(model.device).to(model.dtype)

text_ids, audio_output = model.generate(**inputs, speaker="Chelsie")

text_response = processor.batch_decode(text_ids, skip_special_tokens=True)[0]
sf.write("local_response.wav", audio_output.reshape(-1).cpu().numpy(), samplerate=24000)

print(text_response)
Enter fullscreen mode Exit fullscreen mode

Requisitos mínimos de VRAM:

Variante Precisão VRAM Mínima
Plus (30B MoE) BF16 ~40GB
Flash BF16 ~20GB
Light BF16 ~10GB

Para produção local, prefira vLLM ao invés de HuggingFace Transformers para melhor desempenho com modelos MoE.

Testando suas solicitações Qwen3.5-Omni com Apidog

APIs multimodais envolvem áudio/vídeo base64, arrays de conteúdo e respostas compostas. Fazer isso manualmente é trabalhoso.

Apidog multimodal

Apidog facilita o teste de endpoints DashScope. Crie uma coleção, armazene sua chave de API como variável de ambiente, e modele solicitações para cada modalidade.

  • Duplique solicitações para cada variante (Plus, Flash, Light) e compare facilmente latência, qualidade e resposta.
  • Adicione asserções:
    • Verifique se choices[0].message.content não está vazio (texto)
    • Verifique se choices[0].message.audio.data existe (áudio)
    • Confirme latência da Flash abaixo do limite definido

Essas práticas ajudam na escolha da variante ideal para produção.

Tratamento de erros e lógica de repetição

Implemente retry para lidar com rate limits e timeouts, comuns em entradas grandes (especialmente vídeo):

import time
import random
from openai import OpenAI, RateLimitError, APITimeoutError, APIConnectionError

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-YOUR_DASHSCOPE_KEY",
    timeout=120,
)

def call_with_retry(messages, model="qwen3.5-omni-flash", max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.chat.completions.create(
                model=model,
                messages=messages,
            )
        except RateLimitError:
            wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Limite atingido. Esperando {wait:.1f}s...")
            time.sleep(wait)
        except (APITimeoutError, APIConnectionError) as e:
            if attempt == max_retries - 1:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Erro de conexão: {e}. Tentando novamente em {wait:.1f}s...")
            time.sleep(wait)
    raise RuntimeError(f"Falha após {max_retries} tentativas")
Enter fullscreen mode Exit fullscreen mode

Para arquivos de vídeo acima de 100MB:

  • Corte o trecho relevante antes de enviar
  • Reduza para 480p se possível
  • Divida gravações longas e agregue depois

Problemas comuns e soluções

Áudio distorcido em números ou termos técnicos:

Use Qwen3.5-Omni atualizado; se auto-hospedando, baixe os pesos mais recentes.

Modelo não para após interrupção de áudio:

Interrupção semântica exige Flash ou Plus, além de streaming ativado.

Clonagem de voz ruim:

Amostra deve ser limpa, sem ruído, com pelo menos 15s. Formato WAV 16kHz+.

Erro de limite de tokens em vídeo:

256K tokens ≈ 400s de vídeo 720p. Corte para 6 minutos ou menos.

Inferência local lenta:

Use vLLM ao invés de Transformers para produção.

FAQ

Qual ID de modelo DashScope devo usar para Qwen3.5-Omni?

Use qwen3.5-omni-plus, qwen3.5-omni-flash ou qwen3.5-omni-light conforme qualidade e latência desejadas. Flash é o padrão recomendado.

Posso usar o SDK Python do OpenAI com DashScope?

Sim. Defina base_url="https://dashscope.aliyuncs.com/compatible-mode/v1" e use sua chave DashScope como api_key. O formato é idêntico ao da OpenAI.

Como envio vários arquivos (áudio + imagem) em uma solicitação?

Inclua ambos no array content como objetos tipados distintos, junto ao prompt de texto. Todas as modalidades podem ser combinadas.

Existe limite de tamanho para áudio/vídeo?

DashScope aplica limites de payload. Para arquivos grandes, hospede externamente e envie o URL nos campos audio ou video_url.

Como desativo a saída de áudio e recebo só texto?

Defina modalities=["text"] ou omita o parâmetro. Só texto é mais rápido e barato.

Suporta chamada de função/ferramenta?

Sim. Use o parâmetro tools como na OpenAI, e o modelo retorna objetos de função para execução.

Melhor forma de processar gravações de áudio longas?

Até 10 horas: envie em uma única solicitação. Acima disso, divida em segmentos e agregue os resultados.

Como testo solicitações multimodais antes de construir o app?

Use o Apidog para construir e salvar modelos de requisição, alternar variantes, inspecionar respostas e escrever asserções sem precisar codificar a aplicação primeiro.

Top comments (0)