Transmissão ao vivo no Google Cloud com Media CDN e API Live Streaming

1. Introdução

As redes de fornecimento de conteúdo (CDNs) melhoram a performance do usuário armazenando em cache o conteúdo acessado com frequência mais perto dos usuários finais, encerrando as conexões mais perto dos clientes, reutilizando as conexões com a origem e adotando protocolos e personalizações de rede modernos. Para os usuários (e nossos clientes), isso significa menor latência, mais confiabilidade e custo reduzido, o que leva a um aumento nas vendas, na experiência da Web e um aumento líquido na experiência do usuário. Hoje em dia, poucos sites modernos e plataformas de streaming de vídeo operam sem uma CDN.

O que você vai aprender

Este laboratório vai orientar você pelas etapas de implantação de um ambiente de fluxo de trabalho de transmissão ao vivo com Media CDN (CDN) + API Cloud Media Live Streaming (transcodificação de vídeo ao vivo) + Cloud Storage (armazenamento para os vídeos) + Player de vídeo (VLC, Google Shaka Player etc. - player pronto para HLS + MPEG-DASH).

Vamos configurar os componentes da API Live Streaming (entrada e canal) e iniciar um feed publicado para a entrada/canal com o FFmpeg, que pode gerar um sinal de teste em tempo real. A API Live Streaming vai transcodificar o feed publicado. O manifesto e os segmentos de vídeo transcodificados serão armazenados em um bucket do Cloud Storage. Em seguida, vamos configurar o Media CDN com o bucket do Cloud Storage de vídeo ao vivo como origem. Por fim, o VLC Player será usado para reproduzir conteúdo ao vivo armazenado em cache pela Media CDN. Também vamos configurar um painel do Cloud Monitoring para visualizar a atividade da CDN de mídia.

O que você vai criar

Neste laboratório, vamos configurar o ambiente com base na seguinte arquitetura:

de33cb3e75d52549.png

Vamos configurar os seguintes componentes e realizar as seguintes tarefas como parte do laboratório:

  • Crie um bucket do Google Cloud Storage (GCS) para armazenar os vídeos transcodificados ao vivo.
  • Configure a API Live Streaming para transcodificar o vídeo em vários formatos: HLS + MPEG DASH, SD e HD
  • Configurar os componentes de transmissão ao vivo: entrada/canal
  • Iniciar o canal de transmissão ao vivo
  • Configurar a Media CDN com o bucket do GCS como origem
  • Configurar o FFmpeg para alimentar o canal ao vivo
  • Transmitir o feed publicado transcodificado com um player de vídeo
  • Configure um painel do Cloud Monitoring para monitorar a atividade do Media CDN (latência, ocorrência em cache, ausência no cache etc.).

Observação: para este laboratório, presumimos que os usuários têm acesso ao console do Google Cloud e já têm um projeto configurado. Também presumimos que os usuários começam com um ambiente novo e não têm nada configurado para esta demonstração.

Todas as ações de configuração serão feitas pela linha de comando no Cloud Shell. É possível verificar os componentes configurados pela linha de comando no console. Ao longo do laboratório, você vai encontrar indicadores que apontam para o console do Google Cloud.

2. Antes de começar

O acesso à CDN de mídia é restrito. Para ter acesso à Media CDN, entre em contato com a equipe de conta. Ela pode criar uma solicitação de acesso em seu nome. Se você faz parte do Google e quer testar a transmissão ao vivo com o Media CDN, entre em contato com o gerente de produtos do Media CDN para solicitar acesso.

3. Configuração e requisitos

Inicie o Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

No Console do Google Cloud, clique no ícone do Cloud Shell na barra de ferramentas superior à direita:

55efc1aaa7a4d3ad.png

O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:

7ffe5cbb04455448.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Neste codelab, todo o trabalho pode ser feito com um navegador. Você não precisa instalar nada.

4. Versão do SDK Google Cloud

