Transmisión en vivo en Google Cloud con Media CDN y la API de transmisión en vivo

1. Introducción

Las redes de distribución de contenidos (CDN) mejoran el rendimiento de los usuarios almacenando en caché el contenido al que se accede con frecuencia más cerca de los usuarios finales, cerrando las conexiones más cerca de los clientes, reutilizando las conexiones con el origen y adoptando protocolos y personalizaciones de red modernos. Para los usuarios (y nuestros clientes), esto significa una latencia más baja, más confiabilidad y un costo reducido, lo que genera mejores ventas, una experiencia web mejorada y un aumento neto en la experiencia del usuario. En la actualidad, muy pocos sitios modernos y plataformas de transmisión de video funcionan sin una CDN.

Qué aprenderás

En este lab, se nos guiará a través de los pasos para implementar un entorno de flujo de trabajo de transmisión en vivo con Media CDN (CDN) + API de Cloud Media Live Streaming (transcodificación de video en vivo) + Cloud Storage (almacenamiento para los videos) + Reproductor de video (VLC, Google Shaka Player, etc.: reproductor listo para HLS y MPEG-DASH).

Configuraremos los componentes de la API de transmisión en vivo (entrada y canal) y comenzaremos un feed en vivo en la entrada o el canal con FFmpeg (FFmpeg puede generar una señal de prueba en vivo). La API de transmisión en vivo transcodificará el feed en vivo. El manifiesto y los segmentos de video transcodificados se almacenarán en un bucket de Cloud Storage. Luego, configuraremos Media CDN con el bucket de Cloud Storage de video en vivo como origen. Por último, se usará el Reproductor VLC para reproducir contenido en vivo almacenado en caché a través de Media CDN. También configuraremos un panel de Cloud Monitoring para visualizar la actividad de Media CDN.

Qué compilarás

En este lab, configuraremos el entorno según la siguiente arquitectura:

de33cb3e75d52549.png

Como parte del lab, configuraremos los siguientes componentes y realizaremos las siguientes tareas:

  • Crea un bucket de Google Cloud Storage (GCS) para almacenar los videos transcodificados en vivo
  • Configura la API de transmisión en vivo para transcodificar el video a varios formatos: HLS + MPEG DASH, SD y HD
  • Configura los componentes de transmisión en vivo: Entrada/Canal
  • Inicia el canal de transmisión en vivo
  • Configura Media CDN con el bucket de GCS como origen
  • Configura FFmpeg para que alimente el canal en vivo
  • Transmite el feed en vivo transcodificado con un reproductor de video
  • Configura un panel de Cloud Monitoring para supervisar la actividad de Media CDN (latencia, aciertos de caché, errores de caché, etcétera).

Nota: Para este lab, suponemos que los usuarios tienen acceso a la consola de Google Cloud y ya tienen un proyecto configurado. También suponemos que los usuarios comienzan con un entorno nuevo y no tienen nada configurado para esta demostración.

Todas las acciones de configuración se realizarán a través de la línea de comandos en Cloud Shell. Siempre podemos verificar los componentes configurados a través de la línea de comandos en la consola. Veremos punteros a lo largo del lab que dirigirán a la consola de Google Cloud.

2. Antes de comenzar

El acceso a Media CDN está restringido. Para obtener acceso a Media CDN, comunícate con tu equipo de cuentas. Pueden crear una solicitud de acceso en tu nombre. Si formas parte de Google y quieres probar la transmisión en vivo con Media CDN, comunícate con el PM de Media CDN para solicitar acceso a esta plataforma.

3. Configuración y requisitos

Inicia Cloud Shell

Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.

En Google Cloud Console, haz clic en el ícono de Cloud Shell en la barra de herramientas en la parte superior derecha:

55efc1aaa7a4d3ad.png

El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:

7ffe5cbb04455448.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Todo tu trabajo en este codelab se puede hacer en un navegador. No es necesario que instales nada.

4. Versión del SDK de Google Cloud

En el momento de escribir este artículo, 408.0.0 es la versión más reciente del SDK de Google Cloud. Todos los comandos de este lab se probaron con la versión más reciente del SDK de Google Cloud. Antes de continuar, asegúrate de que Cloud Shell esté usando la versión más reciente del SDK.

Cómo verificar la versión del SDK

Usaremos el comando gcloud version para verificar la versión del SDK.

Comando

gcloud version | grep "Google Cloud SDK"

Ejemplo de salida

Google Cloud SDK 408.0.0

Próximos pasos

  1. Si la versión del SDK es 408.0.0 o posterior, ve a la siguiente sección.
  2. Si la versión del SDK es inferior a 408.0.0, ejecuta el siguiente comando para actualizarlo.
sudo apt-get update && sudo apt-get install google-cloud-sdk

5. Requisitos previos

Antes de comenzar a configurar los recursos de GCP, debemos hacer lo siguiente:

  1. Configura variables de entorno
  2. Habilita las APIs de servicio obligatorias

1. Configura variables de entorno

A lo largo de este lab, ejecutaremos los comandos gcloud y curl con algunas variables. Debemos configurar las siguientes variables de entorno.

  • ID del proyecto
  • Número del proyecto
  • Nombre del usuario
  • Región
  • ID de entrada
  • ID del canal

ID del proyecto y nombre de usuario

Por lo general, estas variables de entorno están preconfiguradas en Cloudshell. Para verificarlo, usaremos el comando env.

Comando

env | grep -E 'DEVSHELL_PROJECT_ID=|LOGNAME'

Ejemplo de salida

