Crie clipes de VOD a partir de uma stream em direto

Esta página descreve como criar clipes de vídeo a pedido (VOD) a partir de uma stream em direto com a API Live Stream. Os clipes de VOD são compostos por ficheiros de manifesto HLS e ficheiros de segmentos guardados a partir de uma stream em direto. Apenas são suportados manifestos HLS.

Diferenças entre clipes de VOD e sessões de DVR

Os clipes VOD (também conhecidos como clipes de canal) são semelhantes às sessões de DVR com as seguintes diferenças importantes:

  • Sessões de DVR:
    • A API guarda o manifesto do DVR na mesma localização que os segmentos da stream em direto, pelo que não é necessária uma cópia adicional para o Cloud Storage. O manifesto de DVR é semelhante ao manifesto da stream em direto, mas mais longo. Quando o período de retenção expira, o manifesto é eliminado juntamente com os ficheiros de segmentos.
    • Pode criar uma sessão de DVR para conteúdo passado, atual e futuro. Por exemplo, uma sessão de DVR pode seguir uma stream em direto ou pode agendar uma sessão de DVR para iniciar e parar numa hora futura.
    • Um exemplo de utilização típico das sessões de DVR é suportar capacidades de DVR para eventos de streaming em direto. Por exemplo, um visitante pode juntar-se à stream em direto uma hora após o início e ver o conteúdo com um atraso de uma hora (ou ignorar partes do mesmo).
  • Clipes de canais:
    • A API Live Stream copia o manifesto do clipe e os ficheiros de segmento associados para um diretório especificado pelo utilizador, para que não sejam eliminados quando o período de retenção expirar. Tem controlo total do clipe.
    • Só é possível criar clipes de conteúdo passado. Os clipes em direto e o agendamento de clipes futuros não são suportados.
    • Um exemplo de utilização típico dos clipes é arquivar uma stream em direto, tornando-a disponível como um ficheiro VOD indefinidamente.

Para mais informações sobre sessões de DVR, consulte o artigo Crie uma sessão de DVR.

Configure o seu Google Cloud projeto e autenticação

Se não tiver criado um Google Cloud projeto e credenciais, consulte a secção Antes de começar.

Crie um ponto final de entrada

Para criar um ponto final de entrada, use o método projects.locations.inputs.create.

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização na qual criar o ponto final de entrada; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • INPUT_ID: um identificador definido pelo utilizador para o novo ponto final de entrada a criar (para o qual envia a sua stream de entrada). Este valor tem de ter entre 1 e 63 carateres, começar e terminar com [a-z0-9] e pode conter travessões (-) entre carateres. Por exemplo, my-input.

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": CREATE_TIME,
    "target": "projects/PROJECT_NUMBER/locations/LOCATION/inputs/INPUT_ID",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

Este comando cria uma operação de longa duração (LRO) que pode usar para acompanhar o progresso do seu pedido. Consulte o artigo Faça a gestão de operações de longa duração para mais informações.

Obtenha detalhes do ponto final de entrada

Para obter os detalhes do ponto final de entrada, use o método projects.locations.inputs.get.

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização onde o seu ponto final de entrada está localizado; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • INPUT_ID: o identificador definido pelo utilizador para o ponto final de entrada

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/inputs/INPUT_ID",
  "createTime": CREATE_TIME,
  "updateTime": UPDATE_TIME,
  "type": "RTMP_PUSH",
  "uri":  "INPUT_STREAM_URI", # For example, "rtmp://1.2.3.4/live/b8ebdd94-c8d9-4d88-a16e-b963c43a953b",
  "tier": "HD"
}

Encontre o campo uri e copie o valor INPUT_STREAM_URI devolvido para usar mais tarde na secção Envie o fluxo de entrada.

Crie um canal

Para criar um canal, use o método projects.locations.channels.create. Os exemplos seguintes criam um canal que gera uma stream em direto de HLS. A stream em direto consiste numa única renderização de alta definição (1280 x 720).

