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 o desempenho do usuário armazenando em cache o conteúdo acessado com frequência mais perto dos usuários finais, encerrando conexões mais próximas aos clientes, reutilizando conexões à origem e pela adoção de personalizações e protocolos de rede modernos. Para os usuários (e nossos clientes), isso significa latência menor, mais confiabilidade e custos reduzidos, melhorando as vendas, a experiência na Web e o aumento líquido na experiência do usuário. Poucos sites modernos e plataformas de streaming de vídeo operam sem CDN hoje em dia.

O que você vai aprender

Neste laboratório, vamos apresentar as etapas para implantar 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 dos vídeos) + Player de vídeo (VLC, Google Shaka Player etc.: player pronto para HLS + MPEG-DASH).

Configuraremos os componentes da API de transmissão ao vivo - Entrada, Canal - e iniciaremos um feed ao vivo para a Entrada/Canal com o FFmpeg (o FFmpeg pode gerar um sinal de teste em tempo real). A API Live Streaming transcodificará o feed ao vivo. O manifesto e os segmentos do vídeo transcodificado serão armazenados em um bucket do Cloud Storage. Depois 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 pelo Media CDN. Também vamos configurar um painel do Cloud Monitoring para visualizar a atividade do Media CDN.

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:

  • Criar um bucket do Google Cloud Storage (GCS) para armazenar os vídeos transcodificados em tempo real
  • 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
  • Crie seu canal de transmissão ao vivo
  • Configure o Media CDN com o bucket do GCS como origem
  • Configurar o FFmpeg para alimentar o canal ao vivo
  • Fazer streaming do feed ao vivo transcodificado com um player de vídeo
  • Configurar 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: neste laboratório, presumimos que os usuários tenham acesso ao console do Google Cloud e já tenham uma configuração de projeto. Também presumimos que os usuários começam com um ambiente novo e não têm nenhuma configuração para esta demonstração.

Todas as ações de configuração serão feitas na linha de comando do Cloud Shell. É possível verificar os componentes configurados pela linha de comando no console. Durante o laboratório, serão exibidos dicas para o console do Google Cloud.

2. Antes de começar

O acesso ao Media CDN é restrito. Para ter acesso ao Media CDN, entre em contato com sua equipe de conta. Ele 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 PM do Media CDN para solicitar acesso ao Media CDN.

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 em que este artigo foi escrito, 408.0.0 é a versão mais recente do SDK do Google Cloud. Todos os comandos deste laboratório foram testados com 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.

Como 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, pule para a próxima seção.
  2. Se a versão do SDK for anterior à 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 configurar os recursos do GCP, é preciso fazer 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 os comandos gcloud e curl com algumas variáveis. Precisamos configurar as variáveis de ambiente a seguir.

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

ID do projeto e nome de usuário

Em geral, essas variáveis de ambiente são pré-configuradas no Cloud Shell. Usaremos o comando env para fazer a verificação.

Comando

env | grep -E 'DEVSHELL_PROJECT_ID=|LOGNAME'

Exemplo de saída

DEVSHELL_PROJECT_ID=<YOUR_PROJECT_ID>
LOGNAME=<YOUR_USERNAME>

Crie 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

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

Comando

source ~/env_variables.txt

Verificar se as variáveis estão definidas

Verifique se todas as variáveis de ambiente necessárias foram definidas. A saída vai ter seis variáveis de ambiente.

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 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. Serão exibidas quatro APIs na saída.

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. Crie o bucket do Cloud Storage

Nesta seção, faremos 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 atuará como um armazenamento de origem para o serviço Media CDN.

1. Criar o bucket

Usaremos o comando gsutil mb para criar o bucket:

Comando

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

2. Torne o bucket acessível publicamente

Vamos usar o comando iam do gsutil 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

A arquitetura dos componentes da cadeia da API Live Streaming é a seguinte:

96b5d26aedeb89a6.png

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

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

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

  • Codificador:um codificador é um programa usado para enviar streams de entrada. Neste laboratório, usaremos 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 indicador da transmissão ao vivo. Neste laboratório, usaremos o sinal RTMP em tempo real.

Comando

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

Criar o endpoint de entrada

No momento da criação deste laboratório, o gcloud não é compatível com a API Live Stream. Usaremos 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 contém muitas informações úteis, mas, no momento, precisamos nos concentrar 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 do exemplo de saída. Isso pode ser encontrado na linha de saída que começa com "name". "operation-1661405972853-5e70a38d6f27f-79100d00-310671b4"
  • Status:precisamos esperar o status mudar 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 executar. 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. Também é possível usar 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 de HLS que consiste em uma única execução em alta definição (1280 x 720). 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. Precisaremos 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 continuar, precisamos verificar se o canal foi criado e se está pronto.

No comando abaixo, substitua <OPERATION> pelo ID da operação que acabamos de executar. 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.

O "streamingState" no momento é "STOPPED". iniciaremos o canal na próxima seção.