DEVSHELL_PROJECT_ID=<YOUR_PROJECT_ID>
LOGNAME=<YOUR_USERNAME>

Crea el archivo env_variables

Usa el comando cat para crear el archivo env_variables.txt. El siguiente comando creará el archivo env_variables.txt en el directorio principal del usuario.

Comandos

cat > ~/env_variables.txt << EOF
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export LOCATION=us-west2
export INPUT_ID=lab-live-input
export CHANNEL_ID=lab-live-channel
EOF

Configura las variables de entorno

Usaremos el comando source para configurar las variables de entorno.

Comando

source ~/env_variables.txt

Verifica que las variables estén configuradas

Verifiquemos que se hayan configurado todas las variables de entorno necesarias. Deberíamos ver un total de 6 variables de entorno en el resultado.

Comando

env | grep -E 'DEVSHELL_PROJECT_ID=|LOGNAME|PROJECT_NUMBER|LOCATION|INPUT_ID|CHANNEL_ID'

Ejemplo de salida

LOCATION=us-west2
DEVSHELL_PROJECT_ID=<YOUR_PROJECT_ID>
LOGNAME=<YOUR_USERNAME>
PROJECT_NUMBER=<YOUR_PROJECT_NUMBER>
INPUT_ID=lab-live-input
CHANNEL_ID=lab-live-channel

2. Habilita las APIs de servicio obligatorias

Debemos asegurarnos de que las siguientes APIs estén habilitadas en nuestro proyecto.

  • API de servicios de red
  • API de Certificate Manager
  • API de Livestream
  • API de caché de borde de Media CDN

Habilita la API de Network Services

Para habilitar la API de Network Services, ejecuta el siguiente comando:

Comando

gcloud services enable networkservices.googleapis.com

Habilita la API de Certificate Manager

Para habilitar el certificado de la API de Management, ejecuta el siguiente comando:

Comando

gcloud services enable certificatemanager.googleapis.com

Habilita la API de Live Stream

Para habilitar la API de Live Stream, ejecuta el siguiente comando:

Comando

gcloud services enable livestream.googleapis.com

Habilita la API de Media CDN Edge Cache

Para habilitar la API de Media CDN Edge Cache, ejecuta el siguiente comando:

Comando

gcloud services enable edgecache.googleapis.com

Verifica que las APIs estén habilitadas

Ejecuta el comando gcloud services list para crear una lista de todas las APIs habilitadas. Deberíamos ver 4 APIs en el resultado.

Comando

gcloud services list | grep -E 'networkservices|certificatemanager|livestream|edgecache'

Ejemplo de salida

NAME: certificatemanager.googleapis.com
NAME: livestream.googleapis.com
NAME: networkservices.googleapis.com
NAME: edgecache.googleapis.com

6. Crea el bucket de Cloud Storage

En esta sección, haremos lo siguiente:

  1. Cree un bucket de Cloud Storage
  2. Permite el acceso público al bucket

Más adelante en el lab, usaremos este bucket para almacenar los archivos de video transcodificados. Este bucket también actuará como almacenamiento de origen para el servicio de Media CDN.

1. Crea un bucket

Usaremos el comando gsutil mb para crear el bucket:

Comando

gsutil mb gs://live-streaming-storage-$LOGNAME

2. Permite el acceso público al bucket

Usaremos el comando iam de gsutil para que los archivos estén disponibles para el público:

Comando

gsutil iam ch allUsers:objectViewer gs://live-streaming-storage-$LOGNAME

7. Cómo configurar el entorno de la API de Live Streaming

Los componentes de la cadena de la API de transmisión en vivo tienen la siguiente arquitectura:

96b5d26aedeb89a6.png

Creamos el bucket de Cloud Storage live-streaming-storage-$LOGNAME en la sección anterior. En las siguientes dos secciones, crearemos los siguientes recursos:

  • Entrada de transmisión en vivo: Un extremo de entrada es un extremo al que el codificador envía tu flujo de entrada. Puedes usar el extremo de entrada para especificar parámetros de configuración para tu transmisión, como la resolución de entrada, el tipo de entrada y el recorte de video.
  • Canal de transmisión en vivo: Un canal es un recurso que transfiere la transmisión de entrada a través de un extremo de entrada, la transcodifica en varias versiones y publica transmisiones en vivo de salida en ciertos formatos en la ubicación especificada. Puedes incluir un flujo de entrada principal y uno de respaldo en el mismo canal.

Más adelante en el lab, crearemos los siguientes recursos:

  • Codificación: Un codificador es un programa que se usa para enviar flujos de entrada. En este lab, usaremos FFmpeg.

8. Crea y configura el extremo de entrada

Crea el archivo input.json

Crearemos un archivo input.json para especificar el tipo de señal de transmisión en vivo. En este lab, usaremos la señal en vivo de RTMP.

Comando

cat > input.json << EOF
{
  "type": "RTMP_PUSH"
}
EOF

Crea el extremo de entrada

En el momento de escribir este lab, no hay compatibilidad con gcloud para la API de transmisión en vivo. Usaremos el comando curl para realizar las llamadas a la API.

Comando

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @input.json \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/inputs?inputId=$INPUT_ID"

Ejemplo de salida