No momento da redação deste artigo, 408.0.0 é a versão mais recente do SDK do Google Cloud. Todos os comandos deste laboratório foram testados usando a versão mais recente do SDK Google Cloud. Antes de continuar, verifique se o Cloud Shell está usando a versão mais recente do SDK.

Verificar a versão do SDK

Vamos usar o comando gcloud version para verificar a versão do SDK.

Comando

gcloud version | grep "Google Cloud SDK"

Exemplo de saída

Google Cloud SDK 408.0.0

Próximas etapas

  1. Se a versão do SDK for 408.0.0 ou mais recente, avance para a próxima seção.
  2. Se a versão do SDK for inferior a 408.0.0, execute o comando listado abaixo para atualizar o SDK.
sudo apt-get update && sudo apt-get install google-cloud-sdk

5. Pré-requisitos

Antes de começar a configurar os recursos do GCP, faça o seguinte:

  1. Configurar as variáveis de ambiente.
  2. Ativar as APIs de serviço necessárias

1. Configurar variáveis de ambiente

Neste laboratório, vamos executar comandos gcloud e curl com algumas variáveis. Precisamos configurar as seguintes variáveis de ambiente.

  • ID do projeto
  • Número do projeto
  • Nome do usuário
  • Região
  • ID da entrada
  • ID do canal

ID do projeto e nome de usuário

Essas variáveis de ambiente geralmente são pré-configuradas no Cloud Shell. Vamos usar o comando env para verificar.

Comando

env | grep -E 'DEVSHELL_PROJECT_ID=|LOGNAME'

Exemplo de saída

DEVSHELL_PROJECT_ID=<YOUR_PROJECT_ID>
LOGNAME=<YOUR_USERNAME>

Criar o arquivo env_variables

Use o comando cat para criar o arquivo env_variables.txt. O comando abaixo vai criar o arquivo env_variables.txt no diretório inicial do usuário.

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

Configurar as variáveis de ambiente

Vamos usar o comando source para definir as variáveis de ambiente.

Comando

source ~/env_variables.txt

Verificar se as variáveis estão definidas

Vamos verificar se todas as variáveis de ambiente necessárias estão definidas. Vamos ver um total de seis variáveis de ambiente na saída.

Comando

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

Exemplo de saída

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. Ativar as APIs de serviço necessárias

Precisamos garantir que as seguintes APIs estejam ativadas no nosso projeto.

  • API Network Services
  • API Certificate Manager
  • API Livestream
  • API Media CDN Edge Cache

Ativar a API Network Services

Para ativar a API Network Services, execute o seguinte comando:

Comando

gcloud services enable networkservices.googleapis.com

Ativar a API Certificate Manager

Para ativar a API Certificate Manager, execute o seguinte comando:

Comando

gcloud services enable certificatemanager.googleapis.com

Ativar a API Live Stream

Para ativar a API Live Stream, execute o seguinte comando:

Comando

gcloud services enable livestream.googleapis.com

Ativar a API Media CDN Edge Cache

Para ativar a API Media CDN Edge Cache, execute o seguinte comando:

Comando

gcloud services enable edgecache.googleapis.com

Verificar se as APIs estão ativadas

Execute o comando gcloud services list para listar todas as APIs ativadas. A saída vai mostrar quatro APIs.

Comando

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

Exemplo de saída

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

6. Criar o bucket do Cloud Storage

Nesta seção, vamos fazer o seguinte:

  1. Criar um bucket do Cloud Storage
  2. Torne o bucket acessível publicamente

Mais adiante no laboratório, vamos usar esse bucket para armazenar os arquivos de vídeo transcodificados. Esse bucket também vai atuar como um armazenamento de origem para o serviço Media CDN.

1. Criar o bucket

Vamos usar o comando gsutil mb para criar o bucket:

Comando

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

2. Tornar o bucket acessível publicamente

Vamos usar o comando gsutil iam para disponibilizar os arquivos publicamente:

Comando

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

7. Como configurar o ambiente da API Live Streaming

Os componentes da cadeia da API Live Streaming são arquitetados da seguinte maneira:

96b5d26aedeb89a6.png

