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 del usuario almacenando en caché el contenido al que se accede con frecuencia más cerca de los usuarios finales, finalizando las conexiones más cerca de los clientes, reutilizando conexiones con el origen y mediante la adopción de personalizaciones y protocolos de red modernos. Para los usuarios (y nuestros clientes), esto significa una menor latencia, más confiabilidad y menos costos, lo que produce mejores ventas, experiencia web y un aumento neto en la experiencia del usuario. En la actualidad, muy pocos sitios y plataformas de transmisión de video por Internet modernos funcionan sin una CDN.

Qué aprenderás

Este lab 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) + Cloud Media Live Streaming API (transcodificación de video en vivo) + Cloud Storage (almacenamiento para los videos) + Reproductor de video (VLC, Google Shaka Player, etc., HLS + MPEG-DASH compatible con el reproductor).

Configuraremos los componentes de la API de Live Streaming - Input, Channel e iniciaremos 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 video en vivo de Cloud Storage como origen. Por último, se usará VLC Player 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 basado en la siguiente arquitectura:

de33cb3e75d52549.png

Configuraremos los siguientes componentes y realizaremos las siguientes tareas como parte del lab:

  • Crear 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
  • Cómo configurar FFmpeg para proporcionar información al 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, acierto de caché, error de caché, etcétera).

Nota: Para este lab, suponemos que los usuarios tienen acceso a la consola de Google Cloud y ya tienen una configuración de proyecto. 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 comprobar los componentes configurados a través de la línea de comandos en la consola. A lo largo del lab, veremos punteros que apuntará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. Ellos pueden crear una solicitud de acceso en tu nombre. Si formas parte de Google y deseas probar la transmisión en vivo con Media CDN, comunícate con el PM de Media CDN para solicitar acceso a Media CDN.

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

Al momento de la redacción, 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, pasa a la siguiente sección.
  2. Si la versión del SDK es anterior a 408.0.0, ejecuta el comando que se muestra a continuación para actualizar el SDK.
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

Durante 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

Estas variables de entorno generalmente están preconfiguradas en Cloud Shell. Usaremos el comando env para verificarlo.

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 estén configuradas 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 Media CDN Edge Cache

Habilita la API de servicios de red

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

Comando

gcloud services enable networkservices.googleapis.com

Habilitar 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 mostrar 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. Permita que el bucket sea accesible de forma pública

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

Comando

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

7. Configura el entorno de la API de Live Streaming

Los componentes de la cadena de API de Live Streaming tienen la siguiente arquitectura:

96b5d26aedeb89a6.png

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

  • Entrada de transmisión en vivo: Un extremo de entrada es aquel al que el codificador envía la transmisión de entrada. Puedes usar el extremo de entrada para especificar parámetros de configuración de tu transmisión, como la resolución, 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 en vivo a través de un extremo de entrada, la transcodifica en varios formatos y publica transmisiones en vivo de salida en ciertos formatos en la ubicación especificada. Puedes incluir una transmisión de entrada principal y una de respaldo en el mismo canal.

Crearemos los siguientes recursos más adelante en el lab:

  • Codificador: Un codificador es un programa que se usa para enviar transmisiones 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 indicador de transmisión en vivo. En este lab, usaremos la señal en vivo RTMP.

Comando

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

Crea el extremo de entrada

Al momento de escribir este lab, no hay asistencia de gcloud para la API de Live Stream. 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 anota el ID de operación. A continuación, se muestra el ID de operación del ejemplo del resultado. Se puede encontrar 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

Cómo consultar 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 ver. 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", lo que indica que el extremo de entrada se creó y está listo.

Guarda el URI

Usaremos el URI del resultado anterior más adelante en el lab. En este momento, vamos a configurar una variable de entorno para URI.

Comando

export URI=<uri>

Reemplaza <uri> por el URI que acabas de anotar. 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. Crear 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 de HLS que consta de una única representación en alta definición (1280 × 720). El canal se asociará con el extremo de entrada y con 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
}

Toma nota y copia el ID de operación. Lo necesitaremos en uno de los próximos pasos. Se puede encontrar en la línea de salida que comienza con "name".

Cómo consultar el estado

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

En el siguiente comando, reemplaza <OPERATION> por el ID de la operación que acabamos de ver. 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", lo que indica que el extremo de entrada se creó y está listo.

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

10. Inicia el canal de transmisión en vivo

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

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

