Implementa la transcripción de audio en vivo lista para la producción con Speech-to-Text (Instructivo)

En este instructivo, crearás una app que realice la transcripción en tiempo real de una transmisión de audio con Speech-to-Text, Google Kubernetes Engine (GKE) y Memorystore. La app está diseñada para tener una disponibilidad alta y ser resiliente, y proporciona un modelo de referencia para una app de transcripción de producción. El código para la app que creas en este instructivo está en un repositorio de GitHub.

Este instructivo se complementa con la guía de arquitectura para la transcripción de audio en vivo lista para la producción mediante Speech-to-Text. Para obtener un análisis más detallado de los casos prácticos y las decisiones relacionadas al diseño, consulta ese documento.

Objetivos

  • Crear un clúster de GKE y una instancia de Memorystore
  • Compilar e implementar microservicios de apps en el clúster de GKE
  • Verificar el comportamiento de la app mediante la transmisión de un archivo de audio
  • Probar la resiliencia de la app mediante la introducción de fallas

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud sean aptos para obtener una prueba gratuita.

Antes de comenzar

  1. Accede a tu Cuenta de Google.

    Si todavía no tienes una cuenta, regístrate para obtener una nueva.

  2. En la página de selección de proyectos de Cloud Console, selecciona o crea un proyecto de Cloud.

    Ir a la página Selector de proyectos

  3. Comprueba que la facturación esté habilitada en tu proyecto.

    Descubre cómo puedes habilitar la facturación

  4. Habilita las API de Cloud Build API and the Speech-to-Text, GKE, and Memorystore.

    Habilita las API

Arquitectura

En el siguiente diagrama, se describe la arquitectura que implementas en este instructivo.

Arquitectura de infraestructura en Google Cloud para una app de transcripción lista para la producción

La arquitectura incluye las características siguientes:

  • Tres microservicios de aplicaciones:
    • Ingestor: Este servicio consume la transmisión de audio de origen.
    • Transcriber: Este servicio llama a Speech-to-Text y emite los resultados de la transcripción.
    • Reviewer: Este servicio muestra las transcripciones en una app web para su revisión.
  • GKE, que aloja los microservicios de aplicaciones en un clúster de GKE regional que abarca varias zonas. Los microservicios de la app se implementan en todas las zonas.
  • Memorystore para Redis, que se usa como almacenamiento intermedio rápido. Se implementa en una configuración de alta disponibilidad.
  • Balanceadores de cargas que exponen la funcionalidad de la app a Internet para hacer lo siguiente:
    • Proporcionar una dirección IP a la que se pueda dirigir la transmisión de audio de origen
    • Mostrar la app web de revisor

En este instructivo, usarás los siguientes clientes para probar la funcionalidad de la app:

  • Una secuencia de comandos de cliente de audio que transmite un archivo de audio al servicio Ingestor
  • Un cliente web de demostración que muestra las transcripciones del servicio Reviewer

Crea la infraestructura de Google Cloud

  1. En Cloud Shell, crea una variable para el ID de tu proyecto de Cloud:

    export PROJECT_ID=project-id
    

    Reemplaza project-id por el ID del proyecto de Cloud que creaste o seleccionaste para este instructivo.

  2. Configura el proyecto para tu sesión activa de Cloud Shell:

    gcloud config set project $PROJECT_ID
    
  3. Crea e inicia un clúster de GKE regional:

    gcloud container clusters create transcription-cluster \
        --cluster-version=1.14 \
        --region=us-central1 \
        --node-locations=us-central1-a,us-central1-b \
        --num-nodes=1 \
        --machine-type=n1-highcpu-2 \
        --scopes=cloud-platform \
        --enable-ip-alias \
        --metadata disable-legacy-endpoints=true
    

    Para este instructivo, crearás recursos en la región us-central1. Un solo nodo en dos zonas dentro de la región es suficiente para las tareas del instructivo.

    Esta tarea puede tardar unos minutos en completarse.

  4. Crea una instancia de Memorystore de nivel estándar en la misma región que el clúster de GKE:

    gcloud redis instances create redis-captions \
        --tier=standard \
        --region=us-central1 \
        --zone=us-central1-a
    

    Las instancias de nivel Estándar brindan alta disponibilidad mediante el uso de replicación y conmutación por error automática. La instancia consta de una instancia principal en la zona especificada y una réplica en una zona diferente dentro de la región. Esta tarea puede tomar unos minutos en completarse.

  5. Crea una variable de entorno para almacenar la dirección IP de la instancia de Memorystore:

    export REDIS_HOST=`gcloud redis instances describe redis-captions \
        --region=us-central1 --format='value(host)'`
    

