Files
n8n/Calendario Voz IA/BLUEPRINT.md
T

15 KiB
Raw Blame History

Voz → Calendario Nextcloud — Blueprint Completo

Versión: 1.0
Fecha: 2026-07-03
Autor: Álvaro
n8n: https://n8n.crewinghunters.com


Visión General

Grabas un audio en el teléfono → se lo mandas al bot de Telegram → la IA local transcribe y entiende el evento → aparece en tu calendario de Nextcloud → te recuerda 30 minutos antes por Telegram.

📱 Audio (teléfono)
    │
    ▼ Telegram
┌─────────────────────────────────────────────────┐
│  n8n  (Raspberry Pi 4 — Colombia)               │
│                                                 │
│  1. Recibe audio de Telegram                    │
│  2. Descarga el archivo .ogg/.mp3               │
│  3. Llama a Whisper API (tu PC via Tailscale)   │
│  4. Llama a Ollama (tu PC via Tailscale)        │
│  5. Crea evento en Nextcloud Calendar (CalDAV)  │
│  6. Confirma por Telegram                       │
│  7. Programa recordatorio 30min antes           │
└─────────────────────────────────────────────────┘
    │
    ▼ Tailscale VPN (túnel privado gratis)
┌─────────────────────────────────────────────────┐
│  Tu PC (Windows)                                │
│  ├── Ollama → AsistentePersonal / qwen2.5:14b   │
│  └── Whisper API → faster-whisper (Python)      │
└─────────────────────────────────────────────────┘

Stack Tecnológico

Componente Herramienta Dónde corre
Automatización n8n RPi4 Colombia
Bot mensajería Telegram Bot Cloud (Telegram)
Transcripción voz faster-whisper Tu PC (Windows)
LLM extracción evento Ollama / qwen2.5:14b Tu PC (Windows)
Calendario Nextcloud CalDAV RPi4 Colombia
Túnel privado Tailscale PC + RPi4
API transcripción FastAPI (Python) Tu PC (Windows)

PASO 1 — Tailscale (conectar PC con RPi4)

Tailscale crea una red privada entre tus dispositivos. Una vez instalado, tu PC tendrá una IP tipo 100.x.x.x accesible desde el RPi4 sin abrir puertos ni router.

En tu PC (Windows)

  1. Descarga e instala Tailscale: https://tailscale.com/download/windows
  2. Inicia sesión con Google o email
  3. Anota tu IP Tailscale: aparece en el icono de la bandeja del sistema
    • Ejemplo: 100.64.1.10

En el RPi4 (via SSH desde Colombia)

# Conectar al RPi4
ssh usuario@n8n.crewinghunters.com

# Instalar Tailscale en RPi4
curl -fsSL https://tailscale.com/install.sh | sh

# Iniciar y autenticar (con la MISMA cuenta que en el PC)
sudo tailscale up

# Verificar que ve tu PC
tailscale ping 100.64.1.10   # ← IP de tu PC Tailscale

Si el ping responde, están conectados. El RPi4 puede hablar con tu PC.


PASO 2 — Whisper API en tu PC

Instalamos faster-whisper y levantamos una API HTTP que n8n puede llamar.

Instalar faster-whisper

# En tu PC (PowerShell)
pip install faster-whisper fastapi uvicorn python-multipart

Crear el servidor API

Guarda este archivo en: C:\whisper-api\server.py

from fastapi import FastAPI, UploadFile, File
from faster_whisper import WhisperModel
import tempfile, os

app = FastAPI()

# Carga el modelo una vez al iniciar (medium es bueno para español)
# Opciones: "tiny", "base", "small", "medium", "large-v3"
model = WhisperModel("medium", device="cpu", compute_type="int8")

@app.post("/transcribe")
async def transcribe(file: UploadFile = File(...)):
    # Guardar audio temporalmente
    suffix = os.path.splitext(file.filename)[1] or ".ogg"
    with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
        tmp.write(await file.read())
        tmp_path = tmp.name
    
    # Transcribir
    segments, info = model.transcribe(tmp_path, language="es")
    text = " ".join([seg.text for seg in segments]).strip()
    
    os.unlink(tmp_path)
    return {"text": text, "language": info.language}

@app.get("/health")
def health():
    return {"status": "ok"}