1. Empieza 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 está activo y listo para recibir una señal.

11. Configurar Media CDN

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

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

1. Crea un origen de almacenamiento en caché perimetral

Un origen de almacenamiento en 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., todos los elementos de CSS, JavaScript, HTML, imágenes, etc. En este lab, crearemos un origen que se asigne al bucket de Cloud Storage que creamos al comienzo del lab. Llamaremos al origen de almacenamiento en caché perimetral cme-origin. En el origen de una CDN, se almacena todo el contenido de origen antes de distribuirlo a los servidores de caché perimetral.

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. Crea un servicio de almacenamiento en caché perimetral

Ahora que tenemos configurado un origen de 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 valores predeterminados de la configuración del servicio de almacenamiento en caché perimetral. En el archivo anterior, hay 3 valores de campo que los usuarios podrían querer actualizar:

  • name: Es el nombre de la instancia de Media CDN, aquí: cme-demo.
  • hosts: es la lista de nombres de dominio que resolverá este servicio de Media CDN, aquí: demo.cme.com. Lo usaremos durante esta demostración. Usaremos la dirección IP de la instancia de Media CDN.
  • Origin: es el origen de almacenamiento en caché perimetral que acabamos de crear en el paso anterior. Establécelo 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 almacenamiento en caché perimetral.

Crea el servicio de almacenamiento en caché perimetral

Crearemos un servicio de almacenamiento en caché perimetral llamado cme-demo, en el origen de 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 almacenamiento en caché perimetral 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'

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

Actualiza el servicio de almacenamiento en caché perimetral

En este punto, es una buena idea 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 o IP de hosts de los que el servicio de almacenamiento en caché perimetral aceptará las solicitudes. En este punto, solo especificamos demo.cme.com como host. Para proporcionar una resolución de nombres a este dominio, configura una zona del DNS en la nube. Sin embargo, una solución más fácil sería agregar la dirección IP a la lista de hosts en el archivo yaml. Vuelve a editar el archivo YAML y edítalo para que se vea de la siguiente manera:

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

Verifica el resultado del comando y comprueba 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 el indicador de entrada

Ahora que configuramos todos los servicios requeridos, generemos el indicador de entrada de la transmisión en vivo. En esta sección, haremos lo siguiente:

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

1. Instalar FFmpeg

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

Comando

sudo apt install ffmpeg -y

Cuando finalice la instalación, verificaremos la versión de FFmpeg que se instaló correctamente:

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 la señal de transmisión en vivo para 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 del URI que creamos en “Crea y configura el extremo de entrada”. sección.

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 en vivo de la prueba. El comando no mostrará el mensaje. La señal se generará hasta que la detengas. Deberás abrir una nueva ventana de Cloud Shell durante el resto del lab.

13. Abrir un nuevo 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>. el comando para detenerla y, así, detener la generación de la señal activa.

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 se acaba de abrir.

Configura las variables de entorno

Como se trata de un nuevo Cloud Shell, debemos configurar las variables de entorno nuevamente. Usaremos el comando source para configurar las variables de entorno.

Comando

source ~/env_variables.txt

Verifica que las variables estén configuradas

Verifiquemos que estén configuradas 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 una curl para describir el canal. Deberíamos ver en el resultado 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", que indica que el canal está transmitiendo y que se está transcodificando la señal en vivo.

También verifiquemos el contenido del bucket en el que deberíamos ver un archivo de manifiesto y varios segmentos de video de TS. Ejecuta el siguiente comando en Cloud Shell para enumerar el contenido del bucket que creamos al comienzo del lab y que usa la API de Live Streaming para generar el manifiesto de la señal en vivo transcodificada y los segmentos de video de 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 de HLS: main.m3u8
  • Los segmentos de video de 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 se 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 el origen de Media CDN.

En las próximas secciones, validaremos el servicio de almacenamiento en caché perimetral y, luego, transmitiremos el video transcodificado con la dirección IP anycast de Media CDN.

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

En esta sección, verificaremos que la instancia del servicio de almacenamiento en caché perimetral funcione como se espera. Para ello, intentaremos acceder a un archivo desde la instancia del servicio de almacenamiento en caché perimetral con la dirección IP de este servicio. La primera vez que se accede a un objeto, aún no se almacena en caché. Deberíamos observar un MISS de caché. En la primera solicitud, el objeto se lee desde el origen y se almacena en caché en el perímetro. Todos los siguientes intentos para acceder al mismo archivo mostrarán una HIT de caché, ya que el objeto ahora se almacena en caché en el perímetro. Comprobemos 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 almacenamiento en caché perimetral:

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. Usa demo.cme.com:<IP>, en el que la 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 que la caché falta, ya que el objeto aún no se almacenó en caché y se lee desde el origen.

