Genesys AudioHook es 8 kHz µ-law, y no hay dónde apoyarse
El protocolo AudioHook de Genesys Cloud fija su frecuencia de muestreo en el sistema de tipos: MediaRate es el literal 8000, y 16000 no aparece en ninguna parte de la especificación. AudioHook Monitor es un tap unidireccional cuya salida del servidor se descarta explícitamente; Audio Connector puede reproducir audio de vuelta, pero es una bifurcación de bot dentro del IVR que pausa el flujo y nunca llega a un agente. Una lectura especificación por especificación de lo que un tercero puede y no puede hacer en esa ruta de medios, con las cuatro cosas que no pudimos confirmar nombradas como no confirmadas.
Cada afirmación sobre la especificación que aparece abajo está citada de la propia documentación publicada de Genesys y enlazada. Donde no pudimos confirmar algo, aparece listado como no confirmado en lugar de rellenado — hay una sección para eso cerca del final. Si algo de esto está mal o cambia, dínoslo y lo corregiremos con fecha.
Los contact centers son donde la IA de voz se encuentra con los ingresos reales, y Genesys Cloud es uno de los más grandes. Así que la pregunta que importa para cualquiera que venda procesamiento de audio es estrecha y respondible: ¿qué aspecto tiene la ruta de medios, y hay en ella un lugar donde un tercero pueda apoyarse?
La respuesta de Genesys es inusualmente legible, porque publican el protocolo en lugar de describirlo. Aquí está la cuestión entera de la frecuencia de muestreo, tal y como aparece en sus definiciones de tipos:
type MediaFormat = 'PCMU';
type MediaRate = 8000;
No es un valor por defecto. No es una recomendación. Es un tipo literal. La referencia del protocolo lo reafirma en prosa — «Frecuencia de muestreo del formato de medios en hercios. El cliente de Genesys Cloud actualmente solo soporta 8000Hz» — y la cadena 16000 no aparece en ningún lugar de la especificación de AudioHook.
Esa es la cuña de la que trata todo este sitio, enunciada por la propia plataforma. Todo tercero que integre audio en Genesys Cloud a través del protocolo documentado recibe G.711 µ-law de banda estrecha, y prácticamente todos los modelos de mejora de voz (speech enhancement) del mercado están entrenados en banda ancha.
El transporte, brevemente
AudioHook invierte los roles que podrías esperar. Genesys es el cliente WebSocket; tu servicio es el servidor.
«El protocolo AudioHook usa WebSockets sobre TLS como transporte y está diseñado para que sea fácil implementar servidores que lo acepten.» — introducción
En concreto, de la página de seguridad y del recorrido de sesión:
| Propiedad | Valor |
|---|---|
| Puerto | 443, y solo 443 |
| TLS | 1.2 y 1.3; los certificados deben estar firmados por una CA pública (nada de autofirmados) |
| Framing | JSON en frames de texto, audio crudo en frames binarios |
| Tamaño máximo de mensaje | 64,000 bytes, texto y binario por igual |
| Timeouts de apertura / ping / cierre | 5,000 ms / 5,000 ms / 10,000 ms |
| Intervalo de ping de aplicación | cada 5 segundos por conexión |
| Autenticación | cabecera X-API-KEY, más firma opcional de peticiones con HMAC-SHA256 y nonce obligatorio |
| Reintentos | hasta 5, backoff exponencial |
Dos detalles que vale la pena destacar porque muerden a los implementadores.
El ping no es el ping de WebSocket. Son mensajes JSON ping/pong a nivel de aplicación — «una característica del protocolo distinta de los mensajes ping/pong de WebSocket (que no se usan)» — y un pong no solicitado es un error de protocolo. Tienes cinco segundos para responder, cada cinco segundos, o Genesys puede dar la conexión por perdida y restablecerla.
No hay subprotocolo WebSocket. Lo buscamos específicamente. El handshake documentado lleva las cabeceras Audiohook-Organization-Id, Audiohook-Correlation-Id, Audiohook-Session-Id y X-API-KEY, y ningún Sec-WebSocket-Protocol en absoluto; la cadena no aparece en ninguna página de la especificación de AudioHook. Si planeabas enrutar por subprotocolo, enruta por path en su lugar.
La negociación de medios, y qué son realmente los dos canales
El mensaje open lleva una oferta y tu respuesta opened elige de ella, al estilo SDP. La regla es estricta:
«El servidor debe elegir exactamente una de las entradas ofrecidas y no debe modificar un formato de medios ofrecido (incluidos los canales y su orden). Es similar al intercambio oferta-respuesta de una negociación de medios SIP/SDP, solo que más simple.» — recorrido de sesión
Una oferta típica son tres entradas, todas PCMU a 8000 Hz, que difieren solo en los canales: ["external", "internal"], ["external"], ["internal"].
Los nombres de los canales son la parte en la que la gente se equivoca, y no son «llamante» y «agente». AudioHook sigue a un participante, no a una pata:
«Actualmente se soportan dos valores:
external, que representa lo que habla la parte representada por el participante, einternal, que representa lo que oye.» — referencia del protocolo
Así que internal es todo lo que ese participante oye — que pueden ser locuciones del IVR, música de espera del ACD o, en una conferencia, una mezcla. Genesys lo dice explícitamente: «el audio del canal 'internal' en nuestro AudioHook representa una mezcla del audio de ambos agentes». Si estás construyendo cualquier cosa que asuma una voz por canal, esa suposición falla en una transferencia atendida (warm transfer). En una respuesta estéreo, la izquierda es el índice 0 y la derecha es el índice 1.
Tamaños de frame: no los hay
Esta es la fuente de bug más probable en una primera implementación, y la especificación es contundente al respecto.
«El número de muestras por frame es variable y lo decide el cliente... El servidor no debe hacer ninguna suposición sobre los tamaños de frame de audio y debe mantener una línea de tiempo del stream de audio contando las muestras.» — recorrido de sesión
El único número concreto que se da es ilustrativo: un frame de 100 ms de PCMU de dos canales a 8000 Hz son 1600 bytes, sin cabecera y entrelazado. Tu presupuesto de framing es el techo de mensaje de 64,000 bytes y los límites de tasa — 10 mensajes binarios por segundo de media con una ráfaga de 25, lo mismo para texto.
Y el stream no está cadenciado como una llamada telefónica. Genesys acumula:
«El cliente mantiene un buffer de historial de al menos 20 segundos de audio... enviará el audio acumulado al servidor más rápido que en tiempo real y luego continuará con el stream en tiempo real. La velocidad a la que el cliente 'se pone al día' no está definida.»
Así que una sesión se abre con una ráfaga de historial a una velocidad sin especificar, y luego se asienta en tiempo real. Cualquier cosa que construyas con un tamaño de bloque fijo — que es todo modelo de mejora en streaming, el nuestro incluido — necesita su propio buffer de re-framing delante, y cualquier cosa que mida el factor de tiempo real a partir de la llegada según el reloj de pared leerá un sinsentido durante los primeros segundos.
Cuando el cliente no puede seguir el ritmo te lo dice, con un mensaje discarded que lleva las duraciones start y discarded y el invariante position = start + discarded. Eso es un anuncio de hueco, no un comando de control: «siempre que haya una discontinuidad en el stream de audio debida a una pérdida inesperada de audio». La pausa y la reanudación explícitas no producen uno. Si estás contando muestras para mantener una línea de tiempo — y la especificación te dice que lo hagas — discarded es como te enteras de que tu línea de tiempo acaba de moverse.
La pregunta que lo decide todo: ¿puedes devolver audio?
Depende por completo de cuál de las cuatro características de AudioHook estés implementando, y las respuestas no se parecen entre sí.
| Característica | Audio hacia tu servidor | Audio de vuelta a la llamada | Lo que puedes devolver |
|---|---|---|---|
| AudioHook Monitor | Sí, external y/o internal | No | Nada en banda |
| Audio Connector | Sí, solo external | Sí — se reproduce al llamante | Audio, como locuciones de bot |
| Transcription Connector | Sí | No | Eventos transcript |
| Bot Transcription Connector | Sí (PCMU o L16) | No | Eventos transcript y de habla |
AudioHook Monitor es un tap y lo dice. La página de características no deja espacio a la interpretación:
«aquí el cliente transmitirá el audio de la conversación al servidor pero no puede enviarse de vuelta al cliente ningún dato en banda. Los datos devueltos por el servidor serán ignorados y descartados en silencio.»
Fíjate en en silencio. Ni un error, ni un aviso — tu audio procesado desaparece y la sesión parece sana. La introducción enmarca el protocolo entero de la misma manera: «Piensa en esto como 'taps' sobre los streams de audio hacia y desde las partes de los participantes.»
Audio Connector es genuinamente bidireccional, y este es el que parece, a primera vista, la apertura:
«Esta característica soporta streaming de audio bidireccional... Cualquier dato de audio enviado al cliente se reproducirá al llamante. Solo el canal de audio
externalse envía del cliente al servidor.» — características
Tiene la maquinaria que esperarías para eso: mensajes de cliente playback-started y playback-completed, un evento de servidor barge_in, un mensaje dtmf. El audio de servidor a cliente está limitado a «no más de 64,000 bytes por mensaje» y cadenciado — «el servidor no debería enviar audio más a menudo que cada 200ms».
Hay una contradicción documentada que vale la pena conocer antes de gastarle un día. La tabla de errores de la misma referencia del protocolo todavía dice lo contrario:
«
415Unsupported Media Type — El servidor envió un mensaje binario al cliente... enviar audio del servidor al cliente no está soportado.»
Nuestra lectura es que el 415 es anterior a Audio Connector y aplica a las sesiones de Monitor y de Transcription Connector, donde el binario desde el servidor es efectivamente ilegal; el changelog muestra el audio bidireccional, el DTMF, la reproducción y el barge-in llegando en una actualización posterior. Pero la especificación contiene hoy ambas afirmaciones, y si estás construyendo contra ella deberías esperar descubrir empíricamente cuál aplica a tu tipo de sesión.
Por qué Audio Connector sigue sin ser un punto de inserción
Aquí es donde la arquitectura, más que el protocolo, cierra la puerta. Audio Connector es un turno de bot, no un filtro en línea, y tres de sus propiedades son individualmente descalificantes para cualquiera que intente limpiar audio antes del bot de otro:
«La acción Call Audio Connector en Architect bifurca el stream de voz, lo envía a la URL configurada, y luego pausa la ejecución del flujo en ese punto, hasta que el stream bidireccional termina... La sesión de streaming bidireccional está activa solo en el canal del IVR. No se transfiere a un agente.» — visión general de Audio Connector
- El audio que envías va al llamante, no al bot. Se te está pidiendo ser la voz al otro lado. No existe la dirección «devuelve el audio limpio del llamante y deja que lo oiga el reconocedor de voz de la plataforma», porque la dirección que existe apunta al humano.
- Es una bifurcación con un flujo bloqueante. La ejecución se detiene en la acción y se reanuda cuando tu sesión termina. Eso es un turno de diálogo, no una etapa de pipeline.
- Nunca llega a un agente. Solo IVR.
Más las restricciones menores, todas documentadas en la misma página: un solo stream bidireccional, canal external únicamente, 300 llamadas concurrentes de Audio Connector y un techo de 900 segundos por llamada, y sin soporte bajo BYOC Premises.
Así que la conclusión honesta, comprobada superficie por superficie: Genesys Cloud documenta la salida de audio, el diálogo de audio en la pata del IVR, y la devolución de metadatos. No documenta ninguna manera de que un tercero reciba audio, lo procese, y el audio procesado sea lo que oyen los propios consumidores aguas abajo de la plataforma. Comprobamos Monitor, Audio Connector, Transcription Connector, Bot Transcription Connector, Genesys Agent Assist (una característica de presentación de conocimiento sin ruta de audio alguna), Genesys Bot Connector (texto e intenciones, solo flujos de mensajes) y Bring Your Own Interactions (ingesta a posteriori, no medios en vivo).
Dónde puedes apoyarte, y es exactamente un lugar
Hay un punto de inserción real, y no es el que la gente busca.
Si tú eres el reconocedor de voz, puedes limpiar el audio antes de tu propio reconocedor. El Bot Transcription Connector existe precisamente para permitir que un tercero sea el motor de STT — «permite transmitir audio al servidor basado en AudioHook que servirá como motor de STT» — y el propio centro de ayuda de Genesys lo describe como la manera de «integrar motores de ASR de terceros usando el protocolo AudioHook de Genesys». Esa ruta recibe PCMU, y es la única que además ofrece L16, y devuelve eventos transcript y de inicio de habla en lugar de audio.
Lo cual reubica la pregunta en lugar de responderla. Dentro de esa frontera eres dueño de la cadena entera: 8 kHz µ-law de entrada, tu procesamiento, tu reconocedor, transcripción de salida. Nada en la plataforma te impide poner un filtro ahí. Lo que te lo impide es que, según nuestras propias mediciones, la mayor parte de lo que podrías poner ahí es actualmente una mala idea: en nuestras siete condiciones de telefonía ningún motor que probamos produjo una mejora significativa sobre el audio sin procesar, y varios lo degradaron en cinco a diez puntos de tasa de error de palabras (WER). El lugar donde apoyarse existe. Lo que ha faltado es algo con lo que valga la pena apoyarse ahí, y esa es la razón entera de que esta empresa exista.
La consecuencia de segundo orden vale la pena enunciarla para cualquiera que esté haciendo selección de plataforma. En AudioHook, la decisión sobre la calidad de audio de tu canal de mayor volumen se toma aguas arriba de ti y tú no puedes cambiarla. Recibes 8 kHz µ-law y lo que la pata del operador le haya hecho, y la única palanca que tienes es lo que haces después de que llegue.
Lo que no pudimos confirmar
Nombrado explícitamente, porque un post orientado a desarrolladores que rellena huecos en silencio no vale nada.
- La frecuencia de muestreo de la transcripción propia de Genesys. No pudimos encontrar ninguna declaración de Genesys sobre a qué frecuencia corre su propio speech-to-text, y ninguna comparación de 8 kHz contra 16 kHz en ninguna parte. Sus motores están respaldados por proveedores (Google, Microsoft Azure, AWS Transcribe, un motor nativo de Genesys, Deepgram) y no se publica frecuencia para ninguno de ellos. Los códecs de troncal pueden incluir G.722 y Opus, así que la pata del operador no es necesariamente banda estrecha — pero lo que llega al transcriptor no está documentado. La cifra de 8000 Hz de este post es solo la ruta de terceros de AudioHook. No la extiendas al pipeline propio de Genesys sobre nuestra palabra.
- Alguna manera soportada de insertar un SBC o un servidor de medios en una ruta SIP de BYOC para modificar el audio. BYOC Cloud te permite definir troncales SIP hacia operadores de terceros, y los códecs de troncal son configurables. No encontramos ningún documento de Genesys que avale, describa o prohíba poner un elemento de procesamiento en esa ruta. La ausencia de documentación no es permiso y no es prohibición.
- Un número máximo de conexiones concurrentes de AudioHook Monitor. Solo se publican recuentos de integraciones y de monitores — cinco integraciones de AudioHook Monitor, hasta 20 instalaciones de integración, hasta 500 monitores configurados, diez integraciones de Transcription Connector. Las 300 llamadas concurrentes de Audio Connector son la única cifra de concurrencia que encontramos.
- El formato de cable del audio de servidor a cliente en Audio Connector. La especificación da la cadencia (no más a menudo que cada 200 ms) y el techo de tamaño (64,000 bytes) pero nunca reitera el formato. Presumiblemente es el negociado. No lo dice.
- «AudioHook Media Service» no parece ser un nombre de producto de Genesys. Buscamos en el sitemap del centro de desarrolladores y en el índice completo de artículos del centro de ayuda y no encontramos nada. Si has visto el término, no salió de la documentación de Genesys.
También señalamos que Genesys publica una implementación de servidor de referencia en TypeScript con una herramienta de cliente y una suite de tests, y un servidor de referencia de Audio Connector aparte cuyo código fija MediaFormat a 'PCMU' | 'L16', MediaRate a 8000 y el mensaje binario máximo a 64000 — lo que constituye una segunda confirmación independiente de los números de arriba, en código y no en prosa.
Si estás implementando esto
- Cuenta muestras, no cuentes frames. La especificación lo exige y la ráfaga de puesta al día castiga todo lo que no lo haga.
- Acumula en el tamaño de bloque de tu modelo, y nunca tomes el timing de llegada como proxy del timing del audio durante los primeros veinte segundos.
- Trata
discardedcomo un evento de línea de tiempo, no como un error que registrar y del que pasar página. Tu contador de muestras queda mal después si no lo haces. - Responde al
pingen menos de cinco segundos, siempre, desde una ruta que la inferencia no pueda bloquear. Si tu modelo y tu plano de control comparten un event loop, un bloqueo lento se come tu conexión. - Decide qué característica eres antes de diseñar nada. Monitor y Audio Connector parecen el mismo protocolo y son arquitecturas opuestas, y la tabla de errores no te impedirá construir la equivocada.
- Toma nota de la frontera PCI. AudioHook se adhiere al cumplimiento de PCI DSS cuando la pausa segura corre durante los flujos seguros, y no puedes usarlo para transmitir audio durante un flujo seguro. Lo que sea que construyas tiene un agujero por diseño, y ese agujero es deliberado.
El post complementario que cubre Amazon Connect, Twilio, NICE CXone y Avaya lee la misma pregunta contra las otras cuatro plataformas — y resulta que una de ellas documenta algo que Genesys no documenta.