Documentación técnica

Integración WebSocket

Información para conectar clientes externos al WebSocket/WebRTC de RA AGENTE, validar conectividad desde Linux y probar endpoints auxiliares ASR/TTS/IA.

Endpoint WebSocket

Producción wss://agente.hablaip.com/ws/webrtc?access_token=TOKEN_WEBSOCKET

Este endpoint recibe señalización WebRTC por WebSocket. El audio viaja por WebRTC/RTP.

Health check

Versión del servicio https://agente.hablaip.com/api/version

Úsalo para validar que IIS, HTTPS y la aplicación estén activos.

Prueba rápida desde Linux

curl -i https://agente.hablaip.com/api/version

npm install -g wscat
wscat -c wss://agente.hablaip.com/ws/webrtc

Si wscat conecta, el upgrade WebSocket está operativo en IIS/proxy/firewall.

Mensaje WebRTC esperado

El cliente debe enviar una oferta WebRTC con esta estructura:

{
  "type": "offer",
  "sdp": "v=0..."
}

El servidor responde:

{
  "type": "answer",
  "sdp": "v=0..."
}

ICE Candidate

{
  "type": "candidate",
  "candidate": {
    "candidate": "candidate:...",
    "sdpMid": "0",
    "sdpMLineIndex": 0
  }
}

Resultado ASR

{
  "type": "asr_result",
  "result": "{...respuesta ASR...}"
}

El cliente debe extraer el texto reconocido desde la respuesta ASR.

Cómo recibir ASR por WebSocket

Después de completar la negociación WebRTC, el cliente envía audio por el track de micrófono. El servidor procesa el audio, llama al servicio ASR y devuelve el resultado por el mismo WebSocket.

ws.onmessage = async event => {
  const msg = JSON.parse(event.data);

  if (msg.type === "ready") {
    console.log("WebSocket listo", msg.sessionId);
  }

  if (msg.type === "answer") {
    await pc.setRemoteDescription({ type: "answer", sdp: msg.sdp });
  }

  if (msg.type === "candidate") {
    await pc.addIceCandidate(msg.candidate);
  }

  if (msg.type === "asr_result") {
    const text = getAsrText(msg.result);
    if (text) {
      console.log("Texto reconocido:", text);
      // Aquí puedes enviarlo a tu bot, PBX, CRM o flujo propio.
    }
  }
};

Función sugerida para extraer texto desde distintas respuestas ASR:

function getAsrText(result) {
  try {
    const data = typeof result === "string" ? JSON.parse(result) : result;
    return findText(data);
  } catch {
    return String(result || "").trim();
  }
}

function findText(value) {
  if (!value) return "";
  if (typeof value === "string") return value.trim();
  if (Array.isArray(value)) return value.map(findText).find(Boolean) || "";
  if (typeof value !== "object") return "";

  for (const key of ["text", "transcript", "transcription", "result", "respuesta"]) {
    const text = findText(value[key]);
    if (text) return text;
  }

  for (const item of Object.values(value)) {
    const text = findText(item);
    if (text) return text;
  }

  return "";
}

Cómo usar TTS

El WebSocket actual entrega resultados ASR y señalización WebRTC. Para convertir texto a voz, usa el endpoint HTTP TTS. La respuesta es un archivo de audio reproducible por el cliente.

async function playTts(text) {
  const form = new FormData();
  form.append("language", "es");
  form.append("type", "N");
  form.append("text", text);

  const response = await fetch("https://agente.hablaip.com/api/testing/tts", {
    method: "POST",
    body: form
  });

  if (!response.ok) {
    throw new Error(`TTS HTTP ${response.status}: ${await response.text()}`);
  }

  const audioBlob = await response.blob();
  const audioUrl = URL.createObjectURL(audioBlob);
  const audio = new Audio(audioUrl);
  audio.onended = () => URL.revokeObjectURL(audioUrl);
  await audio.play();
}

Ejemplo integrando ASR recibido por WebSocket con TTS:

if (msg.type === "asr_result") {
  const text = getAsrText(msg.result);
  if (text) {
    await playTts(`Recibí: ${text}`);
  }
}

Ejemplo JavaScript mínimo

const token = "TOKEN_WEBSOCKET";
const ws = new WebSocket(`wss://agente.hablaip.com/ws/webrtc?access_token=${encodeURIComponent(token)}`);
const pc = new RTCPeerConnection({
  iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
});

ws.onmessage = async event => {
  const msg = JSON.parse(event.data);

  if (msg.type === "answer") {
    await pc.setRemoteDescription({ type: "answer", sdp: msg.sdp });
  }

  if (msg.type === "candidate") {
    await pc.addIceCandidate(msg.candidate);
  }

  if (msg.type === "asr_result") {
    const text = getAsrText(msg.result);
    console.log("ASR", text || msg.result);
  }
};

pc.onicecandidate = event => {
  if (event.candidate) {
    ws.send(JSON.stringify({ type: "candidate", candidate: event.candidate }));
  }
};

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
stream.getTracks().forEach(track => pc.addTrack(track, stream));

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
ws.onopen = () => ws.send(JSON.stringify({ type: "offer", sdp: offer.sdp }));

Prueba ASR HTTP

curl -i -X POST https://agente.hablaip.com/api/testing/asr \
  -F "language=es" \
  -F "audio=@audio.wav;type=audio/wav"

Prueba TTS HTTP

curl -i -X POST https://agente.hablaip.com/api/testing/tts \
  -F "language=es" \
  -F "type=N" \
  -F "text=Hola, esto es una prueba"

Checklist servidor

  • HTTPS válido para agente.hablaip.com.
  • Puerto 443 abierto desde Internet.
  • WebSocket Protocol habilitado en IIS.
  • Application Pool iniciado.
  • Firewall/proxy permite Upgrade: websocket.
  • Logs en P:\Publicacion\AGENTE.HABLAIP.COM.LOG.