Implementa los microservicios

  1. En Cloud Shell, clona el repositorio de GitHub que contiene el código de la app que implementarás:

    git clone https://github.com/GoogleCloudPlatform/solutions-speech-productionized-transcription
    
    
  2. Cambie al directorio del repositorio:

    cd solutions-speech-reliable-transcription
    
  3. Inicia una canalización de Cloud Build a fin de compilar los contenedores de Docker para los microservicios de la app:

    gcloud builds submit --config cloudbuild.yaml
    

    Los contenedores compilados se guardan en el Container Registry de tu proyecto.

  4. Cambia los archivos de configuración de YAML de Kubernetes para usar el ID de tu proyecto de Cloud:

    sed -i "s/myproject/$PROJECT_ID/" k8s/*.yaml
    
  5. Cambia los archivos de configuración YAML de Kubernetes para configurar la dirección IP de tu instancia de Memorystore:

    sed -i "s/redisHost=.*/redisHost=$REDIS_HOST/" k8s/*.yaml
    
  6. Implementa los microservicios Ingestor, Transcriber y Reviewer en el clúster de GKE:

    kubectl apply -f \
        k8s/ingestor.yaml,k8s/transcriber.yaml,k8s/reviewer.yaml
    
  7. Verifica que las tres implementaciones de Kubernetes se hayan creado en el clúster de GKE:

    kubectl get deployments
    

    El resultado es similar al siguiente. Ten en cuenta que cada implementación tiene dos pods.

    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    ingestor-deployment     2/2     2            2           13s
    reviewer-deployment     2/2     2            2           12s
    transcriber-deployment  2/2     2            2           12s
    
  8. Verifica que se hayan creado los servicios de Kubernetes Ingestor y Reviewer en el clúster de GKE:

    kubectl get services
    

    La salida es similar a esta:

    NAME               TYPE           CLUSTER-IP   EXTERNAL-IP
    ingestor-service   LoadBalancer   10.0.9.193   35.224.219.112
    kubernetes         ClusterIP      10.0.0.1     <none>
    reviewer-service   LoadBalancer   10.0.9.203   35.223.138.37
    
  9. Configura una variable de entorno para la dirección IP externa del servicio Ingestor:

    export INGEST_IP=`kubectl get services ingestor-service \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}'`
    
  10. Obtén el contenido de la página Ingestor para verificar que esté disponible:

    curl $INGEST_IP; echo
    

    Si la página funciona, verás un mensaje Hello.

  11. Configura una variable de entorno con la dirección IP externa del servicio Reviewer y muestra el valor de la variable en Console:

    export REVIEWER_IP=`kubectl get services reviewer-service \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}'`; \
        echo $REVIEWER_IP
    
  12. Copia la dirección REVIEWER_IP que mostró el comando anterior.

  13. En tu máquina local, abre una pestaña del navegador en esa dirección IP que acabas de copiar.

    Verás una página web de revisores que muestra el texto Live Transcription demo. Más adelante, las transcripciones se escribirán en esta página web, por lo que debes mantenerla abierta.

Verifica la transcripción de una transmisión de audio

En esta sección, transmites un archivo de audio a la app que acabas de implementar y examinas las transcripciones generadas. El audio es una lectura de las primeras oraciones del capítulo "Humpty Dumpty", del libro A través del espejo, de Lewis Carroll. Para comparar la forma en que Speech-to-Text transcribe el audio, puedes ver el texto del capítulo en el sitio Gutenberg.org.

El cliente de audio transmite el audio al servicio Ingestor mediante la biblioteca SocketIO, que es un paquete de código abierto que proporciona comunicación bidireccional en tiempo real y confiable. De manera similar, el servicio Reviewer entrega las transcripciones al cliente web de demostración con SocketIO.

En el servicio de Transcriber, se incluye la configuración de Speech-to-Text que coincide con las características del archivo de audio de muestra. Específicamente, la configuración define la tasa de muestreo de audio (44,100 kHz), la cantidad de canales de audio (canal único, mono) y el idioma de entrada (inglés de EE.UU.). Si deseas transmitir un archivo de audio diferente, es posible que debas actualizar la configuración para que coincida con el audio de entrada.

  1. En Cloud Shell, cambia al directorio de cliente:

    cd client
    
  2. Crea y activa un entorno virtual nuevo de Python 3. La utilidad virtualenv ya está instalada en Cloud Shell.

    virtualenv -p python3 venv
    source venv/bin/activate
    
  3. Instala los paquetes de Python que requiere el cliente web de demostración:

    pip install -r requirements.txt
    
  4. Ejecuta la secuencia de comandos del cliente de audio para transmitir un archivo de audio al servicio Ingestor:

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    
  5. Vuelve a la página web de revisor en tu máquina local.

    Verás las transcripciones que se transmiten a la página.

  6. Compara las transcripciones de Speech-to-Text con el texto del capítulo para determinar la precisión de las transcripciones.

    En la siguiente captura de pantalla, se muestra el texto y una transcripción de ejemplo.

    El texto original en la parte superior y una transcripción debajo.

  7. En Cloud Shell, presiona Control+C para detener la transmisión de audio.

