Áudio na API Oficial do WhatsApp: por que o áudio chega como arquivo (e os 3 bugs que você precisa corrigir juntos)
Enviar OGG na Cloud API não basta para virar push-to-talk com ondinha. São três bugs empilhados: voice:true no payload, Content-Type audio/ogg sem codecs=opus, metadata MP4 dentro do OGG (erro 131053), start_time negativo e Opus estéreo que quebra no iOS. Receita ffmpeg e checklist de envio.
Áudio na API oficial parece o caso mais simples de mídia na Cloud API. Um OGG, um upload, um send. É também onde integrações que já mandam imagem e PDF quebram sem erro claro.
O fluxo típico: grava no browser, converte para OGG, sobe na /media, manda com "type": "audio". No celular do cliente aparece arquivo genérico, não a ondinha de push-to-talk. Outra vez a Meta devolve 131053, o upload vira application/octet-stream e a mensagem nem sai. Outra ainda entrega, toca no WhatsApp Web, e no iPhone aparece “áudio não disponível”.
Cada sintoma aponta para uma camada diferente (payload, upload, container). Não é um bug. São três bugs empilhados. Corrigir um e pular os outros só troca o erro que você vê amanhã.
Este guia mapeia os três, a receita ffmpeg que a comunidade validou em produção, e o detalhe de arquitetura que impede um caso limpo de escapar na próxima gravação.
Escopo: envio de áudio na API oficial (push-to-talk) via Cloud API. Áudio como arquivo anexo (sem
voice: true) é outro produto. Erros gerais de mídia → guia de erros da API (código 131053 na tabela mestra).
Bug 1: chegar com ondinha (push-to-talk), não como arquivo
Não basta mandar OGG/Opus. A Meta só renderiza waveform se duas condições forem verdade ao mesmo tempo:
| Condição | Valor |
|---|---|
| Container / codec | OGG com Opus |
| Payload da mensagem | "voice": true dentro do objeto audio |
OGG sem voice: true chega como arquivo (ícone de documento, sem ondinha). Esse é o parâmetro de push-to-talk que aparece nos fóruns como “detalhe obscuro” da documentação.
Upload (POST /{phone-number-id}/media):
{
"type": "audio",
"audio": {
"id": "<media_id>",
"voice": true
}
}
Sem "voice": true, você entregou um MP3 disfarçado: formato certo, experiência errada.
Bug 2: erro 131053 (vira application/octet-stream e não envia)
O 131053 na Cloud API costuma aparecer como falha de upload ou download de mídia. No caso de áudio convertido no browser, há duas causas distintas. As duas precisam ser tratadas.
Causa A: Content-Type com parâmetro de codec
No upload para /media, mande Content-Type: audio/ogg puro.
A Meta aceita audio/ogg; codecs=opus no upload, mas rejeita na entrega. O parâmetro ; codecs=... precisa sair antes do envio final.
| Header | Resultado |
|---|---|
audio/ogg; codecs=opus |
Upload pode passar; entrega falha ou classifica errado |
audio/ogg |
Caminho validado em produção |
Causa B: metadata de MP4/WebM dentro do OGG
O OGG gerado pelo browser (conversão webm/mp4 → ogg) carrega vestígios do container original: strings como major_brand=isom, ...vp09... embutidas no arquivo.
A Meta fareja essas strings dentro do OGG, conclui que o tipo real é desconhecido, e trata como application/octet-stream. Daí o 131053.
Fix: limpar metadata e re-paginar o container:
ffmpeg -i in.ogg -map_metadata -1 -c copy \
-avoid_negative_ts make_zero -f ogg out.ogg
(-map_metadata -1 zera tags; -f ogg força re-page do container.)
Bug 3: play no iOS (“áudio não disponível”)
O mais traiçoeiro: toca no WhatsApp Web e quebra só no iPhone.
start_time negativo
Gravações nativas de iOS (e alguns encoders) reportam encoder-delay com start_time negativo (tipicamente ~−0,000625 s). Players tolerantes ignoram; o cliente WhatsApp no iOS, não.
Fix: -avoid_negative_ts make_zero (zera o início do stream).
Opus estéreo
A Meta aceita e entrega Opus estéreo. O WhatsApp do destinatário, porém, não toca (a bolha muda de estado, principalmente no iOS). Áudio push-to-talk tem que ser mono.
Fix: -ac 1.
Receita ffmpeg (normalização em background)
Detalhe de arquitetura que fez diferença: não decidir “converter ou não”. Todo áudio de saída passa pela normalização. Arquivo já compatível → remux lossless (-c copy, custo baixíssimo, zero perda). Só o que está realmente quebrado → transcode. Assim nunca escapa um start_time negativo ou um estéreo escondido.
Caso 1: já é OGG/Opus mono
Remux lossless, sem perder qualidade:
ffmpeg -i in.ogg -map_metadata -1 -c copy \
-avoid_negative_ts make_zero -f ogg out.ogg
Caso 2: estéreo, webm, mp4 ou qualquer outra origem
Transcode para mono Opus:
ffmpeg -i in.* -map_metadata -1 -c:a libopus \
-b:a 128k -ar 48000 -ac 1 \
-avoid_negative_ts make_zero -f ogg out.ogg
Parâmetros que importam:
| Flag | Por quê |
|---|---|
-map_metadata -1 |
Remove metadata MP4/WebM que dispara 131053 |
-avoid_negative_ts make_zero |
Corrige play no iOS |
-ac 1 |
Áudio mono (push-to-talk; estéreo quebra no destinatário) |
-ar 48000 |
Taxa padrão Opus/WhatsApp |
-b:a 128k |
Qualidade suficiente para voz |
-f ogg |
Re-page do container após limpeza |
Checklist de envio para a Meta
| Etapa | O que fazer |
|---|---|
| 1. Normalizar | Rodar ffmpeg (sempre, mesmo se “já é OGG”) |
| 2. Upload | POST /media com body OGG e header Content-Type: audio/ogg (sem codecs=) |
| 3. Mensagem | "type": "audio", "audio": { "id": "<media_id>", "voice": true } |
| 4. Validar | Enviar teste para iPhone e Android antes de liberar em produção |
Sintomas → causa → ação
| Sintoma | Causa provável | Ação |
|---|---|---|
| Ícone de arquivo, sem ondinha | OGG ok, falta voice: true |
Adicionar "voice": true no objeto audio |
| 131053 no webhook / upload rejeitado | Content-Type com codecs= ou metadata MP4 no OGG |
Header audio/ogg puro + -map_metadata -1 |
| Toca no Web, “áudio não disponível” no iPhone | start_time negativo |
-avoid_negative_ts make_zero |
| Bolha muda, sem som (iOS) | Opus estéreo | -ac 1 na normalização |
| Funcionava ontem, quebrou hoje | Nova origem (ex.: gravador iOS nativo) | Pipeline universal: sempre normalizar |
FAQ
Dá para mandar MP3 ou M4A com voice: true? Não conte com isso. O caminho validado é OGG/Opus mono normalizado + voice: true.
Preciso transcodificar se o arquivo “já é OGG”? Sim, pelo menos remux com -map_metadata -1 e -avoid_negative_ts make_zero. O custo de -c copy é desprezível e pega metadata fantasma e timestamp negativo que passam despercebidos.
O 131053 é só de áudio? Não. O código cobre falha geral de mídia (tipo, tamanho, codec). Para áudio de voz, as causas acima são as que mais aparecem quando a origem é browser ou conversão client-side. Ver também a tabela 131xxx.
WhatsApp Web aceita estéreo; por que forçar mono? Porque o destino real é o app mobile do cliente. A Meta entrega; o player do WhatsApp no celular (especialmente iOS) não reproduz Opus estéreo como push-to-talk.
O parâmetro voice aparece na documentação? Sim, no objeto audio do Messages API. É fácil omitir porque exemplos genéricos de áudio não incluem o flag.
Créditos
Investigação completa deste encadeamento (browser → OGG → 131053 → iOS) conduzida na comunidade WhatsApp Founders por Lucas Rafagnin (Dev ITA Jr / Bola8), com apoio do time ChatJur, do sintoma “chega como arquivo” até a receita ffmpeg que roda em background hoje.
Referências: WhatsApp Cloud API: Audio messages, Media API. Comportamento de player pode variar por versão do app. Valide sempre em dispositivo real.
Conteúdo da comunidade WhatsApp Founders 🇧🇷. Independente, sem vínculo oficial com o WhatsApp ou a Meta.