Criamos o bucket do Cloud Storage live-streaming-storage-$LOGNAME na seção anterior. Nas próximas duas seções, vamos criar os seguintes recursos:

  • Entrada de transmissão ao vivo:um endpoint de entrada é um endpoint para o qual o codificador envia o fluxo de entrada. É possível usar o endpoint de entrada para especificar configurações da sua transmissão, como resolução, tipo de entrada e corte de vídeo.
  • Canal de transmissão ao vivo:um canal é um recurso que ingere o stream de entrada por um endpoint de entrada, transcodifica o stream de entrada em várias renderizações e publica transmissões ao vivo de saída em determinados formatos no local especificado. É possível incluir um stream de entrada principal e um de backup no mesmo canal.

Vamos criar os seguintes recursos mais tarde no laboratório:

  • Codificador:um programa usado para enviar fluxos de entrada. Neste laboratório, vamos usar o FFmpeg.

8. Criar e configurar o endpoint de entrada

Criar o arquivo input.json

Vamos criar um arquivo input.json para especificar o tipo de sinal de transmissão ao vivo. Neste laboratório, usamos o sinal de transmissão ao vivo RTMP.

Comando

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

Criar o endpoint de entrada

No momento em que este laboratório foi escrito, não há suporte do gcloud para a API Live Stream. Vamos usar o comando curl para fazer as chamadas de 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"

Exemplo de saída

{
  "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
}

A saída tem muitas informações úteis, mas, no momento, precisamos focar em dois campos:

  • ID da operação:na saída, copie e anote o ID da operação. Confira abaixo o ID da operação no exemplo de saída. Isso pode ser encontrado na linha de saída que começa com "name". "operation-1661405972853-5e70a38d6f27f-79100d00-310671b4"
  • Status:aguarde a mudança do status de "done": false para "done": true.

Verificar o status

Antes de prosseguir, precisamos verificar se o endpoint de entrada foi criado e está pronto.

No comando abaixo, substitua <OPERATION> pelo ID da operação que acabamos de receber acima. Neste exemplo, é "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"

Exemplo de saída

{
  "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"
  }
}

Execute o comando novamente até ver "done:true", indicando que o endpoint de entrada foi criado e está pronto.

Salvar o URI

Vamos usar o URI da saída anterior mais adiante no laboratório. Agora, vamos definir uma variável de ambiente para o URI.

Comando

export URI=<uri>

Substitua <uri> pelo URI que você anotou acima. Se quiser, use o método GET para recuperar o 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. Criar e configurar o canal de transmissão ao vivo

Vamos criar o canal de transmissão ao vivo associado ao endpoint de entrada que criamos na seção anterior. O exemplo a seguir cria um canal que gera uma transmissão ao vivo HLS com uma única renderização de alta definição (1280x720). O canal será associado ao endpoint de entrada e ao bucket de armazenamento que criamos anteriormente.

Criar o arquivo channel.json

No terminal do Cloud Shell, digite o seguinte comando para criar um arquivo "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

Criar o canal

Execute o seguinte comando curl para criar o 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"

Exemplo de saída

{
  "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
}

Anote e copie o ID da operação. Vamos precisar dele em uma das próximas etapas. Isso pode ser encontrado na linha de saída que começa com "name".

Verificar o status

Antes de prosseguir, precisamos verificar se o canal foi criado e está pronto.

No comando abaixo, substitua <OPERATION> pelo ID da operação que acabamos de receber acima. Neste exemplo, é 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"

Exemplo de saída

  "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"
    }
  }
}

Execute o comando novamente até ver "done:true", indicando que o endpoint de entrada foi criado e está pronto.

No momento, o "streamingState" é "STOPPED". Vamos iniciar o canal na próxima seção.

10. Iniciar o canal de transmissão ao vivo

Agora que criamos nosso canal de transmissão ao vivo, vamos iniciá-lo. Nesta seção, vamos fazer o seguinte:

  1. Iniciar o canal de transmissão ao vivo
  2. Verifique o status do canal para garantir que o streamingState seja "AWAITING INPUT".