Ahora haremos varias solicitudes para el archivo m3u8 y, si todo está configurado correctamente, Media CDN debería comenzar a entregar el contenido desde su caché. El siguiente comando realizará 10 solicitudes 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 caché. Si ves aciertos de caché en el resultado, significa que Media CDN funciona como se esperaba.

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 hit de la caché, ya que el objeto ahora está almacenado en caché en el perímetro. El servicio de Cloud Medie Edge funciona según lo previsto.

16. Transmite videos de señales en vivo transcodificadas con VLC

Esta es la parte en la que unimos 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 al contenido HLS por la API de transmisión en vivo.
  • Configuramos la API de Live Streaming.
  • Iniciamos una señal en vivo RTMP con FFmpeg que alimenta la entrada/canal de la API de Live Streaming.
  • Verificamos que la señal en vivo se envió al canal y verificamos que este esté en modo streaming.
  • Verificamos que los archivos transcodificados resultantes (manifiesto + segmentos de TS) se generaron y se almacenaron en el bucket live-streaming-storage-$LOGNAME.
  • Se configuró un origen de almacenamiento en caché perimetral llamado cme-origin con el bucket de GCS live-streaming-storage-$LOGNAME como origen.
  • Se configuró una instancia de almacenamiento en caché perimetral llamada cme-demo con cme-origin como su origen.
  • Verificamos el comportamiento (error 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 la señal en vivo transcodificada a través de la caché de Media CDN. Para ello, usaremos el reproductor VLC. VLC Player es un reproductor multimedia y un framework de código abierto, gratuito y multiplataforma que reproduce la mayoría de los archivos multimedia. Reproduce formatos multimedia adaptables (como DASH y HLS). Usa el principio de transmisión adaptable: El reproductor adaptará la calidad de video de reproducción según la calidad de tu conexión de red y el ancho de banda disponible. Con el trabajo de transcodificación que acabamos de hacer, usamos los ajustes predeterminados y generamos dos cualidades "únicamente": SD y HD. Cuando empecemos a reproducir el video en el reproductor, deberías ver que empieza 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 HLS (formato de video ampliamente compatible de Apple). El archivo correspondiente se llama main.m3u8, que es el manifiesto de HLS. El manifiesto dirige a los segmentos de video de TS.

Para usar el reproductor VLC, visita 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, iOS y Android.

2a2d19abe728d222.png

Instala el reproductor en tu laptop e inícialo. En los próximos pasos, usaremos la versión MacOSX del reproductor.

Para reproducir un video, ve a "Archivo" /"Red abierta":

f85565301f7c68dc.png

Configúralo con lo siguiente:

  • URL: http://&lt;Replace_With_Edge_Cache_IP&gt;/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. Reemplázala por la IP del servicio multimedia de Cloud que implementaste.
  • La ruta de acceso al archivo de video de manifiesto: "/". Esta es la ruta que usamos en el bucket live-streaming-storage-$LOGNAME para almacenar los archivos de indicadores en vivo transcodificados. La ruta es la ruta raíz aquí: “/”.
  • El nombre del archivo de video de manifiesto: el archivo de manifiesto de HLS, main.m3u8.

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

Es una señal en vivo de prueba RTMP básica generada por FFmpeg, transcodificada a HLS por la API de transmisión en vivo y entregada 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 debes tener en cuenta:

  • Reproductor Quicktime: instalado de forma predeterminada en Mac. Lo mismo ocurre 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 de servicio de almacenamiento en caché perimetral).

17. Supervisa Media CDN

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

Para instalarla, 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 para 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 de control. Deberías ver un panel llamado "Media Edge Metrics". Haz clic en él para ver 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 la señal FFmpeg:

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

Detén 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"

Sigue estos pasos para borrar 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 almacenamiento en caché perimetral:

Comando

gcloud edge-cache services delete cme-demo

Ingresa “Y” para confirmar la eliminación. Cuando se te solicite,

Borra el origen del almacenamiento en caché perimetral:

Comando

gcloud edge-cache origins delete cme-origin

Ingresa “Y” para confirmar la eliminación. 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)")