Script para iniciar la API (guarda como C:\whisper-api\start.bat)

@echo off
cd C:\whisper-api
uvicorn server:app --host 0.0.0.0 --port 8765

Iniciar automáticamente con Windows

  1. Presiona Win + R → escribe shell:startup
  2. Crea un acceso directo a start.bat en esa carpeta
  3. La API estará disponible en: http://100.64.1.10:8765 (via Tailscale)

Verificar que funciona (desde RPi4)

# Desde el RPi4 via SSH
curl http://100.64.1.10:8765/health
# Debe responder: {"status":"ok"}

PASO 3 — Exponer Ollama via Tailscale

Por defecto Ollama solo escucha en localhost. Hay que permitir que escuche en todas las interfaces.

En tu PC (PowerShell como Administrador)

# Agregar variable de entorno para Ollama
[System.Environment]::SetEnvironmentVariable("OLLAMA_HOST", "0.0.0.0:11434", "Machine")

# Reiniciar Ollama (busca en la bandeja del sistema → clic derecho → Quit, luego reabre)

Verificar desde RPi4

curl http://100.64.1.10:11434/api/tags
# Debe listar tus modelos

PASO 4 — Bot de Telegram

Crear el bot

  1. Abre Telegram → busca @BotFather
  2. Escribe /newbot
  3. Nombre del bot: Mi Calendario Personal (o el que quieras)
  4. Username: mi_calendario_alvaro_bot (debe terminar en _bot)
  5. BotFather te da un token — guárdalo: 7123456789:AAF...

Obtener tu Chat ID

  1. Escribe cualquier mensaje a tu nuevo bot
  2. Abre en el navegador (reemplaza TOKEN):
    https://api.telegram.org/botTOKEN/getUpdates
    
  3. Busca "id" dentro de "chat" — ese número es tu Chat ID
    • Ejemplo: 123456789

PASO 5 — Nextcloud Calendar (CalDAV)

n8n se conecta al calendario de Nextcloud via CalDAV.

Obtener la URL CalDAV

En Nextcloud → Calendario → ⚙️ (engranaje junto al calendario) → "Copiar enlace privado"

La URL tiene esta forma:

https://tu-nextcloud.com/remote.php/dav/calendars/USUARIO/personal/

Credenciales

  • Usuario: tu usuario de Nextcloud
  • Contraseña: genera una contraseña de aplicación en Nextcloud: Configuración → Seguridad → Dispositivos y sesiones → "Crear nueva contraseña de aplicación"
    • Nombre: n8n-calendario

PASO 6 — Organizar Carpetas en n8n

Antes de crear el workflow, organiza las carpetas:

  1. Abre https://n8n.crewinghunters.com
  2. En el panel izquierdo → "Workflows" → "Add folder"
  3. Crea estas carpetas:
📁 Prisa Yachts          ← mueve el bot de WhatsApp aquí
📁 Personal - Productividad
📁 AIS Navigator
📁 Pruebas / Sandbox
  1. El nuevo workflow irá en 📁 Personal - Productividad

PASO 7 — Workflow n8n Completo

Nombre del workflow: 🎙️ Voz → Calendario Nextcloud Carpeta: Personal - Productividad

Nodos del workflow (en orden):

[Telegram Trigger]
      │
      ▼
[IF: ¿es audio?]
      │ sí
      ▼
[HTTP: Descargar audio de Telegram]
      │
      ▼
[HTTP: Whisper API → transcripción]
      │
      ▼
[HTTP: Ollama → extraer evento]
      │
      ▼
[Code: parsear JSON respuesta Ollama]
      │
      ▼
[HTTP: Crear evento CalDAV en Nextcloud]
      │
      ▼
[Telegram: Confirmar al usuario]
      │
      ▼
[Wait: esperar hasta 30min antes del evento]
      │
      ▼
[Telegram: Enviar recordatorio]

Nodo 1 — Telegram Trigger

Tipo: Telegram Trigger
Credential: (crear nueva → Token del bot)
Updates: message

Nodo 2 — IF: ¿Es audio?

Tipo: IF
Condición: {{ $json.message.voice }} existe
           O {{ $json.message.audio }} existe

Nodo 3 — HTTP: Descargar audio de Telegram