Prueba la conmutación por error de Transcriber

Como se describe en la guía complementaria, el servicio Transcriber usa un patrón de elección de líder para garantizar que solo un pod de Transcriber esté conectado a Speech-to-Text y que los pods restantes actúen como pods en espera para una conmutación por error eficiente. En esta sección, verificarás el comportamiento de la conmutación por error mediante la supervisión de resultado de la transcripción cuando se borre el pod líder.

Cuando se elige un nuevo pod Transcriber como líder, como parte del proceso de recuperación, el nuevo líder reproduce los últimos segundos del audio recibido más recientemente. Esto ayuda a minimizar la pérdida de audio cuando el líder anterior se queda sin conexión. Este enfoque puede generar algunas palabras duplicadas, ya que se vuelve a reproducir el audio anterior. En una app de producción, los procesos que consumen las transcripciones deben eliminar cualquier duplicado.

  1. En tu máquina local, actualiza la pestaña del navegador para borrar las transcripciones existentes de la página web de revisor.

  2. En Cloud Shell, reinicia el cliente de audio:

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    Las transcripciones aparecen en la página web de revisor.

  3. Abre otra pestaña de Cloud Shell para tener dos pestañas de Cloud Shell abiertas.

  4. En la pestaña nueva de Cloud Shell, establece una variable de entorno en tu ID del proyecto:

    export PROJECT_ID=project-id
    

    Reemplaza project-id por el ID del proyecto de Cloud que creaste o seleccionaste para este instructivo.

  5. Cambie al directorio del repositorio:

    cd solutions-speech-reliable-transcription
    
  6. Borra el pod de transcriptor líder:

    python3 deleter.py --leader --iterations 3 --delay 15
    

    La secuencia de comandos consulta el plano de control de Kubernetes para obtener la identidad del pod líder actual y, luego, borra el pod. El comando borra al líder tres veces y espera 15 segundos entre cada iteración.

  7. Supervisa la página web de revisor.

    Verás una notificación de [REPLAY] en la transmisión de la transcripción. Esto indica que se eligió un nuevo pod Transcriber como líder y que los últimos segundos de datos de audio se están reproduciendo. Es posible que veas algunas palabras duplicadas en las transcripciones. Observa que la conmutación por error es muy rápida y que hay una interrupción limitada en el resultado de la transcripción.

  8. Verifica que la implementación de Transcriber aún tenga dos pods:

    kubectl get pods -l=app=transcriber
    

    La salida es similar a esta:

    NAME                                      READY   STATUS
    transcriber-deployment-7f57746c7c-rjwm5   2/2     Running
    transcriber-deployment-7f57746c7c-t7srr   2/2     Running
    

    Debido a que Transcriber es una implementación de Kubernetes, Kubernetes crea de manera automática nuevos pods para que se cumpla la cantidad especificada de réplicas de pods.

  9. Regresa a la primera pestaña de Cloud Shell y detén el cliente de audio presionando Control+C.

Borra otros pods de microservicios

En la sección anterior, verificaste que la publicación de la transcripción no se interrumpa cuando se borran los pods Transcriber. En esta sección, probarás el comportamiento de la aplicación cuando se borren otros pods de microservicios.

Los servicios de Kubernetes del tipo LoadBalancer exponen los pods Ingestor y Reviewer a Internet. Los clientes se conectan a cada servicio de Kubernetes mediante una dirección IP estable, y Kubernetes enruta el tráfico a un pod disponible. Cuando se borran los pods Ingestor o Reviewer, Kubernetes actualiza el servicio correspondiente para que el tráfico no se dirija a un pod inexistente. Del mismo modo, cuando se crean pods nuevos para satisfacer la cantidad configurada de réplicas de pods, el servicio se actualiza y se puede enviar el tráfico al pod nuevo.

En esta app, dependes de este comportamiento para mantener el tráfico avanzando por la app. Debido a que los servicios Ingestor y Reviewer tienen dos pods cada uno, cuando se quita un pod, Kubernetes puede redireccionar rápidamente el tráfico a otro pod que esté listo y que pueda comenzar a procesar el tráfico.

El cliente de audio y el cliente web de demostración usan SocketIO para conectarse con los servicios Ingestor y Reviewer. Cuando SocketIO pierde una conexión, intenta volver a conectarse de forma automática. De esa manera, si se borra el pod actual, los clientes se vuelven a conectar a un nuevo pod con la misma dirección IP de servicio.