{
  "name": "projects/PROJECT_NUMBER/locations/us-west2/operations/operation-1661405972853-5e70a38d6f27f-79100d00-310671b4",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": "2022-08-25T05:39:32.884030164Z",
    "target": "projects/PROJECT_NUMBER/locations/us-west2/inputs/lab-live-input",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

El resultado tiene mucha información útil, pero en este momento, debemos enfocarnos en dos campos:

  • ID de operación: En el resultado, copia y toma nota del ID de operación. A continuación, se muestra el ID de operación del ejemplo de salida. Puedes encontrarlo en la línea de salida que comienza con "name". "operation-1661405972853-5e70a38d6f27f-79100d00-310671b4"
  • Estado: Debemos esperar a que el estado cambie de "done": false a "done": true.

Consulta el estado

Antes de continuar, debemos verificar que el extremo de entrada se haya creado correctamente y esté listo.

En el siguiente comando, reemplaza <OPERATION> por el ID de la operación que acabamos de obtener. En este ejemplo, es "operation-1661405972853-5e70a38d6f27f-79100d00-310671b4".

Comando

export OPERATION_ID_1=<OPERATION>

Comando

curl -X GET \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/operations/$OPERATION_ID_1"

Ejemplo de salida

{
  "name": "projects/PROJECT_NUMBER/locations/us-west2/operations/operation-1661408816982-5e70ae25cea49-617844f0-8fdcb4a1",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": "2022-08-25T06:26:57.001530499Z",
    "endTime": "2022-08-25T06:26:57.043623522Z",
    "target": "projects/PROJECT_NUMBER/locations/us-west2/inputs/lab-live-input",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.Input",
    "name": "projects/PROJECT_ID/locations/us-west2/inputs/lab-live-input",
    "createTime": "2022-08-25T06:26:56.997623672Z",
    "updateTime": "2022-08-25T06:26:56.997623672Z",
    "type": "RTMP_PUSH",
    "uri": "rtmp://34.94.97.220/live/4b7846a1-4a67-44ed-bfd0-d98281b6464a",
    "tier": "HD"
  }
}

Vuelve a ejecutar el comando hasta que veas "done:true", que indica que se creó el extremo de entrada y está listo.

Guarda el URI

Más adelante en el lab, usaremos el URI del resultado anterior. En este momento, establezcamos una variable de entorno para URI.

Comando

export URI=<uri>

Reemplaza <uri> por el URI que anotaste anteriormente. De manera opcional, también puedes usar el método GET para recuperar el URI.

Comando

curl -s -X GET -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) "https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/inputs/$INPUT_ID" | jq .uri

9. Crea y configura el canal de transmisión en vivo

Creemos el canal de transmisión en vivo, asociado con el extremo de entrada que acabamos de crear en la sección anterior. En el siguiente ejemplo, se crea un canal que genera una transmisión en vivo HLS que consta de una sola renderización de alta definición (1280 x 720). El canal se asociará con el extremo de entrada y el bucket de almacenamiento que creamos anteriormente.

Crea el archivo channel.json

En la terminal de Cloud Shell, escribe el siguiente comando para crear un archivo "channel.json":

Comando

cat > channel.json << EOF
{
  "inputAttachments": [
    {
      "key": "my-input",
      "input": "projects/$PROJECT_NUMBER/locations/$LOCATION/inputs/$INPUT_ID"
    }
  ],
  "output": {
    "uri": "gs://live-streaming-storage-$LOGNAME"
  },
  "elementaryStreams": [
    {
      "key": "es_video",
      "videoStream": {
        "h264": {
          "profile": "high",
          "widthPixels": 1280,
          "heightPixels": 720,
          "bitrateBps": 3000000,
          "frameRate": 30
        }
      }
    },
    {
      "key": "es_audio",
      "audioStream": {
        "codec": "aac",
        "channelCount": 2,
        "bitrateBps": 160000
      }
    }
  ],
  "muxStreams": [
    {
      "key": "mux_video_ts",
      "container": "ts",
      "elementaryStreams": ["es_video", "es_audio"],
      "segmentSettings": { "segmentDuration": "2s" }
    }
  ],
  "manifests": [
    {
      "fileName": "main.m3u8",
      "type": "HLS",
      "muxStreams": [
        "mux_video_ts"
      ],
      "maxSegmentCount": 5
    }
  ]
}
EOF

Crea el canal

Ejecuta el siguiente comando curl para crear el canal:

Comando

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @channel.json \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels?channelId=$CHANNEL_ID"

Ejemplo de salida