10. Crie um canal de transmissão ao vivo

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

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

1. Inicie 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 seguinte comando curl para ver 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 o Media CDN: a infraestrutura do CDN. Criaremos os seguintes recursos:

  1. Origem do armazenamento em cache próximo dos usuários finais
  2. Serviço de armazenamento em cache de borda

1. Criar uma origem de armazenamento em cache próximo dos usuários finais

Uma origem de armazenamento em cache próximo dos usuários finais representa um local do 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á localizada a fonte do conteúdo que queremos distribuir. Por exemplo, CSS, JavaScript, HTML, imagens etc. Neste laboratório, vamos criar uma origem que é associada ao bucket do Cloud Storage que criamos no início. Chamaremos a origem do armazenamento em cache próximo dos usuários finais 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. O comando vai levar alguns minutos para ser concluído.

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 de armazenamento em cache próximo dos usuários finais configurada, podemos criar o próprio serviço de armazenamento em cache próximo dos usuários finais.

Criar o arquivo cme-demo.yaml

A configuração do serviço de armazenamento em cache de borda é feita 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

Deixaremos todos os padrões de configuração do serviço de armazenamento em cache de borda. 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 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:, esta é a origem do armazenamento em cache próximo dos usuários finais que criamos na etapa anterior. Defina como cme-origin: nome da origem do Media CDN.

Para mais informações sobre as diferentes variáveis que podem ser usadas no arquivo YAML, consulte o guia de configuração do serviço do armazenamento em cache próximo dos usuários finais.

Criar o serviço de armazenamento em cache de borda

Vamos criar um serviço de armazenamento em cache próximo dos usuários finais chamado cme-demo, na origem cme-origin do armazenamento em cache próximo dos usuários finais, 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 armazenamento em cache próximo dos usuários finais 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 armazenamento em cache próximo dos usuários finais - aqui 34.104.36.157. Ele será usado para atualizar o arquivo cme-demo.yaml e depois fazer o streaming do vídeo transcodificado.

Atualizar o serviço de armazenamento em cache de borda

Neste ponto, é uma boa ideia atualizar a configuração do serviço de armazenamento em cache próximo dos usuários finais para poder usar o IP do serviço e fazer streaming do vídeo mais tarde. Com o arquivo YAML do serviço de armazenamento em cache próximo dos usuários finais, podemos listar os nomes/IPs de todos os hosts de onde o serviço de armazenamento em cache de borda aceitará solicitações. Neste ponto, especificamos apenas demo.cme.com como um host. Para fornecer resolução de nomes a este domínio, você precisa configurar uma zona de DNS na nuvem. 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 e edite-o para que se pareça com o seguinte:

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 importar novamente o arquivo YAML. No terminal do Cloud Shell, execute o seguinte comando:

Comando

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

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

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

12. Gerar o sinal 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, faremos o seguinte:

  1. Instale o FFmpeg, um software sem custo financeiro 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 lidar com vídeos, áudios e outros arquivos e streams de multimídia. No terminal do Cloud Shell, use o seguinte comando para instalar o FFmpeg:

Comando

sudo apt install ffmpeg -y

Quando a instalação terminar, verifique a versão do FFmpeg que foi instalado corretamente:

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 sinal da transmissão ao vivo na entrada/canal

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

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

Comando

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

Você verá o FFmpeg enviando o sinal ativo de teste. O comando não vai retornar o prompt. O sinal será gerado até que você o interrompa. Você precisará abrir uma nova janela do Cloud Shell durante o restante do laboratório.

13. Abrir novo Cloud Shell

Você precisará abrir uma nova janela do Cloud Shell para continuar o laboratório, já que o FFmpeg será executado permanentemente até que você <CTRL+C> o comando para interrompê-lo e, assim, interromper a geração do sinal ativo.

Clique em "+" ao lado do nome do terminal do Cloud Shell atual. Uma nova janela do Cloud Shell será aberta.

b3c7b0be6276c194.png

Execute o restante do laboratório na janela recém-aberta do Cloud Shell.

Configurar as variáveis de ambiente

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

Comando

source ~/env_variables.txt

Verificar se as variáveis estão definidas

Verifique se todas as variáveis de ambiente necessárias foram definidas. A saída vai ter seis variáveis de ambiente.

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 indicador ativo está sendo transcodificado

Vamos executar um curl para descrever o canal. A saída mostra 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ê verá "streamingState": "STREAMING", indicando que o canal está sendo transmitido e que o sinal ao vivo está sendo transcodificado.

Vamos verificar também o conteúdo do bucket onde devemos ver um arquivo de manifesto e vários segmentos de vídeo TS. Execute o seguinte comando no Cloud Shell para listar o conteúdo do bucket que criamos no início do laboratório e usado pela API Live Streaming para gerar o manifesto de sinal ativo transcodificado e os segmentos de vídeo do 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 de HLS: main.m3u8
  • Os segmentos de vídeo TS correspondentes: uma série de arquivos numerados segment-000000000X.ts