Borrar pods Ingestor

  1. En tu máquina local, actualiza la pestaña del navegador para borrar las transcripciones existentes de la página web de revisor.

  2. En Cloud Shell, reinicia el cliente de audio:

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    Las transcripciones aparecen en la página web de revisor.

  3. Cambia a la otra pestaña de Cloud Shell.

  4. Borra un pod Ingestor:

    python3 deleter.py --applabel ingestor --iterations 5 --delay 15
    

    La secuencia de comandos consulta el plano de control de Kubernetes para obtener los nombres de todos los pods Ingestor y, luego, borra un pod seleccionado al azar. El comando borra un pod cinco veces, y espera 15 segundos entre cada iteración.

    Debido a que la secuencia de comandos selecciona de forma aleatoria un pod Ingestor para borrar, el pod al que se conecta el cliente de audio solo se borra la mitad del tiempo. Borrar el pod al que el cliente de audio no está conectado no tiene ningún impacto.

  5. Supervisa la página web de revisor. Las transcripciones continúan transmitiendo a la página sin interrupciones importantes a pesar de que se borran los pods.

  6. Cambia a la otra pestaña de Cloud Shell que ejecuta el cliente de audio.

    Observa que el cliente muestra mensajes cada vez que se interrumpe y restablece la conexión con el pod Ingestor.

  7. Presiona Control+C para detener el cliente de audio.

Borra los pods Reviewer

  1. En tu máquina local, actualiza la pestaña del navegador para borrar las transcripciones existentes de la página web de revisor.

  2. En Cloud Shell, reinicia el cliente de audio:

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    Las transcripciones aparecen en la página web de revisor.

  3. Cambia a la otra pestaña de Cloud Shell.

  4. Borrar un pod Reviewer

    python3 deleter.py --applabel reviewer --iterations 5 --delay 15
    

    La secuencia de comandos consulta el plano de control de Kubernetes para obtener los nombres de todos los pods Reviewer y, luego, borra un pod seleccionado al azar. El comando borra un pod cinco veces y espera 15 segundos entre cada iteración.

  5. Supervisa la página web de revisor.

    Las transcripciones siguen transmitiendo a la página sin interrupciones importantes, aunque se borren pods. En la página, se muestra el nombre del pod Reviewer al que está conectado. Verás este cambio en el campo cuando se borra el pod y cuando se establece una conexión con otro pod.

    Al igual que antes, debido a que un pod Reviewer se selecciona de forma aleatoria para su eliminación, el pod al que está conectada la página web de revisor solo se borra la mitad del tiempo. Borrar el pod al que el cliente web de demostración no está conectado no afecta la entrega de transcripciones.

  6. Pasa a la otra pestaña de Cloud Shell y presiona Control+C para detener el cliente de audio.

Prueba la conmutación por error de Memorystore para Redis

La aplicación usa Memorystore para Redis para lograr un almacenamiento rápido y en memoria. Utiliza una instancia de Memorystore para Redis en el nivel estándar, que brinda alta disponibilidad a través de la replicación y la conmutación por error automática. Una instancia de nivel estándar se configura de forma automática como un par de instancia principal y réplica. La réplica actúa como espera, y se encuentra en una zona diferente a la de la instancia principal. Si la instancia principal falla, las solicitudes se redireccionan de forma automática a la réplica.

En esta sección, probarás el comportamiento de conmutación por error de Memorystore para Redis cuando inicias una conmutación por error manual. Durante el tiempo que el servicio Memorystore para Redis promueve la réplica a la instancia principal, la instancia de Memorystore para Redis no se encuentra disponible temporalmente. Esto significa que las transcripciones se detienen durante la conmutación por error.

  1. En tu máquina local, actualiza la pestaña del navegador para borrar las transcripciones existentes de la página web de revisor.
  2. En Cloud Shell, reinicia el cliente de audio para comenzar a transmitir audio:

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    
  3. En la otra pestaña de Cloud Shell, inicia una conmutación por error manual de Memorystore para Redis y confirma que deseas que continúe la conmutación por error.

    gcloud redis instances failover redis-captions \
        --region us-central1 --project $PROJECT_ID
    
  4. Mira el resultado de la transcripción en la página web de revisor.

    Verás una notificación de [REDIS-FAILOVER], que indica que Memorystore no está disponible. Como era de esperar, las transcripciones se detienen mientras la réplica se convierte en la instancia principal. Cuando se completa este proceso, se procesan los datos de audio almacenados en búfer y se reanudan las transcripciones.

Limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en este instructivo:

Borra el proyecto

  1. En Cloud Console, ve a la página Administrar recursos.

    Ir a la página Administrar recursos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar .
  3. En el cuadro de diálogo, escribe el ID del proyecto y haz clic en Cerrar para borrar el proyecto.

¿Qué sigue?