
Compartir:
Javier studied Industrial Engineering back in Madrid where he's from. He is now one of our Solution Engineers, so if you get into trouble using our APIs he may be the one that gives you a hand. Out of work he loves playing football and travelling as much as he can.
Activar subtítulos en directo en Vonage Video con Symbl.ai
Tiempo de lectura: 8 minutos
En esta publicación del blog, me gustaría mostrarte cómo puedes agregar transcripción/subtitulado a tu aplicación de Vonage Video. Vamos a aprovechar SDK web de Symbl.ai para lograrlo. El audio se enviará desde el lado del cliente a Symbl.ai, por lo tanto, no se requieren cambios en el lado del servidor. Symbl.ai te permite añadir fácilmente inteligencia conversacional a tus aplicaciones de voz y video con su conjunto de APIs y herramientas para desarrolladores.
¿Por qué se necesitan subtítulos?
La accesibilidad fue uno de los principales requisitos cuando las comunicaciones se trasladaron a Internet durante la pandemia. ¿Tiene clientes con acentos diferentes a los que a veces le cuesta entender? ¿Quiere ver qué les preocupa a sus usuarios, qué quieren, con qué tienen dificultades? ¿O simplemente quiere almacenar la transcripción de una llamada para poder analizarla más tarde? Lo tenemos todo. Quédate. Si prefiere ver un vídeo de la aplicación terminadano dudes en verlo.
En esta entrada del blog, voy a mostrarte cómo añadir subtítulos en una llamada uno a uno. Echa un vistazo al repositorio GitHub para obtener el código fuente completo, que muestra ejemplos de gráficos de análisis de sentimiento. También le proporciona información y un resumen de su llamada, además de subtítulos.
Voy a construir con ReactJS, pero puedes usar vanilla JS o cualquier framework/biblioteca de tu elección.
Requisitos
Para ejecutar esta aplicación de ejemplo, necesitarás algunas cosas:
Asumiré que conoces los fundamentos de ReactJS.
Tienes una cuenta de Video API de Vonage. Si no, puedes inscribirte gratis aquí.
Account SymblAI. Si no tiene una, puede registrarse gratis aquí.
Arquitectura
El siguiente diagrama muestra lo que vamos a construir hoy. En aras de la simplicidad, esta entrada de blog va a cubrir la integración con Symbl.ai en el lado del cliente. Para una explicación más detallada de la arquitectura de la aplicación puedes consultar el archivo Léame de la aplicación.
El Client SDK de Vonage controla nuestra aplicación de video. Como puedes ver en el siguiente diagrama, el Client SDK se comunicará con el Symbl.ai SDK abriendo una conexión bidireccional a través de un WebSocket. El audio de los participantes llegará al SDK de Symbl.ai y nosotros recibiremos la transcripción del audio.
Para autenticar la sesión de Vonage y la conexión de Symbl.ai en el lado del cliente hemos creado una API en nuestro servidor Node.js para generar credenciales. Esta API se basará en el SDK de Vonage Node.js y la API de Symbl.ai.

Creación de nombres de usuario
Para una llamada uno a uno, el SDK de Symbl.ai va a abrir una conexión con la infraestructura de Symbl.ai donde dos usuarios enviarán audio. Una vez que recibimos la salida de la transcripción, necesitamos saber a qué usuario pertenecen los subtítulos. Por eso nuestra app tendrá el concepto de usuarios con nombre de usuario. De esta forma, cuando creemos el connectionConfig en el useSymblai hookpodemos informar a Symbl.ai quién está hablando y cuándo. La salida de Symbl.ai incluye el nombre del orador junto con la transcripción, por lo que podemos saber a quién pertenece la transcripción en todo momento.
Para empezar, he creado un contexto de preferencias para poder acceder al nombre de usuario y conversationId en cualquier parte de nuestra aplicación. El conversationId es un identificador único para una determinada conversación que tiene lugar dentro de la infraestructura de Symbl.ai. Puede tener uno o más usuarios. No es necesario habilitar el subtitulado, pero utilizaremos el conversationId para realizar llamadas a la API de Symbl.ai con el fin de obtener información sobre el análisis de opiniones y un resumen de la conversación. Cubriremos estos temas en la Sección adicional.
import { createContext } from 'react';
export const PreferencesContext = createContext();const [preferences, setPreferences] = useState({
userName: null,
conversationId: null,
});
const preferencesValue = useMemo(
() => ({ preferences, setPreferences }),
[preferences, setPreferences]
);
Ahora, sólo tenemos que envolver nuestra aplicación con la etiqueta ContextProvider para que podamos acceder a las preferencias en cualquier parte de nuestra aplicación.
<Router>
<PreferencesContext.Provider value={preferencesValue}>
<Switch>
<ProtectedRoute exact path="/room/:roomName" component={Wrapper} />
<Route path="/room/:roomName/:conversationId/end">
<EndCall />
</Route>
<Route path="/">
<WaitingRoom />
</Route>
</Switch>
</PreferencesContext.Provider>
</Router>Como puede ver en la estructura de nuestra aplicaciónpor defecto el usuario será redirigido al componente WaitingRoom componente. Allí, le pediremos al usuario que escriba su nombre de usuario y un nombre de sala. Puedes ver la implementación de la sala de espera aquí. La ruta Protected es un componente que comprobará si el usuario ha configurado un nombre de usuario y, en caso contrario, lo redirigirá a la sala de espera. Puede ver la implementación de esta ruta aquí. Esto es para evitar que un usuario se una a una sala sin haber elegido un nombre. Si el usuario ya ha elegido un nombre de usuario, le redirigiremos al componente Wrapper que contiene un Header y el componente principal. Si tienes curiosidad, puedes echar un vistazo a este componente aquí.
Este es el aspecto de la sala de espera:

Gancho UseSymblai
Vamos a hacer uso del SDK web de Symbl.ai para abstraernos de la complejidad de abrir una conexión WebSocket y canalizar el audio. En una aplicación React, es una buena práctica escribir un gancho React personalizado para hacer nuestra aplicación más reutilizable y el código más limpio. Puedes ver la implementación completa del custom hook aquípero voy a explicar cada paso en detalle.
Vamos a instalar e importar el SDK:
npm i @symblai/symbl-web-sdk
import symbl from '@symblai/symbl-web-sdk';
Vamos a crear un gancho personalizado que aceptará el editor de la sesión de Vonage Video, así como un indicador booleano que indica si el editor ha comenzado a enviar medios. El gancho personalizado devolverá nuestros subtítulos, los subtítulos de la otra parte y el nombre del orador.
//CODE WILL GO HERE
return {
captions,
myCaptions,
name,
};
}
let streamRef = useRef(null);
const { preferences } = useContext(PreferencesContext);
const [captions, setCaptions] = useState('');
const [myCaptions, setMyCaptions] = useState('');
const [name, setName] = useState(null);
const [symblToken, setSymblToken] = useState(null);
let { roomName } = useParams();Estamos creando algunas variables de estado para almacenar nuestros propios subtítulos, los subtítulos de la otra parte, el nombre de la persona que habla, y el token. También crearemos una referencia al streamObject devuelto por Symbl.ai una vez que establezcamos una conexión con ellos. Consumiremos el contexto que hemos creado previamente.
Vamos a crear un useEffect hook que sólo se ejecutará en la primera renderización. El objetivo de este hook es obtener las credenciales para la sesión de video y un token para la conexión Symbl.ai. Los campos getToken y getSymblToken se implementan aquí. Se comunicarán con una API en nuestro servidor que se encargará de la generación de credenciales. Obtendremos el roomName de los parámetros de la URL.
useEffect(() => {
getToken()
.then((response) => {
setSymblToken(response.data.accessToken);
symbl.init({
accessToken: response.data.accessToken,
});
})
.catch((e) => console.log(e));
}, []);Seguiremos adelante y definiremos otro useEffect hook que se ejecutará una vez hayamos publicado en la sesión e iniciado la conexión con Symbl.ai. Obtendremos un mediaStreamTrack del publicador una vez que hayamos publicado en la sesión. A continuación, aprovecharemos la Web Audio API para crear un MediaStreamSource que se utilizará como fuente en el connectionConfig para Symbl.ai.
Si no quieres obtener el mediaStream del editor de Vonage, y sólo obtener el audio del micrófono, puedes hacerlo no especificando ninguna fuente en el archivo connectionConfig. Por defecto, el SDK Web de Symbl.ai manejará el contexto de audio y los nodos de origen por su cuenta.
En nuestra aplicación, en aras de la simplicidad, estamos asignando id el valor de roomNameque es un identificador único utilizado por los clientes para conectarse a la conversación y enviar audio a Symbl.ai. En una aplicación del mundo real, es necesario asegurarse de que esta id es único y no se reutiliza de nuevo después de la conversación termina.
Puede ver que hay una userId cadena en el speaker del objeto connectionConfig. Si configuras allí una dirección de correo electrónico válida, recibirás un correo electrónico con algunos datos de la conversación. Si lo dejas en blanco, no te enviará un correo electrónico. Sin embargo, queremos configurar el nombre del orador para que sepamos de quién es el discurso cuando recibamos la salida de Symbl.ai. Como puedes ver, estamos escuchando la llamada de retorno onSpeechDetected callback:
useEffect(() => {
if (isPublishing && publisher) {
const audioTrack = publisher.getAudioSource();
const stream = new MediaStream();
stream.addTrack(audioTrack);
const AudioContext = window.AudioContext;
const context = new AudioContext();
const source = context.createMediaStreamSource(stream);
const id = roomName;
const connectionConfig = {
id,
insightTypes: ['action_item', 'question'],
source: source,
config: {
meetingTitle: 'My Test Meeting ' + id,
confidenceThreshold: 0.5, // Offset in minutes from UTC
encoding: 'LINEAR16',
languageCode: 'en-US',
speaker: {
// Optional, if not specified, will simply not send an email in the end.
userId: '', // Update with valid email
name: preferences.userName || uuidv4(),
},
handlers: {
/**
* This will return live speech-to-text transcription of the call.
*/
onSpeechDetected: (data) => {
if (data) {
if (data.user.name !== preferences.userName) {
setCaptions(data.punctuated.transcript);
setName(data.user.name);
} else {
setMyCaptions(data.punctuated.transcript);
}
}
},
},
};
const start = async () => {
try {
const stream = await symbl.createStream(connectionConfig);
streamRef.current = stream;
await stream.start();
conversationId.current = await stream.conversationId;
preferences.conversationId = conversationId.current;
} catch (e) {
console.log(e);
}
};
start();
}
}, [
isPublishing,
roomName,
preferences,
publisher,
]);Hemos definido una función asíncrona al final de nuestro hook que será llamada para crear una conexión con Symbl.ai. Esto es necesario porque el WebSocket se inicia en un estado de no procesamiento, por lo que necesitamos instruir a Symbl.ai cuando queremos iniciar la conexión.
En este punto, podemos utilizar nuestro gancho personalizado en el componente de nuestra elección. En esta aplicación, se utilizará en el componente Componente principal. Primero necesitamos importarlo:
import { useSymblai } from '../../hooks/useSymblai';Y luego podemos desestructurar los datos llamando al gancho personalizado, pasándole el editor y la variable isPublishing variable booleana:
const { captions, name, myCaptions} =
useSymblai({
publisher,
isPublishing,
});En este punto, puede simplemente mostrar los subtítulos en su interfaz de usuario o llevar a cabo cualquier lógica que desee. Puedes echar un vistazo a la implementación del componente principal de Video aquí. Para recapitular, captions son los subtítulos de la otra parte, myCaptions son tus propios subtítulos, y name es sólo el nombre de la otra persona.
Bono
Symbl.ai no solo te ofrece funciones de subtitulado, sino también análisis de sentimientos, extracción de insights, resumen de la llamada, análisis y mucho más. He creado una aplicación de ejemplo más completa con estas funciones.
Encontrará más información sobre las funciones de la aplicación en la referencia de la API:
El siguiente Video muestra el aspecto de la aplicación. Hay dos usuarios en la llamada, Javier y Binoy. Como puedes ver en la parte superior izquierda, hay un gráfico que te muestra la puntuación del análisis de sentimiento para el discurso de la otra parte (que va de -1 a 1, siendo 1 muy positivo y -1 muy negativo). En este caso, podemos ver que Binoy se mostró bastante positivo cuando le hablé de las fantásticas funciones que ofrece Symbl.ai.
En la parte inferior izquierda, puede ver algunos action_items que son recogidos por la API de Symbl.ai. Contiene el nombre del destinatario cuando está disponible. Así que en este caso, podemos ver algunas preguntas, como Binoy preguntando a Javier si Symbl.ai era fácil de integrar con nuestras Video APIs, y un elemento de acción que es Binoy que necesita "echarles un vistazo" (refiriéndose a Symbl.ai).
Cuando hagas clic en "finalizar la llamada", la aplicación te redirigirá a la página de análisis, donde podrás ver las métricas de desglose de cada orador (tiempo de conversación y de silencio) y las métricas de la reunión en general. En este caso, podemos ver las estadísticas de Javier y Binoy. Otra función muy interesante de Symbl.ai es la posibilidad de resumir la llamada mediante el procesamiento del lenguaje natural. Esto te proporciona unas cuantas frases con un resumen de la llamada. De este modo, puedes hacerte una idea de lo que ha tratado la llamada leyendo algunos puntos destacados.
Esto es muy útil, ya que puede ayudar a evitar largos correos electrónicos de seguimiento con una recapitulación y elementos de acción después de una llamada. Reconocer los nombres de las marcas siempre es un reto, pero podemos ver cómo, en este caso, Javier ya ha realizado una integración con una empresa de IA que le permite habilitar subtítulos en directo, análisis de sentimiento y mucho más. Hay que tener en cuenta que esta fue una reunión muy corta, pero cuanto más larga sea la reunión, más preciso será el resumen.
¿Y ahora qué?
Esperamos que ahora sepas cómo puedes habilitar los subtítulos en vivo en tu aplicación Vonage Video y obtener más información sobre tus videollamadas. El proyecto completo está disponible en GitHub,
Cuéntanos en Twitter qué proyectos realizas con la Video API de Vonage.