Neste ponto, terminamos o seguinte:

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

Nas próximas seções, vamos validar o serviço de armazenamento em cache próximo dos usuários finais e fazer streaming do vídeo transcodificado usando o endereço IP anycast do Media CDN.

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

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

Execute o seguinte comando curl no Cloud Shell para acessar o arquivo de manifesto do vídeo transcodificado que está armazenado na origem do armazenamento em cache próximo dos usuários finais:

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 armazenamento em cache próximo dos usuários finais 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 o cache miss, porque o objeto ainda não foi armazenado em cache e é lido a partir da origem.

Agora faremos várias solicitações para o arquivo m3u8 e, se tudo estiver configurado corretamente, o Media CDN vai começar a veicular o conteúdo do cache. O comando abaixo fará 10 solicitações curl e 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. Caso haja ocorrências 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 cache hit, porque o objeto agora está armazenado em cache na borda. O serviço Cloud Medie Edge está funcionando como esperado.

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

Esta é a parte em que conectamos os pontos e vinculamos todas as etapas em que temos trabalhado 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 de transmissão ao vivo.
  • Começamos um sinal RTMP ao vivo com o FFmpeg que alimenta a entrada/canal da API de transmissão ao vivo.
  • Verificamos que o sinal de transmissão ao vivo foi enviado ao canal e verificamos que ele estava no modo streaming.
  • Verificamos que os arquivos transcodificados resultantes (segmentos de manifesto + TS) foram gerados e armazenados no bucket live-streaming-storage-$LOGNAME.
  • Uma origem de armazenamento em cache próximo dos usuários finais chamada cme-origin foi configurada com o bucket do GCS live-streaming-storage-$LOGNAME como origem.
  • Uma instância do armazenamento em cache de borda 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 é possível usar um player de vídeo para fazer streaming do sinal ao vivo transcodificado pelo cache do Media CDN. Para isso, vamos usar o VLC Player. O VLC Player é um player e um framework multiplataforma de código aberto sem custo financeiro 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 de Streaming adaptável: de acordo com a qualidade da sua conexão de rede e a largura de banda disponível, o player vai adaptar a qualidade do vídeo reproduzido. Com o job de transcodificação que acabamos de fazer, usamos as predefinições padrão e geramos duas qualidades "somente": SD e HD. Quando começarmos a reproduzir o vídeo no player, você verá que ele começará a reproduzir o formato SD e, se sua conexão de rede for boa o suficiente, passará rapidamente para o formato HD.

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

Para usar o VLC Player, acesse https://www.videolan.org/vlc/ (em inglês) 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 o Player em seu laptop e inicie-o. Usaremos a versão MacOSX do player nas próximas etapas.

Para reproduzir um vídeo, vá até "Arquivo" / "Rede aberta":

f85565301f7c68dc.png

Configure com:

  • URL: http://&lt;Replace_With_Edge_Cache_IP&gt;/main.m3u8. Este é 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 serviço do Cloud Media que você implantou.
  • Caminho para o arquivo de vídeo do manifesto: "/". Esse é o caminho que usamos no bucket live-streaming-storage-$LOGNAME para armazenar os arquivos de indicadores ativos transcodificados. O caminho é o caminho raiz aqui: "/".
  • O nome do arquivo de manifesto de vídeo: o arquivo de manifesto de HLS, main.m3u8.

E clique em "Abrir". A reprodução do vídeo ao vivo transcodificado será iniciada. O vídeo vai ficar parecido com a captura de tela abaixo. O contador na tela será executado em incrementos de 1, e você conseguirá ouvir um bipe contínuo.

É um teste de sinal ativo básico de 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. Aqui estão alguns que você pode querer considerar:

  • Player Quicktime - instalado por padrão em Macs. O mesmo aqui: abra uma conexão de rede para http://34.104.36.157/main.m3u8. Substitua o endereço IP pelo endereço da sua instância do serviço de armazenamento em cache de borda.

17. Como monitorar o Media CDN

Um modelo de painel do Media CDN foi criado pela equipe de PMEs: https://gist.github.com/elithrar/1c511d00f5cd3736fb2a3897867209c1.

Para instalá-lo, 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 conferir 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 que criamos no laboratório.

Pare o sinal do FFmpeg:

Pressione <CTRL+C> no terminal do Cloud Shell em que o FFmpeg está em execução.

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

Excluir 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 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/inputs/$INPUT_ID"

Exclua o bucket do GCS:

Comando

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

Exclua a instância de serviço do armazenamento em cache de borda:

Comando

gcloud edge-cache services delete cme-demo

Para confirmar a exclusão, digite "Y" quando solicitado

Exclua a origem do armazenamento em cache próximo dos usuários finais:

Comando

gcloud edge-cache origins delete cme-origin

Para confirmar a exclusão, digite "Y" quando solicitado

Excluir o painel personalizado

Comando

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