1. Iniciar o canal

No Cloud Shell, execute o seguinte comando curl para iniciar o 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"

Exemplo de saída

{
  "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. Verificar o status do canal

Execute o comando curl a seguir para conferir o status do 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"

Exemplo de saída

"streamingState": "AWAITING_INPUT",

Execute o comando novamente até ver "AWAITING_INPUT", indicando que o canal está em execução e pronto para receber um sinal.

11. Configurar o Media CDN

Nesta seção, vamos implantar a Media CDN, a infraestrutura de CDN. Vamos criar os seguintes recursos:

  1. Origem do armazenamento em cache de borda
  2. Serviço de armazenamento em cache de borda

1. Criar uma origem do armazenamento em cache de borda

Uma origem do armazenamento em cache de borda representa um local de conteúdo, como um bucket do Cloud Storage, um local de armazenamento de terceiros ou um balanceador de carga. Em termos de CDN, a origem (ou servidor de origem) é o local onde está a fonte do conteúdo que queremos distribuir, por exemplo, todos os CSS, JavaScripts, HTML, imagens etc. Para este laboratório, vamos criar uma origem que mapeia para o bucket do Cloud Storage criado no início do laboratório. Vamos chamar a origem do armazenamento em cache de borda de cme-origin. A origem de uma CDN é onde todo o conteúdo de origem é armazenado antes de ser distribuído para os servidores de cache de borda.

Vamos usar o comando gcloud edge-cache origins create para criar a origem. A execução do comando leva alguns minutos.

Comando

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

Exemplo de resposta

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. Criar um serviço de armazenamento em cache de borda

Agora que temos uma origem do armazenamento em cache de borda configurada, podemos criar o serviço de cache próximo dos usuários finais.

Crie o arquivo cme-demo.yaml.

As configurações do serviço de cache de borda são feitas por um arquivo YAML. No Cloud Shell, crie um arquivo local chamado cme-demo.yaml. Use vi, nano ou qualquer outro editor e cole as seguintes linhas no arquivo 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

Vamos deixar todos os padrões de configurações de serviço do Edge Cache Service. No arquivo acima, há três valores de campo que os usuários podem querer atualizar:

  • name: o nome da instância do Media CDN. Aqui: cme-demo
  • hosts: a lista de nomes de domínio que serão resolvidos por este serviço do Media CDN. Aqui: demo.cme.com. Vamos usar isso durante esta demonstração. Vamos usar o endereço IP da instância do Media CDN.
  • Origin:: é a origem do armazenamento em cache de borda que acabamos de criar na etapa anterior. Defina como cme-origin, o nome da origem da CDN de mídia.

Para mais informações sobre as diferentes variáveis que podem ser usadas no arquivo YAML, consulte o guia de configurações de serviço do Edge Cache Service.

Criar o serviço de cache próximo dos usuários finais

Vamos criar um serviço de cache de borda chamado cme-demo na origem do armazenamento em cache de borda cme-origin com o host demo.cme.com. Para criar o serviço, execute o seguinte comando no Cloud Shell:

Comando

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

A criação do serviço de cache de borda pode levar alguns minutos.

Exemplo de saída

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'

Anote e copie o ipv4Addresses da instância do serviço de cache próximo dos usuários finais. Aqui, 34.104.36.157. Vamos usá-lo para atualizar o arquivo cme-demo.yaml e, mais tarde, para transmitir o vídeo transcodificado.

Atualizar o serviço de armazenamento em cache de borda

Neste ponto, é recomendável atualizar as configurações de serviço do Edge Cache Service para usar o IP do serviço e transmitir o vídeo mais tarde. O arquivo YAML do serviço de armazenamento em cache próximo dos usuários finais permite listar todos os nomes de hosts/IPs de que o serviço aceitará solicitações. Neste momento, especificamos apenas demo.cme.com como host. Para fornecer resolução de nome para esse domínio, configure uma zona de DNS. No entanto, uma solução mais fácil seria adicionar o endereço IP à lista de hosts no arquivo yaml. Edite o arquivo YAML novamente para que ele fique assim:

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 refletir as mudanças, basta reimportar o arquivo YAML. No terminal do Cloud Shell, execute o comando a seguir:

Comando

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

Verifique a saída do comando e confira se o IP aparece na lista de hosts.

Nesse ponto, a instância do serviço de cache de borda aceitará solicitações com "demo.cme.com" ou o endereço IP como host.

12. Gerar o indicador de entrada

Agora que configuramos todos os serviços necessários, vamos gerar o sinal de entrada da transmissão ao vivo. Nesta seção, vamos fazer o seguinte:

  1. Instale o FFmpeg, um software livre de código aberto
  2. Enviar um sinal de teste em tempo real para a entrada/canal

1. Instalar o FFmpeg

O FFmpeg é um projeto de software sem custo financeiro e de código aberto que consiste em um conjunto de bibliotecas e programas para processar vídeos, áudios e outros arquivos e streams multimídia. No terminal do Cloud Shell, use o comando a seguir para instalar o FFmpeg:

Comando

sudo apt install ffmpeg -y

Quando a instalação for concluída, verifique se o FFmpeg foi instalado corretamente conferindo a versão:

Comando

ffmpeg -version

Exemplo de saída

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

O FFmpeg foi instalado corretamente.

2. Inicie o Live Stream Signal to the Input/Channel (Sinal de transmissão ao vivo para a entrada/canal).

Agora que o FFmpeg está instalado, vamos enviar um stream de entrada de teste para o endpoint de entrada e gerar a transmissão ao vivo.

No terminal do Cloud Shell, execute o comando a seguir usando a variável de ambiente URI que criamos na seção "Criar e configurar o endpoint de entrada".

Comando

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

O FFmpeg vai enviar o sinal de teste ao vivo. O comando não vai retornar o aviso. O indicador será gerado até que você o interrompa. Você precisará abrir uma nova janela do Cloud Shell para o restante do laboratório.

13. Abrir o novo Cloud Shell

Neste ponto, você precisará abrir uma nova janela do Cloud Shell para continuar o laboratório, já que o FFmpeg será executado permanentemente até que você pressione <CTRL+C> para interromper o comando e, assim, interromper a geração de sinal ao vivo.

Clique no sinal de "+" ao lado do nome do terminal atual do Cloud Shell. Isso vai abrir outra janela do Cloud Shell.

b3c7b0be6276c194.png

Execute o restante do laboratório na janela do Cloud Shell que acabou de ser aberta.

Configurar as variáveis de ambiente

Como este é um novo Cloud Shell, precisamos definir as variáveis de ambiente novamente. Vamos usar o comando source para definir as variáveis de ambiente.

Comando

source ~/env_variables.txt

Verificar se as variáveis estão definidas

Vamos verificar se todas as variáveis de ambiente necessárias estão definidas. Vamos ver um total de seis variáveis de ambiente na saída.

Comando

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

Exemplo de saída

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. Verificar se o sinal ao vivo está sendo transcodificado

Vamos executar um curl para descrever o canal. Na saída, vamos ver que o streamingState mudou de "AWAITING_INPUT" para "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"

Na resposta do arquivo JSON de saída, você vai encontrar "streamingState": "STREAMING", indicando que o canal está transmitindo e o sinal ao vivo está sendo transcodificado.

Vamos também verificar o conteúdo do bucket, onde um arquivo de manifesto e vários segmentos de vídeo TS devem aparecer. Execute o comando a seguir no Cloud Shell para listar o conteúdo do bucket que criamos no início do laboratório e que é usado pela API Live Streaming para gerar o manifesto do sinal ao vivo transcodificado e os segmentos de vídeo TS:

Comando

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

Exemplo de saída

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
...

Você verá:

  • o arquivo de manifesto HLS: main.m3u8
  • Os segmentos de vídeo TS correspondentes: uma série de arquivos numerados segment-000000000X.ts

Neste ponto, já concluímos o seguinte:

  • API Live Streaming: o sinal ao vivo é gerado e transcodificado em um bucket pela API Live Streaming.
  • Media CDN: configuramos o Media CDN com o bucket de armazenamento do Live Streaming como origem do Media CDN.

Nas próximas seções, vamos validar o serviço de cache de borda e transmitir o vídeo transcodificado usando o endereço IP anycast da Media CDN.

15. Verificar se a instância do serviço de cache de borda funciona

Nesta seção, vamos verificar se a instância do serviço de cache de borda funciona conforme o esperado. Para isso, vamos tentar acessar um arquivo da instância do serviço de cache próximo dos usuários finais usando o endereço IP do serviço de cache próximo dos usuários finais. Na primeira vez que um objeto é acessado, ele ainda não está em cache. Vamos observar um cache MISS. Na primeira solicitação, o objeto é lido da origem e armazenado em cache na borda. Todas as tentativas a seguir de acessar o mesmo arquivo vão retornar um cache HIT, já que o objeto agora está em cache na borda. Vamos verificar esse comportamento:

Execute o seguinte comando curl no Cloud Shell para acessar o arquivo de manifesto de vídeo transcodificado armazenado na origem do armazenamento em cache de borda:

Comando

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

Observe a resolução em que usamos o endereço IP da instância do serviço de cache de borda para resolver o nome dela. Use demo.cme.com:<IP>, em que IP é o IP da instância do serviço de armazenamento em cache de borda que acabamos de criar.

Procure o cabeçalho x-cache-status na saída.

Exemplo de saída

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

Observe a falha de cache, já que o objeto ainda não foi armazenado em cache e é lido da origem.

Agora vamos fazer várias solicitações para o arquivo m3u8. Se tudo estiver configurado corretamente, a Media CDN vai começar a veicular o conteúdo do cache. O comando abaixo fará 10 solicitações curl e vai imprimir apenas o cabeçalho 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

A saída precisa ser uma combinação de cache hit e miss. Se você encontrar acertos de cache na saída, o Media CDN está funcionando conforme o esperado.

Exemplo de saída

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

Observe o acerto de cache, já que o objeto agora está armazenado em cache na borda. O serviço Cloud Media Edge está funcionando conforme o esperado.

16. Fazer streaming de vídeo de sinal ao vivo transcodificado com o VLC

Esta é a parte em que conectamos os pontos e vinculamos todas as etapas em que trabalhamos até agora:

  • Criamos um bucket chamado live-streaming-storage-$LOGNAME que recebe o resultado do sinal ao vivo transcodificado para conteúdo HLS pela API Live Streaming.
  • Configuramos a API Live Streaming.
  • Iniciamos um sinal RTMP ao vivo com o FFmpeg que alimenta a entrada/canal da API Live Streaming.
  • Verificamos que o sinal ao vivo foi enviado ao canal e que ele estava no modo streaming.
  • Verificamos se os arquivos transcodificados resultantes (manifesto + segmentos TS) foram gerados e armazenados no bucket live-streaming-storage-$LOGNAME.
  • Uma origem do armazenamento em cache de borda chamada cme-origin foi configurada com o bucket do GCS live-streaming-storage-$LOGNAME como origem.
  • Uma instância do Edge Cache chamada cme-demo foi configurada com cme-origin como origem.
  • Verificamos o comportamento (ausência no cache, ocorrência em cache) da instância do serviço de armazenamento em cache de borda.

Agora podemos usar um player de vídeo para transmitir o sinal ao vivo transcodificado pelo cache da Media CDN. Para isso, vamos usar o VLC Player. O VLC Player é um player e framework multimídia multiplataforma sem custo financeiro e de código aberto que reproduz a maioria dos arquivos multimídia. Ele reproduz formatos de mídia adaptáveis, como DASH e HLS. Ele usa o princípio do streaming adaptável. De acordo com a qualidade da sua conexão de rede e a largura de banda disponível, o player adapta a qualidade do vídeo reproduzido. No job de transcodificação que acabamos de fazer, usamos as predefinições padrão e geramos "apenas" duas qualidades: SD e HD. Quando o vídeo começar a ser reproduzido no player, ele vai começar no formato SD e mudar rapidamente para HD se a conexão de rede for boa o suficiente.

Vamos transmitir o sinal ao vivo transcodificado em HLS, um formato de vídeo da Apple amplamente aceito. O arquivo correspondente é chamado de main.m3u8, que é o manifesto HLS. O manifesto aponta para os segmentos de vídeo TS.

Para usar o VLC Player, acesse https://www.videolan.org/vlc/ e faça o download de uma versão do player para o sistema operacional do seu laptop. O VLC está disponível para Windows, MacOSX, Linux, Android e iOS.

2a2d19abe728d222.png

Instale e inicie o Player no seu laptop. Vamos usar a versão MacOSX do player nas próximas etapas.

Para reproduzir um vídeo, acesse "Arquivo" / "Abrir rede":

f85565301f7c68dc.png

Configure com:

  • URL: http://<Replace_With_Edge_Cache_IP>/main.m3u8. Esse é o URL do vídeo que queremos transmitir. Aviso:
  • O IP da instância do Media CDN: 34.105.35.246. Substitua pelo IP do Cloud Media Service implantado.
  • O caminho para o arquivo de vídeo de manifesto: "/". Esse é o caminho que usamos no bucket live-streaming-storage-$LOGNAME para armazenar os arquivos de sinal ao vivo transcodificados. O caminho é o caminho raiz aqui: "/".
  • O nome do arquivo de vídeo de manifesto: o arquivo de manifesto HLS, main.m3u8.

e clique em "Abrir". O vídeo ao vivo transcodificado vai começar a ser reproduzido. O vídeo vai ficar parecido com a captura de tela abaixo. O contador na tela vai aumentar em incrementos de 1, e você vai ouvir um bipe contínuo.

É um sinal básico de teste ao vivo RTMP gerado pelo FFmpeg, transcodificado para HLS pela API Live Streaming e veiculado pelo cache do Media CDN:

28fc359b49d44ec2.png

Você pode usar qualquer outro player HLS e MPEG DASH, se quiser. Confira algumas opções:

  • Quicktime Player: instalado por padrão em Macs. Faça o mesmo: abra uma conexão de rede com http://34.104.36.157/main.m3u8. Substitua o endereço IP pelo da sua instância do serviço de cache do Edge.

17. Monitorar o Media CDN

A equipe de PMEs criou um modelo de painel do Media CDN: https://gist.github.com/elithrar/1c511d00f5cd3736fb2a3897867209c1.

Para instalar, execute os seguintes comandos na janela do Cloud Shell:

Faça o download do arquivo YAML:

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

Crie o painel do Cloud Monitoring:

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

A configuração pode levar alguns minutos. Acesse o console do Google Cloud e clique nas três barras > Operações > Monitoramento > Painéis. Um painel chamado "Métricas do Media Edge" vai aparecer. Clique nele para ver as métricas:

d0821d84a88a928d.png

18. Limpar o ambiente do laboratório

Parabéns por concluir o laboratório. Nesta seção, vamos excluir todos os recursos criados ao longo do laboratório.

Parar o indicador do FFmpeg:

Pressione <CTRL+C> no terminal do Cloud Shell em que o FFmpeg está sendo executado.

Parar o canal de transmissão ao 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"

Exclua o canal de transmissão ao 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"

Exclua o endpoint de entrada da transmissão ao 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"

Exclua o bucket do GCS:

Comando

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

Exclua a instância do serviço de armazenamento em cache próximo dos usuários finais:

Comando

gcloud edge-cache services delete cme-demo

Confirme a exclusão digitando "Y" quando solicitado.

Exclua a origem do armazenamento em cache de borda:

Comando

gcloud edge-cache origins delete cme-origin

Confirme a exclusão digitando "Y" quando solicitado.

Excluir o painel personalizado

Comando

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