Para ativar a criação de clipes de VOD, adicione o objeto retentionConfig à configuração do canal.

"retentionConfig": {
  "retentionWindowDuration": {
      "seconds": 86400
    }
},

Quando a retenção está ativada para um canal de stream em direto, os segmentos da stream em direto e o manifesto são retidos para criar clipes de VOD. O objeto retentionWindowDuration especifica o período durante o qual a saída da stream em direto é guardada após o carregamento para o Cloud Storage. O período de retenção começa no momento em que o segmento é criado no Cloud Storage.

O período de retenção está limitado a 30 dias. Depois de o período de retenção terminar, os ficheiros de segmento e o ficheiro de manifesto da stream em direto são eliminados automaticamente do Cloud Storage. (O manifesto do clipe de VOD e os respetivos ficheiros de segmentos associados não são eliminados automaticamente.) Não pode criar clipes de VOD com segmentos eliminados. O processo de eliminação é assíncrono e pode demorar até 24 horas a ser concluído.

Especifique uma chave para o manifesto para ativar a criação de clipes de VOD. Refere-se a esta chave quando cria o clipe. Apenas são suportados manifestos HLS.

"manifests": [
{
  ...
  "key": "manifest_hls"
}

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização na qual criar o canal; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • CHANNEL_ID: um identificador definido pelo utilizador para o canal a criar; este valor tem de ter entre 1 e 63 carateres, começar e terminar com [a-z0-9] e pode conter traços (-) entre carateres
  • INPUT_ID: o identificador definido pelo utilizador para o ponto final de entrada
  • BUCKET_NAME: o nome do contentor do Cloud Storage que criou para conter o manifesto da stream em direto e os ficheiros de segmentos

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": CREATE_TIME,
    "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

Este comando cria uma operação de longa duração (LRO) que pode usar para acompanhar o progresso do seu pedido. Consulte o artigo Faça a gestão de operações de longa duração para mais informações.

Inicie o canal

Para iniciar um canal, use o método projects.locations.channels.start.

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização onde o seu canal está localizado; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • CHANNEL_ID: um identificador definido pelo utilizador para o canal

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": CREATE_TIME,
    "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID",
    "verb": "start",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

Este comando cria uma operação de longa duração (LRO) que pode usar para acompanhar o progresso do seu pedido. Consulte o artigo Faça a gestão de operações de longa duração para mais informações.

Envie a stream de entrada

Abra uma nova janela de terminal. Execute o seguinte comando, usando INPUT_STREAM_URI da secção Obtenha detalhes do ponto final de entrada:

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

Crie um clipe de VOD

Para criar um clipe de VOD, use o método projects.locations.channels.clips.create.

Use o campo outputUri para especificar a localização onde guardar os clipes e o ficheiro de manifesto de clipes no Cloud Storage. Pode usar o mesmo contentor que criou para o manifesto da stream em direto ou um contentor diferente. Também pode anexar um nome de diretório ao nome do contentor (por exemplo, my-bucket/vod-clip).

Use o campo manifestKey na matriz clipManifests para especificar o manifesto a partir do qual guardar clipes. No exemplo de configuração do canal nesta página, esta chave está definida como manifest_hls.

Use o campo outputType para especificar um dos formatos de saída de clipe suportados: MANIFEST (predefinição) ou MP4. Na configuração do canal de exemplo nesta página, este campo está definido como MANIFEST, o que gera um manifesto de VOD semelhante à saída do canal.

Pode combinar várias secções de tempo da stream em direto num único clipe adicionando objetos timeSlice à matriz slices.

"outputUri": "gs://my-bucket",
"clipManifests":[
  {
    "manifestKey": "manifest_hls"
  }
],
"slices":[
  {
    "timeSlice": {
      "markinTime": "2022-07-08T23:03:20.000Z",
      "markoutTime": "2022-07-08T23:04:20.000Z"
    }
  },
  {
    "timeSlice": {
      "markinTime": "2022-07-08T23:05:20.000Z",
      "markoutTime": "2022-07-08T23:06:20.000Z"
    }
  }
]

Tenha em conta o seguinte:

  • Cada clipe tem de conter, pelo menos, um timeSlice em slices.
  • O campo clipManifests.manifestKey tem de fazer referência a um manifesto HLS definido no canal principal do clipe. Se o pedido de criação do trabalho de clipe for bem-sucedido, o URI do manifesto do clipe gerado é devolvido no campo clipManifests.outputUri. Este URI encontra-se no caminho especificado pelo campo outputUri do clipe.
  • A matriz clipManifests só suporta um manifesto por pedido. Se quiser gerar vários manifestos para a mesma tarefa de recorte, tem de dividir os manifestos em vários pedidos de tarefas de recorte.
  • As divisões de clipes têm de ser homogéneas. Todos os elementos têm de ser do tipo timeSlice.
  • O conjunto de objetos timeSlice não pode ter sobreposições e tem de estar por ordem cronológica. O markinTime tem de ser anterior ao markoutTime em todos os timeSlice.
  • Se o markinTime mais recente de um clipe for anterior à hora de início do canal ou ao início do período de retenção, a hora de início é definida como a mais recente das duas.
  • Se o último markoutTime de um clipe for posterior à hora de paragem do canal, é definido como a hora de paragem do canal. Se o markoutTime mais recente de um clipe for posterior à hora atual do relógio do sistema, é definido para a hora em que a API inicia realmente a tarefa de recorte.
  • Para clipes com o tipo de saída MANIFEST, a duração máxima é de 24 horas. Para clipes com o tipo de saída MP4, a duração máxima é de 6 horas.

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização onde o seu canal está localizado; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • CHANNEL_ID: um identificador definido pelo utilizador para o canal
  • CLIP_ID: um identificador definido pelo utilizador para o clipe de VOD
  • MARK_IN_TIME: a hora de início da marcação no tempo de época Unix no manifesto da stream em direto original; usa uma data/hora no formato "Zulu" UTC RFC3339 (por exemplo, 2014-10-02T15:01:23Z)
  • MARK_OUT_TIME: a hora de exclusão da época Unix no manifesto da stream em direto original; usa uma data/hora no formato "Zulu" UTC RFC3339 (por exemplo, 2014-10-02T15:01:23Z)
  • BUCKET_NAME: o nome do contentor do Cloud Storage que criou para armazenar o manifesto do clipe VOD e os ficheiros de segmentos. Pode usar o mesmo contentor que criou para o manifesto da stream em direto ou um contentor diferente. Também pode anexar um nome de diretório ao nome do contentor (por exemplo, my-bucket/vod-clip)

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata",
    "createTime": CREATE_TIME,
    "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID/clips/CLIP_ID",
    "verb": "create",
    "requestedCancellation": false,
    "apiVersion": "v1"
  },
  "done": false
}