Tipo: HTTP Request
Método: GET
URL: https://api.telegram.org/bot{{ $env.TELEGRAM_TOKEN }}/getFile
Parámetros:
  file_id: {{ $json.message.voice.file_id }}

Luego un segundo HTTP Request para descargar el archivo:

URL: https://api.telegram.org/file/bot{{ $env.TELEGRAM_TOKEN }}/{{ $json.result.file_path }}
Respuesta: archivo binario

Nodo 4 — HTTP: Whisper API (transcripción)

Tipo: HTTP Request
Método: POST
URL: http://100.64.1.10:8765/transcribe   ← IP Tailscale de tu PC
Body: form-data
  file: [archivo de audio del nodo anterior]

Resultado esperado:

{ "text": "Reunión con Juan el viernes a las diez de la mañana en el puerto" }

Nodo 5 — HTTP: Ollama (extraer evento)

Tipo: HTTP Request
Método: POST
URL: http://100.64.1.10:11434/api/generate
Body JSON:
{
  "model": "qwen2.5:14b",
  "stream": false,
  "prompt": "Extrae el evento de esta frase y devuelve SOLO JSON válido sin explicaciones:\n\nFrase: '{{ $json.text }}'\n\nFecha actual: {{ $now.format('YYYY-MM-DD') }}, {{ $now.format('dddd') }}\n\nDevuelve exactamente este formato:\n{\"titulo\": \"...\", \"fecha\": \"YYYY-MM-DD\", \"hora_inicio\": \"HH:MM\", \"hora_fin\": \"HH:MM\", \"lugar\": \"...\", \"descripcion\": \"...\"}\n\nSi no hay hora fin, suma 1 hora a la hora inicio. Si no hay lugar, pon vacío."
}

Nodo 6 — Code: Parsear respuesta Ollama

// Extraer el JSON de la respuesta de Ollama
const responseText = $input.item.json.response;

// Buscar el JSON dentro del texto (por si Ollama añade texto extra)
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
if (!jsonMatch) throw new Error("Ollama no devolvió JSON válido: " + responseText);

const evento = JSON.parse(jsonMatch[0]);

// Construir fechas iCal (formato: 20260704T100000)
const fechaInicio = evento.fecha.replace(/-/g, '') + 'T' + evento.hora_inicio.replace(':', '') + '00';
const fechaFin = evento.fecha.replace(/-/g, '') + 'T' + evento.hora_fin.replace(':', '') + '00';

// UID único para el evento
const uid = 'n8n-' + Date.now() + '@crewinghunters.com';

