Caso:
Hola espero que alguien me pueda ayudar, me dejaron un proyecto de la escuela de crear un chatbot en n8n y mandar mensaje a WhatsApp y que al momento de yo mandar audio el bot me responda de igual por voz si alguien me puede decir paso a paso de como hacerlo lo agradecería demasiado 😿
Requisitos
- Cuenta WhatsApp Business Cloud API (o Twilio WhatsApp) con
PHONE_NUMBER_IDyACCESS_TOKEN. - Instancia pública de n8n (o ngrok para desarrollo).
- Cuenta de Speech-to-Text (ej. OpenAI / Whisper) y de TTS (ej. ElevenLabs, OpenAI TTS, Google o Azure).
- Opcional: FFmpeg si necesitas transcodificar audio (opus/ogg ↔ wav/mp3).
Resumen del workflow (nodos en n8n)
- Webhook (Trigger) — recibe payload de WhatsApp.
- Function / Set — extrae
media_idy número origen. - HTTP Request — GET Retrieve Media (Graph API) → devuelve
url. - HTTP Request — descargar
url→ guarda binario (audio_in). - HTTP Request / Nodo OpenAI — POST a STT (Whisper) con el binario → obtiene
transcript. - OpenAI / HTTP Request — enviar
transcripta LLM → obtenerreply_text. - HTTP Request — POST a servicio TTS (ElevenLabs / OpenAI TTS) con
reply_text→ recibir audio (audio_out). - HTTP Request — POST upload media a WhatsApp → recibir
media_id_wh. - HTTP Request — POST send message (tipo audio) con
media_id_wh.
1) Webhook en n8n
Crea un nodo Webhook en n8n con Method = POST. Copia la URL pública y configúrala en Meta Developers (App → Webhooks) para tu número de WhatsApp Cloud API.
Ejemplo de payload entrante (simplificado)
{
"entry": [
{
"changes": [
{
"value": {
"messages": [
{
"id": "wamid.HBgL...",
"from": "54911xxxxxxx",
"type": "audio",
"audio": { "id": "MEDIA_ID_FROM_WHATSAPP" }
}
]
}
}
]
}
]
}
En el nodo Function/Set extrae $json["entry"][0].changes[0].value.messages[0] y guarda media_id y from.
2) Recuperar URL del media (Retrieve Media)
Haz una petición GET al Graph API para obtener la url temporal que contiene el archivo:
GET https://graph.facebook.com/v17.0/{MEDIA_ID}
Authorization: Bearer {ACCESS_TOKEN}
La respuesta incluirá un campo url que sirve para descargar el audio.
3) Descargar el audio (HTTP Request en n8n)
Haz un HTTP Request con la url devuelta y guarda la respuesta como archivo binario en n8n. En el nodo HTTP Request pon Response Format: File / Binary.
Nota de formato: WhatsApp suele enviar notas de voz en ogg/opus. Muchos STT aceptan ogg, pero si tu STT necesita wav conviene transcodificar con FFmpeg dentro de n8n o un servicio externo.
Ejemplo con cURL (descargar URL temporal)
curl -L "https://....temporary-url..." -o audio_in.ogg
4) Transcribir audio → Speech-to-Text (OpenAI / Whisper ejemplo)
En n8n puedes usar un nodo HTTP Request (POST) con multipart/form-data para enviar el archivo al endpoint de transcripción.
Ejemplo (cURL simplificado para OpenAI Whisper)
curl -X POST "https://api.openai.com/v1/audio/transcriptions" \
-H "Authorization: Bearer {OPENAI_KEY}" \
-F "file=@audio_in.ogg" \
-F "model=whisper-1"
Respuesta esperada (JSON): { "text": "Transcripción aquí..." }
5) Generar respuesta con el LLM (ChatGPT / OpenAI)
Envía la transcripción como prompt al modelo. Puedes pedir que responda en español y con frases cortas (para que el TTS no genere una pista muy larga).
Prompt sugerido
El usuario dijo: "{{transcript}}"
Responde en español, tono amable, máximo 25 segundos de voz.
Ejemplo cURL (Chat Completions)
curl -X POST "https://api.openai.com/v1/chat/completions" \
-H "Authorization: Bearer {OPENAI_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "TRANSCRIPT_HERE"}],
"max_tokens": 200
}'
Guarda el texto resultante en reply_text.
6) Convertir el texto a voz (TTS)
Ejemplo con ElevenLabs (o usa OpenAI TTS si lo prefieres). El servicio devuelve audio (mp3/ogg).
Ejemplo (cURL ElevenLabs)
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}" \
-H "xi-api-key: {ELEVEN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"text": "Hola, gracias por tu mensaje. Estoy procesando lo que me dijiste..."
}' --output reply_audio.mp3
Si ElevenLabs devuelve mp3 y quieres oggs/opus para imitar «voice note» de WhatsApp, transcodifica con FFmpeg:
ffmpeg -i reply_audio.mp3 -c:a libopus -b:a 24k -vbr on reply_audio.opus
7) Subir audio a WhatsApp (Media Upload) y enviar mensaje
Sube el archivo binario al endpoint de media del número de WhatsApp (PHONE_NUMBER_ID):
Upload media (cURL)
curl -X POST "https://graph.facebook.com/v17.0/{PHONE_NUMBER_ID}/media" \
-H "Authorization: Bearer {ACCESS_TOKEN}" \
-F "file=@reply_audio.mp3" \
-F "messaging_product=whatsapp"
Respuesta ejemplo: { "id": "MEDIA_ID_WH" }
Enviar audio message (cURL)
curl -X POST "https://graph.facebook.com/v17.0/{PHONE_NUMBER_ID}/messages" \
-H "Authorization: Bearer {ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "54911XXXXXXX",
"type": "audio",
"audio": { "id": "MEDIA_ID_WH" }
}'
8) Manejo de errores y consideraciones
- Valida el webhook (challenge) de Meta para asegurar que los eventos vienen de WhatsApp.
- Limita la duración de audio que aceptarás (ej. 60 s) para controlar costos y latencia.
- Si STT falla por formato, transcodifica con FFmpeg (ogg → wav 16k).
- Contempla enviar un mensaje de texto cuando haya error en transcripción o TTS.
- Atención a costos: transcribir y generar voz tiene coste por minuto/requests.
9) Ejemplo condensado: Orden de nodos en n8n
- Webhook (POST)
- Function/Set (extraer media_id y from)
- HTTP Request (GET https://graph.facebook.com/v17.0/{MEDIA_ID}) → obtener url
- HTTP Request (GET url) → guardar binario audio_in
- HTTP Request (POST STT) → transcript
- OpenAI/HTTP Request → reply_text
- HTTP Request (POST TTS) → binary audio_out
- HTTP Request (POST upload media a /{PHONE_NUMBER_ID}/media) → media_id_wh
- HTTP Request (POST /{PHONE_NUMBER_ID}/messages) enviar tipo audio
- Respuesta 200 al webhook
10) Código / snippets útiles
Function node (n8n) - Extraer media_id y from
// Usa esto en un nodo Function para normalizar el payload
const entry = $json["entry"]?.[0];
const msg = entry?.changes?.[0]?.value?.messages?.[0] || {};
return [{
json: {
media_id: msg.audio?.id || null,
from: msg.from || null,
raw: msg
}
}];
Set node: prepara variables
{
"media_id": "={{$json.media_id}}",
"from": "={{$json.from}}"
}
11) Reemplaza estos placeholders
{ACCESS_TOKEN}→ tu token de Meta (WhatsApp Cloud).{PHONE_NUMBER_ID}→ id del número de WhatsApp Cloud.{OPENAI_KEY}→ clave de OpenAI (si usas Whisper/ChatGPT).{ELEVEN_KEY}y{VOICE_ID}→ si usas ElevenLabs.
12) ¿Quieres que te lo deje listo para pegar en n8n?
Puedo generarte el JSON exportable del workflow (con nodos y placeholders para tus keys) para que lo importes en n8n. Si quieres eso, dime “Genera JSON n8n” y te lo doy en el siguiente mensaje.