Este comando cria uma operação de longa duração (LRO) que pode usar para acompanhar o progresso do seu pedido. Consulte o artigo Faça a gestão de operações de longa duração para mais informações.

Obtenha o clipe de VOD

Para obter um clipe de VOD, use o método projects.locations.channels.clips.get.

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_NUMBER: o número do seu Google Cloud projeto. Este encontra-se no campo Número do projeto na página Definições do IAM
  • LOCATION: a localização onde o seu canal está localizado; use uma das regiões suportadas
    Mostrar localizações
    • us-central1
    • us-east1
    • us-east4
    • us-west1
    • us-west2
    • northamerica-northeast1
    • southamerica-east1
    • asia-east1
    • asia-east2
    • asia-south1
    • asia-northeast1
    • asia-southeast1
    • australia-southeast1
    • europe-north1
    • europe-west1
    • europe-west2
    • europe-west3
    • europe-west4
  • CHANNEL_ID: um identificador definido pelo utilizador para o canal
  • CLIP_ID: um identificador definido pelo utilizador para o clipe de VOD

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID/clips/CLIP_ID",
  "createTime": CREATE_TIME,
  "startTime": START_TIME,
  "updateTime": UPDATE_TIME,
  "state": "SUCCEEDED",
  "outputUri": "gs://BUCKET_NAME",
  "slices": [
    {
      "timeSlice": {
        "markinTime": "MARK_IN_TIME",
        "markoutTime": "MARK_OUT_TIME"
      }
    }
  ],
  "features": {},
  "clipManifests": [
    {
      "manifestKey": "manifest_hls",
      "outputUri": "gs://BUCKET_NAME/main.m3u8"
    }
  ]
}