{
  "name": "projects/PROJECT_NUMBER/locations/us-west2/operations/operation-1661405972853-5e70a38d6f27f-79100d00-310671b4",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": "2022-08-25T05:39:32.884030164Z",
    "target": "projects/PROJECT_NUMBER/locations/us-west2/channels/lab-live-channel",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

Anota y copia el ID de operación. La necesitaremos en uno de los próximos pasos. Puedes encontrarlo en la línea de salida que comienza con "name".

Consulta el estado

Antes de continuar, debemos verificar que el canal se haya creado correctamente y esté listo.

En el siguiente comando, reemplaza <OPERATION> por el ID de la operación que acabamos de obtener. En este ejemplo, es operation-1661405972853-5e70a38d6f27f-79100d00-310671b4.

Comando

export OPERATION_ID_2=<OPERATION>

Comando

curl -s -X GET \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/operations/$OPERATION_ID_2"

Ejemplo de salida

  "name": "projects/PROJECT_NUMBER/locations/us-west2/operations/operation-1668666801461-5eda4c3f31852-a4d2229f-0efeef9e",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": "2022-11-17T06:33:21.500841488Z",
    "endTime": "2022-11-17T06:33:21.529311112Z",
    "target": "projects/PROJECT_NUMBER/locations/us-west2/channels/lab-live-channel",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.Channel",
    "name": "projects/PROJECT_NAME/locations/us-west2/channels/lab-live-channel",
    "createTime": "2022-11-17T06:33:21.497818033Z",
    "updateTime": "2022-11-17T06:33:21.497818033Z",
    "activeInput": "my-input",
    "output": {
      "uri": "gs://live-streaming-storage-LOGNAME"
    },
    "elementaryStreams": [
      {
        "videoStream": {
          "h264": {
            "widthPixels": 1280,
            "heightPixels": 720,
            "frameRate": 30,
            "bitrateBps": 3000000,
            "gopDuration": "2s",
            "vbvSizeBits": 3000000,
            "vbvFullnessBits": 2700000,
            "entropyCoder": "cabac",
            "profile": "high"
          }
        },
        "key": "es_video"
      },
      {
        "audioStream": {
          "codec": "aac",
          "bitrateBps": 160000,
          "channelCount": 2,
          "sampleRateHertz": 48000
        },
        "key": "es_audio"
      }
    ],
    "muxStreams": [
      {
        "key": "mux_video_ts",
        "container": "ts",
        "elementaryStreams": [
          "es_video",
          "es_audio"
        ],
        "segmentSettings": {
          "segmentDuration": "2s"
        }
      }
    ],
    "manifests": [
      {
        "fileName": "main.m3u8",
        "type": "HLS",
        "muxStreams": [
          "mux_video_ts"
        ],
        "maxSegmentCount": 5,
        "segmentKeepDuration": "60s"
      }
    ],
    "streamingState": "STOPPED",
    "inputAttachments": [
      {
        "key": "my-input",
        "input": "projects/PROJECT_NUMBER/locations/us-west2/inputs/lab-live-input"
      }
    ],
    "logConfig": {
      "logSeverity": "OFF"
    }
  }
}

Vuelve a ejecutar el comando hasta que veas "done:true", que indica que se creó el extremo de entrada y está listo.

Ten en cuenta que el "streamingState" en este momento es "STOPPED". Comenzaremos el canal en la siguiente sección.

10. Inicia el canal de transmisión en vivo

Ahora que creamos nuestro canal de transmisiones en vivo, comencemos a usarlo. En esta sección, haremos lo siguiente:

  1. Inicia el canal de transmisiones en vivo
  2. Verifica el estado del canal. Debemos asegurarnos de que streamingState sea "AWAITING INPUT".

1. Inicia el canal

En Cloud Shell, ejecuta el siguiente comando curl para iniciar el canal:

Comando

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d "" \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels/$CHANNEL_ID:start"

Ejemplo de salida

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/operation-1661405972853-5e70a38d6f27f-79100d00-310671b4",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": "2022-08-25T05:39:32.884030164Z",
    "target": "projects/PROJECT_NUMBER/locations/us-west2/channels/lab-live-channel",
    "verb": "start",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

2. Verifica el estado del canal

Ejecuta el siguiente comando curl para obtener el estado del canal:

Comando

curl -s -X GET -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) "https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels/$CHANNEL_ID" | grep "streamingState"

Ejemplo de salida

"streamingState": "AWAITING_INPUT",

Vuelve a ejecutar el comando hasta que veas "AWAITING_INPUT", lo que indica que el canal se está ejecutando y está listo para recibir una señal.

11. Configura Media CDN

En esta sección, implementaremos Media CDN, la infraestructura de CDN. Crearemos los siguientes recursos:

  1. Origen de la caché perimetral
  2. Servicio de almacenamiento en caché perimetral

1. Crea un origen de almacenamiento en caché perimetral

Un origen de caché perimetral representa una ubicación de contenido, como un bucket de Cloud Storage, una ubicación de almacenamiento de terceros o un balanceador de cargas. En términos de CDN, el origen (o servidor de origen) es la ubicación donde se encuentra la fuente del contenido que queremos distribuir, p.ej., todo el CSS, JavaScript, HTML, imágenes, etc. En este lab, crearemos un origen que se asigne al bucket de Cloud Storage que creamos al principio del lab. Llamaremos al origen de almacenamiento en caché perimetral cme-origin. El origen de una CDN es donde se almacena todo el contenido de origen antes de distribuirlo a los servidores de caché perimetrales.

Usaremos el comando gcloud edge-cache origins create para crear el origen. El comando tardará unos minutos en completarse.

Comando

gcloud edge-cache origins create cme-origin \
--origin-address="gs://live-streaming-storage-$LOGNAME"

Resultado de ejemplo

Create request issued for: cme-origin
Waiting for operation [projects/my-project/locations/global/operations/operation-1612121774168-5ba3759af1919-
3fdcd7b1-99f59223] to complete...done
Created origin cme-origin

2. Cómo crear un servicio de almacenamiento en caché perimetral

Ahora que tenemos configurado un origen del almacenamiento en caché perimetral, podemos crear el servicio de almacenamiento en caché perimetral.

Crea el archivo cme-demo.yaml

La configuración del servicio de almacenamiento en caché perimetral se realiza a través de un archivo YAML. En Cloud Shell, crea un archivo local llamado cme-demo.yaml. Usa vi, nano o cualquier otro editor y pega las siguientes líneas en el archivo YAML:

name: cme-demo
routing:
  hostRules:
    - hosts:
        - demo.cme.com
      pathMatcher: routes
  pathMatchers:
    - name: routes
      routeRules:
        - headerAction:
            responseHeadersToAdd:
              - headerName: x-cache-status
                headerValue: "{cdn_cache_status}"
          matchRules:
            - prefixMatch: /
          origin: cme-origin
          priority: 100
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 3600s
              signedRequestMode: DISABLED
        - headerAction:
            responseHeadersToAdd:
              - headerName: x-cache-status
                headerValue: "{cdn_cache_status}"
          matchRules:
            - pathTemplateMatch: /**.m3u8
          origin: cme-origin
          priority: 25
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 1s
              signedRequestMode: DISABLED
        - headerAction: {}
          matchRules:
            - pathTemplateMatch: /**.ts
          origin: cme-origin
          priority: 50
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 2s
              signedRequestMode: DISABLED

Dejaremos todos los parámetros de configuración predeterminados del servicio de almacenamiento en caché perimetral. En el archivo anterior, hay 3 valores de campo que los usuarios podrían querer actualizar:

  • name: El nombre de la instancia de Media CDN (aquí: cme-demo)
  • hosts: La lista de nombres de dominio que resolverá este servicio de Media CDN: demo.cme.com. La usaremos durante esta demostración. Usaremos la dirección IP de la instancia de Media CDN.
  • Origin: es el origen del almacenamiento en caché perimetral que acabamos de crear en el paso anterior. Establece el valor en cme-origin, el nombre del origen de Media CDN.

Para obtener más información sobre las diferentes variables que puedes usar en el archivo YAML, consulta la Guía de configuración del servicio de caché de Edge.

Crea el servicio de almacenamiento en caché perimetral

Crearemos un servicio de almacenamiento en caché perimetral llamado cme-demo, en el origen del almacenamiento en caché perimetral cme-origin, con el host demo.cme.com. Para crear el servicio, ejecuta el siguiente comando en Cloud Shell:

Comando

gcloud edge-cache services import cme-demo \
    --source=cme-demo.yaml

La creación del servicio de caché de Edge puede tardar unos minutos.

Ejemplo de salida

Request issued for: [cme-demo]
Waiting for operation [projects/PROJECT_ID/locations/global/operations/operation-1670476252264-5ef4a0f9f36ce-dd380af5-321be9a0] to complete...done.     
createTime: '2022-12-07T18:08:54.403446942Z'
ipv4Addresses:
- 34.104.35.152
ipv6Addresses:
- '2600:1900:4110:d18::'
name: projects/PROJECT_ID/locations/global/edgeCacheServices/cme-demo
routing:
  hostRules:
  - hosts:
    - demo.cme.com
    - 34.104.35.152
    pathMatcher: routes
  pathMatchers:
  - name: routes
    routeRules:
    - headerAction:
        responseHeadersToAdd:
        - headerName: x-cache-status
          headerValue: '{cdn_cache_status}'
      matchRules:
      - prefixMatch: /
      origin: projects/123456789/locations/global/edgeCacheOrigins/cme-origin
      priority: '100'
      routeAction:
        cdnPolicy:
          cacheKeyPolicy: {}
          cacheMode: FORCE_CACHE_ALL
          defaultTtl: 3600s
          signedRequestMode: DISABLED
    - headerAction:
        responseHeadersToAdd:
        - headerName: x-cache-status
          headerValue: '{cdn_cache_status}'
      matchRules:
      - pathTemplateMatch: /**.m3u8
      origin: projects/123456789/locations/global/edgeCacheOrigins/cme-origin
      priority: '25'
      routeAction:
        cdnPolicy:
          cacheKeyPolicy: {}
          cacheMode: FORCE_CACHE_ALL
          defaultTtl: 1s
          signedRequestMode: DISABLED
    - headerAction: {}
      matchRules:
      - pathTemplateMatch: /**.ts
      origin: projects/123456789/locations/global/edgeCacheOrigins/cme-origin
      priority: '50'
      routeAction:
        cdnPolicy:
          cacheKeyPolicy: {}
          cacheMode: FORCE_CACHE_ALL
          defaultTtl: 2s
          signedRequestMode: DISABLED
updateTime: '2022-12-08T05:11:31.598744308Z'

Anota y copia el ipv4Addresses de la instancia del servicio de almacenamiento en caché perimetral, aquí 34.104.36.157. La usaremos para actualizar el archivo cme-demo.yaml y, luego, para transmitir el video transcodificado.

Actualiza el servicio de almacenamiento en caché perimetral

En este punto, es recomendable actualizar la configuración del servicio de almacenamiento en caché perimetral para poder usar la IP del servicio y transmitir el video más adelante. El archivo YAML del servicio de almacenamiento en caché perimetral nos permite enumerar todos los nombres de host o IPs de los que el servicio de almacenamiento en caché perimetral aceptará solicitudes. En este punto, solo especificamos demo.cme.com como host. Para proporcionar la resolución de nombres de este dominio, puedes configurar una zona de DNS. Sin embargo, una solución más sencilla sería agregar la dirección IP a la lista de hosts en el archivo yaml. Vuelve a editar el archivo YAML para que se vea como el siguiente:

name: cme-demo
routing:
  hostRules:
    - hosts:
        - demo.cme.com
        - IPADDRESS
      pathMatcher: routes
  pathMatchers:
    - name: routes
      routeRules:
        - headerAction:
            responseHeadersToAdd:
              - headerName: x-cache-status
                headerValue: "{cdn_cache_status}"
          matchRules:
            - prefixMatch: /
          origin: cme-origin
          priority: 100
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 3600s
              signedRequestMode: DISABLED
        - headerAction:
            responseHeadersToAdd:
              - headerName: x-cache-status
                headerValue: "{cdn_cache_status}"
          matchRules:
            - pathTemplateMatch: /**.m3u8
          origin: cme-origin
          priority: 25
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 1s
              signedRequestMode: DISABLED
        - headerAction: {}
          matchRules:
            - pathTemplateMatch: /**.ts
          origin: cme-origin
          priority: 50
          routeAction:
            cdnPolicy:
              cacheKeyPolicy: {}
              cacheMode: FORCE_CACHE_ALL
              defaultTtl: 2s
              signedRequestMode: DISABLED

Para reflejar los cambios, solo debemos volver a importar el archivo YAML. En la terminal de Cloud Shell, ejecuta el siguiente comando:

Comando

gcloud edge-cache services import cme-demo \
    --source=cme-demo.yaml

Revisa el resultado del comando y verifica que la IP aparezca en la lista de hosts.

En este punto, la instancia del servicio de almacenamiento en caché perimetral aceptará solicitudes con "demo.cme.com" o la dirección IP como host.

12. Genera la señal de entrada

Ahora que configuramos todos los servicios necesarios, generemos la señal de entrada de la transmisión en vivo. En esta sección, haremos lo siguiente:

  1. Instala FFmpeg, un software de código abierto y gratuito
  2. Envía una señal de prueba en vivo a la entrada o al canal

1. Instala FFmpeg

FFmpeg es un proyecto de software gratuito y de código abierto que consta de un paquete de bibliotecas y programas para controlar transmisiones y archivos multimedia, de audio y video. En la terminal de Cloud Shell, usa el siguiente comando para instalar FFmpeg:

Comando

sudo apt install ffmpeg -y

Cuando termine la instalación, verifiquemos que FFmpeg se haya instalado correctamente comprobando su versión:

Comando

ffmpeg -version

Ejemplo de salida

ffmpeg version 4.3.4-0+deb11u1 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 10 (Debian 10.2.1-6)
...

FFmpeg se instaló correctamente.

2. Inicia el indicador de transmisión en vivo en la entrada o el canal.

Ahora que FFmpeg está instalado, enviaremos una transmisión de entrada de prueba al extremo de entrada para generar la transmisión en vivo.

En la terminal de Cloud Shell, ejecuta el siguiente comando con la variable de entorno de URI que creamos en la sección "Crea y configura el extremo de entrada".

Comando

ffmpeg -re -f lavfi -i "testsrc=size=1280x720 [out0]; sine=frequency=500 [out1]" \
  -acodec aac -vcodec h264 -f flv $URI

Deberías ver que FFmpeg envía la señal de prueba en vivo. El comando no mostrará el mensaje. El indicador se generará hasta que lo detengas. Deberás abrir una ventana nueva de Cloud Shell para el resto del lab.

13. Cómo abrir una nueva sesión de Cloud Shell

En este punto, deberás abrir una nueva ventana de Cloud Shell para continuar con el lab, ya que FFmpeg se ejecutará de forma permanente hasta que presiones <Ctrl + C> para detenerlo y, de esta manera, detener la generación de la señal en vivo.

Haz clic en el signo "+" junto al nombre de la terminal de Cloud Shell actual. Se abrirá una ventana adicional de Cloud Shell.

b3c7b0be6276c194.png

Ejecuta el resto del lab en la ventana de Cloud Shell que acabas de abrir.

Configura las variables de entorno

Dado que esta es una nueva instancia de CloudShell, debemos volver a configurar las variables de entorno. Usaremos el comando source para configurar las variables de entorno.

Comando

source ~/env_variables.txt

Verifica que las variables estén configuradas

Verifiquemos que se hayan configurado todas las variables de entorno necesarias. Deberíamos ver un total de 6 variables de entorno en el resultado.

Comando

env | grep -E 'DEVSHELL_PROJECT_ID=|LOGNAME|PROJECT_NUMBER|LOCATION|INPUT_ID|CHANNEL_ID'

Ejemplo de salida

LOCATION=us-west2
DEVSHELL_PROJECT_ID=<YOUR_PROJECT_ID>
LOGNAME=<YOUR_USERNAME>
PROJECT_NUMBER=<YOUR_PROJECT_NUMBER>
INPUT_ID=lab-live-input
CHANNEL_ID=lab-live-channel

14. Verifica que se esté transcodificando la señal en vivo

Ejecutaremos un curl para describir el canal. En el resultado, deberíamos ver que streamingState cambió de "AWAITING_INPUT" a "STREAMING".

Comando

curl -s -X GET -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) "https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels/$CHANNEL_ID" | grep "streamingState"

En la respuesta del archivo JSON de salida, deberías ver "streamingState": "STREAMING", lo que indica que el canal está transmitiendo y que la señal en vivo se está transcodificando.

También verifiquemos el contenido del bucket, en el que deberíamos ver un archivo de manifiesto y varios segmentos de video TS. Ejecuta el siguiente comando en Cloud Shell para crear una lista del contenido del bucket que creamos al comienzo del lab y que usa la API de transmisión continua para generar el manifiesto de señal en vivo transcodificado y los segmentos de video TS:

Comando

gcloud storage ls --recursive gs://live-streaming-storage-$LOGNAME/**

Ejemplo de salida

gs://live-streaming-storage-$LOGNAME/
gs://live-streaming-storage-$LOGNAME/main.m3u8
gs://live-streaming-storage-$LOGNAME/mux_video_ts/index-1.m3u8
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000016.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000017.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000018.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000019.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000020.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000021.ts
gs://live-streaming-storage-$LOGNAME/mux_video_ts/segment-0000000022.ts
...

Deberías ver lo siguiente:

  • el archivo de manifiesto HLS: main.m3u8
  • Los segmentos de video TS correspondientes: una serie de archivos numerados segment-000000000X.ts

En este punto, ya terminamos con lo siguiente:

  • API de transmisión en vivo: La señal en vivo se genera y transcodifica en un bucket a través de la API de transmisión en vivo.
  • Media CDN: Se configuró Media CDN con el bucket de almacenamiento de transmisión en vivo como su origen.

En las siguientes secciones, validaremos el servicio de caché de borde y, luego, transmitiremos el video transcodificado con la dirección IP de anycast de la CDN de Media.

15. Verifica que la instancia del servicio de almacenamiento en caché perimetral funcione

En esta sección, verificaremos que la instancia del servicio de caché de Edge funcione según lo esperado. Para ello, intentaremos acceder a un archivo de la instancia del servicio de almacenamiento en caché perimetral con la dirección IP del servicio de almacenamiento en caché perimetral. La primera vez que se accede a un objeto, aún no se almacena en caché. Deberíamos observar una caché MISS. En la primera solicitud, el objeto se lee desde el origen y se almacena en caché en el perímetro. Todos los siguientes intentos de acceso al mismo archivo mostrarán una caché HIT, ya que el objeto ahora está almacenado en caché en el perímetro. Verifiquemos este comportamiento:

Ejecuta el siguiente comando curl en Cloud Shell para acceder al archivo de manifiesto de video transcodificado que se almacena en el origen de la caché de Edge:

Comando

curl -svo /dev/null --resolve demo.cme.com:80:<Replace_With_Edge_Cache_IP> \
"http://demo.cme.com/main.m3u8"

Observa la resolución en la que usamos la dirección IP de la instancia del servicio de almacenamiento en caché perimetral para resolver su nombre. Asegúrate de usar demo.cme.com:<IP>, donde IP es la IP de la instancia del servicio de almacenamiento en caché perimetral que acabamos de crear.

Busca el encabezado x-cache-status en el resultado.

Ejemplo de salida

Added demo.cme.com:80:34.104.35.152 to DNS cache
* Hostname demo.cme.com was found in DNS cache
*   Trying 34.104.35.152:80...
* Connected to demo.cme.com (34.104.35.152) port 80 (#0)
> GET /main.m3u8 HTTP/1.1
> Host: demo.cme.com
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< x-guploader-uploadid: ADPycdtKtflWt4Kha5YxXNNRwO-Eu6fGSPs-T-XY4HJmNMo46VJyWlD4EAk-8a6SegxjWq3o1gTPqZbpkU_sjW__HPAdDw
< date: Wed, 07 Dec 2022 18:23:46 GMT
< last-modified: Wed, 07 Dec 2022 18:23:45 GMT
< etag: "6bff620ccca4a9849ba4e17fa7c521fb"
< x-goog-generation: 1670437425805400
< x-goog-metageneration: 1
< x-goog-stored-content-encoding: identity
< x-goog-stored-content-length: 193
< content-type: application/x-mpegURL
< x-goog-hash: crc32c=sPO3zw==
< x-goog-hash: md5=a/9iDMykqYSbpOF/p8Uh+w==
< x-goog-storage-class: STANDARD
< accept-ranges: bytes
< content-length: 193
< server: Google-Edge-Cache
< x-request-id: fd25285b-fc1a-4fd4-981a-c50ead2c85ed
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< x-cache-status: den;miss
< cache-control: public,max-age=3600
<
{ [193 bytes data]
* Connection #0 to host demo.cme.com left intact

Observa la falta de caché, ya que el objeto aún no se almacenó en caché y se lee desde el origen.

Ahora, realizaremos varias solicitudes para el archivo m3u8 y, si todo está configurado correctamente, la CDN de Media debería comenzar a entregar el contenido desde su caché. El siguiente comando realizará 10 solicitudes de curl y solo imprimirá el encabezado x-cache-status.

Comando

for i in {1..10};do curl -Is --resolve demo.cme.com:80:<Replace_With_Edge_Cache_IP> "http://demo.cme.com/main.m3u8" | grep x-cache-status;done

El resultado debe ser una combinación de hit y miss de la caché. Si ves hits de caché en el resultado, significa que Media CDN funciona como se espera.

Ejemplo de salida

x-cache-status: den;miss
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit
x-cache-status: den;hit

Observa el acierto de la caché, ya que el objeto ahora está almacenado en caché en el perímetro. El servicio de Cloud Media Edge funciona como se espera.

16. Cómo transmitir un video de señal en vivo transcodificado con VLC

Esta es la parte en la que conectamos los puntos y vinculamos todos los pasos en los que hemos estado trabajando hasta ahora:

  • Creamos un bucket llamado live-streaming-storage-$LOGNAME que recibe el resultado de la señal en vivo transcodificada a contenido HLS por la API de transmisión en vivo.
  • Configuramos la API de transmisión en vivo.
  • Comenzamos un indicador en vivo de RTMP con FFmpeg que alimenta la entrada o el canal de la API de transmisión en vivo.
  • Verificamos que el canal recibiera la señal en vivo y que estuviera en modo streaming.
  • Verificamos que los archivos transcodificados resultantes (manifiesto + segmentos TS) se generaron y almacenaron en el bucket live-streaming-storage-$LOGNAME.
  • Se configuró un origen del almacenamiento en caché perimetral llamado cme-origin con el bucket de GCS live-streaming-storage-$LOGNAME como origen.
  • Se configuró una instancia de Edge Cache llamada cme-demo con cme-origin como su origen.
  • Verificamos el comportamiento (falta de caché, acierto de caché) de la instancia del servicio de almacenamiento en caché perimetral.

Ahora estamos en un punto en el que podemos usar un reproductor de video para transmitir el indicador en vivo transcodificado a través de la caché de Media CDN. Para ello, usaremos el reproductor VLC. El reproductor VLC es un framework y reproductor multimedia multiplataforma de código abierto y gratuito que reproduce la mayoría de los archivos multimedia. Reproduce formatos multimedia adaptables (como DASH y HLS). Usa el principio de la transmisión adaptable: según la calidad de tu conexión de red y el ancho de banda disponible, el reproductor adaptará la calidad del video que se reproduce. Con el trabajo de transcodificación que acabamos de realizar, usamos los parámetros de configuración predeterminados y generamos “solo” dos calidades: SD y HD. Cuando comencemos a reproducir el video en el reproductor, deberías ver que comienza a reproducirse en formato SD y cambia rápidamente al formato HD si tu conexión de red es lo suficientemente buena.

Transmitiremos la señal en vivo transcodificada en HLS (formato de video de Apple ampliamente compatible). El archivo correspondiente se llama main.m3u8, que es el manifiesto HLS. El manifiesto apunta a los segmentos de video TS.

Para usar el Reproductor VLC, ve a https://www.videolan.org/vlc/ y descarga una versión del reproductor para el sistema operativo de tu laptop. VLC está disponible para Windows, MacOSX, Linux, Android y iOS.

2a2d19abe728d222.png

Instala el reproductor en tu laptop y ejecútalo. En los próximos pasos, usaremos la versión para MacOSX del reproductor.

Para reproducir un video, ve a "File" / "Open Network":

f85565301f7c68dc.png

Configura el dispositivo con lo siguiente:

  • URL: http://<Replace_With_Edge_Cache_IP>/main.m3u8. Esta es la URL del video que queremos transmitir. Ten en cuenta que:
  • La IP de la instancia de Media CDN: 34.105.35.246 Reemplaza la IP del servicio de Cloud Media que implementaste.
  • La ruta de acceso al archivo de video del manifiesto: "/". Esta es la ruta que usamos en el bucket live-streaming-storage-$LOGNAME para almacenar los archivos de señal en vivo transcodificados. La ruta de acceso es la raíz: “/”.
  • Es el nombre del archivo de video del manifiesto: el archivo de manifiesto HLS, main.m3u8.

y haz clic en “Abrir”. Deberías ver que comienza a reproducirse el video en vivo transcodificado. El video se verá como en la siguiente captura de pantalla. El contador en pantalla se ejecutará en incrementos de 1 y deberías escuchar un pitido continuo.

Es una señal en vivo de prueba básica de RTMP que genera FFmpeg, que la API de transmisión en vivo transcodifica a HLS y se entrega a través de la caché de Media CDN:

28fc359b49d44ec2.png

Si lo deseas, puedes usar cualquier otro reproductor HLS y MPEG DASH. Estos son algunos que te recomendamos:

  • Reproductor QuickTime: Se instala de forma predeterminada en Mac. Lo mismo aquí: abre una conexión de red a http://34.104.36.157/main.m3u8. Reemplaza la dirección IP por la de tu instancia del servicio de almacenamiento en caché perimetral.

17. Cómo supervisar Media CDN

El equipo de SME creó una plantilla de panel de Media CDN: https://gist.github.com/elithrar/1c511d00f5cd3736fb2a3897867209c1.

Para instalarlo, ejecuta los siguientes comandos en la ventana de Cloud Shell:

Descarga el archivo YAML:

curl https://gist.githubusercontent.com/elithrar/1c511d00f5cd3736fb2a3897867209c1/raw/3cb70855304f29e5c06b8d63063196354db0dec3/media-edge-20210208-dashboard --output media-edge-20210208-dashboard.yaml

Crea el panel de Cloud Monitoring:

gcloud monitoring dashboards create --config-from-file media-edge-20210208-dashboard.yaml

La configuración puede tardar unos minutos. Ve a la consola de Google Cloud y haz clic en las 3 barras > Operaciones > Supervisión > Paneles. Deberías ver un panel llamado "Métricas de Edge de contenido multimedia". Haz clic en él y verás las métricas:

d0821d84a88a928d.png

18. Limpia el entorno del lab

Felicitaciones por completar el lab. En esta sección, borraremos todos los recursos que creamos a lo largo del lab.

Detén el indicador de FFmpeg:

Presiona <CTRL+C> en la terminal de Cloud Shell en la que se ejecuta FFmpeg.

Detener el canal de transmisión en vivo:

Comando

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d "" \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels/$CHANNEL_ID:stop"

Borra el canal de transmisión en vivo:

Comando

curl -X DELETE -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) "https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/channels/$CHANNEL_ID"

Borra el extremo de entrada de transmisión en vivo:

Comando

curl -X DELETE \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
"https://livestream.googleapis.com/v1/projects/$PROJECT_NUMBER/locations/$LOCATION/inputs/$INPUT_ID"

Borra el bucket de GCS:

Comando

gsutil rm -r gs://live-streaming-storage-$LOGNAME

Borra la instancia del servicio de caché perimetral:

Comando

gcloud edge-cache services delete cme-demo

Para confirmar la eliminación, ingresa "Y" cuando se te solicite.

Borra el origen de almacenamiento en caché perimetral:

Comando

gcloud edge-cache origins delete cme-origin

Para confirmar la eliminación, ingresa "Y" cuando se te solicite.

Cómo borrar el panel personalizado

Comando

gcloud monitoring dashboards delete $(gcloud monitoring dashboards list --filter="displayName:Media Edge Metrics" --format="value(name)")