// Formato iCalendar (CalDAV)
const ical = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//n8n//Calendario Voz//ES
BEGIN:VEVENT
UID:${uid}
DTSTART:${fechaInicio}
DTEND:${fechaFin}
SUMMARY:${evento.titulo}
LOCATION:${evento.lugar || ''}
DESCRIPTION:${evento.descripcion || 'Creado por voz via n8n'}
END:VEVENT
END:VCALENDAR`;

return {
  json: {
    ...evento,
    ical,
    uid,
    fechaInicio,
    fechaFin,
    // Para el recordatorio: fecha ISO completa
    fechaRecordatorio: new Date(evento.fecha + 'T' + evento.hora_inicio + ':00').toISOString()
  }
};

Nodo 7 — HTTP: Crear evento en Nextcloud (CalDAV)

Tipo: HTTP Request
Método: PUT
URL: https://tu-nextcloud.com/remote.php/dav/calendars/USUARIO/personal/{{ $json.uid }}.ics
Autenticación: Basic Auth
  Usuario: tu_usuario_nextcloud
  Password: contraseña_de_aplicacion
Headers:
  Content-Type: text/calendar; charset=utf-8
Body: {{ $json.ical }}

Nodo 8 — Telegram: Confirmar

Tipo: Telegram
Operación: Send Message
Chat ID: {{ $env.TELEGRAM_CHAT_ID }}
Texto:
✅ *Evento creado en tu calendario*

📅 *{{ $json.titulo }}*
🗓 {{ $json.fecha }}
🕐 {{ $json.hora_inicio }}  {{ $json.hora_fin }}
📍 {{ $json.lugar || 'Sin ubicación' }}

_Te recordaré 30 minutos antes_ ⏰

Nodo 9 — Wait (hasta 30min antes del evento)

Tipo: Wait
Modo: Until specified time
Fecha/Hora: {{ $json.fechaRecordatorio }}
Offset: -30 minutos

Nodo 10 — Telegram: Recordatorio

Tipo: Telegram
Operación: Send Message
Chat ID: {{ $env.TELEGRAM_CHAT_ID }}
Texto:
⏰ *Recordatorio — en 30 minutos:*

📅 *{{ $json.titulo }}*
🕐 {{ $json.hora_inicio }}
📍 {{ $json.lugar || '' }}

PASO 8 — Variables de Entorno en n8n

En n8n → Settings → Variables → Agregar:

Variable Valor
TELEGRAM_TOKEN 7123456789:AAF... (token del bot)
TELEGRAM_CHAT_ID 123456789 (tu chat ID)
WHISPER_URL http://100.64.1.10:8765
OLLAMA_URL http://100.64.1.10:11434
NEXTCLOUD_URL https://tu-nextcloud.com
NEXTCLOUD_USER tu_usuario
NEXTCLOUD_PASS contraseña_de_aplicacion

PASO 9 — Prueba Completa

  1. Graba un audio en el teléfono diciendo:

    "Reunión con Federico el próximo martes a las tres de la tarde en el puerto de Miami"

  2. Envía el audio al bot de Telegram

  3. En ~10-15 segundos deberías recibir:

    ✅ Evento creado en tu calendario
    📅 Reunión con Federico
    🗓 2026-07-07
    🕐 15:00  16:00
    📍 Puerto de Miami
    
  4. Verifica en Nextcloud Calendar que el evento aparece

  5. Espera el recordatorio 30 min antes


Checklist de Instalación

En tu PC (Windows)

  • Instalar Tailscale → anotar IP (100.x.x.x)
  • pip install faster-whisper fastapi uvicorn python-multipart
  • Crear C:\whisper-api\server.py (código arriba)
  • Crear C:\whisper-api\start.bat
  • Agregar start.bat al inicio de Windows
  • Iniciar la API y verificar: curl http://localhost:8765/health
  • Configurar Ollama para escuchar en 0.0.0.0: variable OLLAMA_HOST

En el RPi4 (via SSH)

  • curl -fsSL https://tailscale.com/install.sh | sh
  • sudo tailscale up → autenticar con la misma cuenta
  • Verificar ping a PC: tailscale ping 100.x.x.x
  • Verificar Whisper: curl http://100.x.x.x:8765/health
  • Verificar Ollama: curl http://100.x.x.x:11434/api/tags

En Telegram

  • Crear bot con @BotFather → guardar token
  • Obtener tu Chat ID
  • Escribir un mensaje al bot para activarlo

En Nextcloud

  • Copiar URL CalDAV del calendario
  • Crear contraseña de aplicación para n8n

En n8n

  • Crear carpetas: Prisa Yachts / Personal / AIS Navigator / Sandbox
  • Crear variables de entorno (8 variables)
  • Crear workflow 🎙️ Voz → Calendario Nextcloud
  • Agregar los 10 nodos en orden
  • Activar el workflow
  • Prueba con audio real

Solución de Problemas

Problema Causa probable Solución
n8n no llega a Whisper Tailscale no conectado sudo tailscale up en RPi4
Whisper tarda mucho Modelo "medium" pesado en CPU Cambiar a "small" en server.py
Ollama no responde OLLAMA_HOST no configurado Reiniciar Ollama tras la variable
Evento en fecha incorrecta Ollama interpretó mal el día Ajustar el prompt con más contexto
CalDAV 401 Unauthorized Contraseña de app incorrecta Crear nueva contraseña en Nextcloud
Audio no se procesa Formato no soportado Telegram envía .ogg — faster-whisper lo soporta

Mejoras Futuras (Fase 2)

  • Cancelar eventos por voz: "Cancela la reunión del martes" → n8n borra el evento
  • Consultar agenda: "¿Qué tengo mañana?" → n8n lee el CalDAV y responde
  • Recordatorio personalizable: "Recuérdame 1 hora antes"
  • Múltiples calendarios: personal, trabajo, AIS Navigator
  • Texto además de voz: si escribes (no mandas audio), también funciona

Blueprint generado: 2026-07-03 | AR Electronics / Álvaro