O manifesto gerado encontra-se no URI especificado no campo clipManifests.outputUri. O nome do ficheiro do manifesto é igual ao valor do campo manifests.fileName do canal principal.

A resposta deve conter o seguinte:

{
  ...
  "state": "SUCCEEDED"
  ...
}

Apenas os 1000 registos de tarefas de clipes mais recentes por canal estão disponíveis através do método projects.locations.channels.clips.get. Todos os registos de tarefas de recorte com mais de 30 dias são removidos. Tem de gerir os ficheiros de clipes gerados especificados por outputUri. A API Live Stream não elimina estes ficheiros do Cloud Storage.

Valide o conteúdo do contentor

Abra o contentor do Cloud Storage conforme especificado no campo outputUri do clipe. Confirme que contém os seguintes ficheiros e diretórios:

  • Um manifesto de nível superior para o clipe com o mesmo nome que o manifests.fileName especificado na configuração do canal (por exemplo, main.m3u8); pode reproduzir este manifesto através de um leitor de multimédia online
  • Um diretório para cada muxStreams.key especificado no canal (por exemplo, mux_video_ts)
    • Uma playlist para o clipe (por exemplo, index-1.m3u8)
    • Um diretório com um nome no formato YYYYMMDDTHHMMSSZ (por exemplo, 20220708T203309Z/); este diretório contém os segmentos de clipes VOD
      • Vários ficheiros de segmentos segment-number.ts que compõem o clipe de VOD

Ver o clipe de VOD

Para reproduzir o ficheiro multimédia gerado no Shaka Player, conclua os seguintes passos:

  1. Torne o contentor do Cloud Storage que criou publicamente legível.
  2. Para ativar a partilha de recursos de origem cruzada (CORS) num contentor do Cloud Storage, faça o seguinte:
    1. Crie um ficheiro JSON que contenha o seguinte:
      [
        {
          "origin": ["https://shaka-player-demo.appspot.com/"],
          "responseHeader": ["Content-Type", "Range"],
          "method": ["GET", "HEAD"],
          "maxAgeSeconds": 3600
        }
      ]
    2. Execute o seguinte comando depois de substituir JSON_FILE_NAME pelo nome do ficheiro JSON que criou no passo anterior:
      gcloud storage buckets update gs://BUCKET_NAME --cors-file=JSON_FILE_NAME.json
  3. No contentor do Cloud Storage, encontre o ficheiro gerado. Clique em Copiar URL na coluna Acesso público do ficheiro.
  4. Navegue para Shaka Player, um leitor de streams em direto online.
  5. Clique em Conteúdo personalizado na barra de navegação superior.
  6. Clique no botão +.
  7. Cole o URL público do ficheiro na caixa URL do manifesto.

  8. Introduza um nome na caixa Nome.

  9. Clique em Guardar.

  10. Clique em Jogar.

Deve ver um padrão de teste a ser reproduzido como stream em direto.

Vídeo de padrão de teste

Eventos de pausas para anúncios e de indicação

Se criou um evento de intervalo de anúncios para a stream em direto, os clipes de VOD não contêm os anúncios. A API gera uma lista de reprodução com os pontos de inserção de anúncios substituídos pelas seguintes etiquetas:

#EXT-X-CUE-OUT: AD_BREAK_DURATION
#EXT-X-CUE-IN

As faixas que aparecem no início ou no fim do clipe de VOD são removidas automaticamente. As faixas que aparecem na stream, rodeadas pelo conteúdo da stream em direto, são mantidas no clipe de VOD gerado.