Fazer upload de vídeos

O YouTubeVideoUploadService permite fazer upload de vídeos diretamente para o YouTube pela API Google Ads. Esses vídeos podem ser usados para criar recursos de vídeo em vários tipos de anúncios, como campanhas Performance Max ou campanhas Geração de Demanda.

Esse serviço simplifica o fluxo de trabalho de criação de anúncios em vídeo, processando o upload do YouTube e garantindo que os vídeos estejam associados corretamente à sua conta.

Principais conceitos

Antes de começar, é importante entender como os uploads de vídeo são gerenciados e os diferentes estados que eles podem passar.

Fluxo de trabalho completo

O upload de um arquivo de vídeo e a veiculação dele em um anúncio exigem quatro etapas sequenciais:

Etapa Serviço e método Resumo
1. Iniciar e fazer upload de bytes de vídeo CreateYouTubeVideoUpload em YouTubeVideoUploadService Faça upload dos metadados e do arquivo binário do vídeo para criar um YouTubeVideoUpload recurso (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}).
2. Verificar o estado de processamento SearchStream em GoogleAdsService Consulte you_tube_video_upload até que state = 'PROCESSED' e o video_id de 11 caracteres do YouTube seja preenchido.
3. Criar um recurso de vídeo reutilizável MutateAssets em AssetService Crie um YoutubeVideoAsset (youtube_video_id = video_id) para receber um nome de recurso de recurso (customers/{customer_id}/assets/{asset_id}).
4. Vincular o recurso a campanhas ou anúncios MutateAssetGroupAssets em AssetGroupAssetService ou MutateAdGroupAds em AdGroupAdService Vincule o recurso a um AssetGroupAsset (field_type = YOUTUBE_VIDEO) da Performance Max ou a um DemandGenVideoResponsiveAdInfo (videos[].asset) da Geração de Demanda.

Propriedade do canal

Ao fazer upload de um vídeo, você pode especificar o canal de destino do YouTube usando o campo channel_id no YouTubeVideoUpload recurso:

  • Canal da marca de propriedade do anunciante:forneça o channel_id de um canal do YouTube que pertence ao anunciante. Isso só é compatível com o fluxo de autenticação do usuário; não pode ser usado com contas de serviço.
  • Canal gerenciado pelo Google:se channel_id for omitido, o vídeo será enviado para um canal do YouTube gerenciado pelo Google associado à conta do Google Ads.

Estados de upload

O ciclo de vida de um upload de vídeo do YouTube é rastreado pelo campo state. A YouTubeVideoUploadState enumeração define os seguintes estados:

Estado Descrição
PENDING O vídeo está sendo enviado.
UPLOADED O vídeo foi enviado e está sendo processado pelo YouTube.
PROCESSED O vídeo foi processado e está pronto para uso.
FAILED O upload ou o processamento falhou e não pode ser concluído.
REJECTED O vídeo foi rejeitado devido a motivos de validação ou política.
UNAVAILABLE O estado do vídeo não está disponível. Ele pode ter sido removido do YouTube.

Configurações de privacidade

O campo video_privacy controla quem pode assistir o vídeo enviado. A YouTubeVideoPrivacy enumeração oferece suporte a:

  • PUBLIC: o vídeo está disponível para qualquer pessoa no YouTube. Permitido apenas para canais de marca.
  • UNLISTED: o vídeo não pode ser pesquisado, mas pode ser assistido por qualquer pessoa com o link. Essa é a opção padrão e única para canais gerenciados pelo Google.

Divulgação de conteúdo gerado com IA

A partir da v26, de acordo com regulamentações como a Lei de IA da UE, os anunciantes podem divulgar se o conteúdo de vídeo enviado contém mídia sintética ou gerada por IA.

O campo video_content_metadata em YouTubeVideoUpload contém VideoContentMetadata. Defina seu campo aninhado generative_content_disclosure usando a enumeração YouTubeVideoUploadGenerativeContentDisclosure:

Valor Descrição
NON_GENERATIVE_CONTENT O anunciante divulgou o vídeo como não gerado por IA.
GENERATIVE_CONTENT O anunciante divulgou o vídeo como gerado com IA.

Fazer upload de um vídeo

Para fazer upload de um vídeo, use uma solicitação de várias partes para o método CreateYouTubeVideoUpload. A solicitação contém os metadados do upload e o arquivo de vídeo.

1. Iniciar o upload

Crie um CreateYouTubeVideoUploadRequest com os seguintes campos:

Campo Requisito Descrição e restrições
customer_id Obrigatório O ID de cliente do Google Ads com 10 dígitos (sem hifens).
you_tube_video_upload.video_title Obrigatório (INPUT_ONLY, IMMUTABLE) Título do vídeo enviado no YouTube (até 100 caracteres; não pode conter < ou >).
you_tube_video_upload.video_description Opcional (INPUT_ONLY, IMMUTABLE) Descrição do vídeo no YouTube (até 5.000 caracteres; não pode conter < ou >).
you_tube_video_upload.channel_id Opcional (IMMUTABLE) ID do canal do YouTube de 24 caracteres de destino (começando com UC) para um canal de marca de propriedade do anunciante. Se omitido, faz upload para um canal gerenciado pelo Google.
you_tube_video_upload.video_privacy Opcional (mutável em canais de marca) YouTubeVideoPrivacy configuração (UNLISTED padrão ou PUBLIC para canais de marca de propriedade do anunciante).
you_tube_video_upload.video_content_metadata Opcional (INPUT_ONLY, IMMUTABLE) Disponível a partir da v26: VideoContentMetadata com generative_content_disclosure definido como um valor YouTubeVideoUploadGenerativeContentDisclosure (NON_GENERATIVE_CONTENT ou GENERATIVE_CONTENT).

Se você estiver usando uma biblioteca de cliente, chame o CreateYouTubeVideoUpload método, transmitindo o arquivo de vídeo, e o upload será processado internamente.

Java

String videoUploadResourceName;
try (YouTubeVideoUploadServiceClient youTubeVideoUploadServiceClient =
    googleAdsClient.getLatestVersion().createYouTubeVideoUploadServiceClient()) {
  YouTubeVideoUpload youTubeVideoUpload =
      YouTubeVideoUpload.newBuilder()
          .setVideoTitle("Test Video")
          .setVideoDescription("Test Video Description")
          .setVideoPrivacy(YouTubeVideoPrivacy.UNLISTED)
          .build();

  CreateYouTubeVideoUploadRequest createUploadRequest =
      CreateYouTubeVideoUploadRequest.newBuilder()
          .setCustomerId(Long.toString(customerId))
          .setYouTubeVideoUpload(youTubeVideoUpload)
          .build();

  CreateYouTubeVideoUploadResponse response =
      youTubeVideoUploadServiceClient.createYouTubeVideoUpload(
          createUploadRequest, () -> new FileInputStream(videoFile), null);

  videoUploadResourceName = response.getResourceName();
  System.out.printf("Created YouTube video upload: %s%n", videoUploadResourceName);
}
      

C#

YouTubeVideoUploadServiceClient ytService = client.GetService(
    Services.V26.YouTubeVideoUploadService);

CreateYouTubeVideoUploadRequest createUploadRequest =
    new CreateYouTubeVideoUploadRequest()
    {
        CustomerId = customerId.ToString(),
        YouTubeVideoUpload = new YouTubeVideoUpload()
        {
            VideoTitle = "Test Video",
            VideoDescription = "Test Video Description",
            VideoPrivacy = YouTubeVideoPrivacy.Unlisted
        }
    };

string videoUploadResourceName;
using (FileStream stream = File.OpenRead(videoFilePath))
{
    ResumableUploadSession<CreateYouTubeVideoUploadRequest, CreateYouTubeVideoUploadResponse> session =
        ytService.CreateYouTubeVideoUpload();
    CreateYouTubeVideoUploadResponse response =
        session.BeginUploadAsync(createUploadRequest, stream).Result;

    videoUploadResourceName = response.ResourceName;
    Console.WriteLine($"Created YouTube video upload: {videoUploadResourceName}");
}
      

PHP

$youTubeVideoUploadServiceClient = $googleAdsClient->getYouTubeVideoUploadServiceClient();

$youTubeVideoUpload = new YouTubeVideoUpload([
    'video_title' => 'Test Video',
    'video_description' => 'Test Video Description',
    'video_privacy' => YouTubeVideoPrivacy::UNLISTED
]);

$createYouTubeVideoUploadRequest = CreateYouTubeVideoUploadRequest::build(
    $customerId,
    $youTubeVideoUpload
);

/** @var ResumableUpload $resumableUpload */
$resumableUpload = $youTubeVideoUploadServiceClient->createYouTubeVideoUpload(
    $createYouTubeVideoUploadRequest
);

$stream = Utils::streamFor(fopen($videoFilePath, 'rb'));
/** @var CreateYouTubeVideoUploadResponse $response */
$response = $resumableUpload->startUpload($stream);

$videoUploadResourceName = $response->getResourceName();
printf("Created YouTube video upload: '%s'%s", $videoUploadResourceName, PHP_EOL);
      

Python

yt_service: YouTubeVideoUploadServiceClient = client.get_service(
    "YouTubeVideoUploadService"
)

create_upload_request: CreateYouTubeVideoUploadRequest = (
    youtube_video_upload_service.CreateYouTubeVideoUploadRequest()
)
create_upload_request.customer_id = customer_id
create_upload_request.you_tube_video_upload.video_title = "Test Video"
create_upload_request.you_tube_video_upload.video_description = (
    "Test Video Description"
)
create_upload_request.you_tube_video_upload.video_privacy = (
    client.enums.YouTubeVideoPrivacyEnum.UNLISTED
)

video_upload_resource_name: str
with open(video_file_path, "rb") as stream:
    response: CreateYouTubeVideoUploadResponse = (
        yt_service.create_you_tube_video_upload(
            stream=stream,
            request=create_upload_request,
            retry=None,
        )
    )
    video_upload_resource_name = response.resource_name
    print(f"Created YouTube video upload: {video_upload_resource_name}")
      

Ruby

video_upload = client.resource.you_tube_video_upload do |v|
  v.video_title = "Test Video"
  v.video_description = "Test Video Description"
  v.video_privacy = :UNLISTED
end

upload = client.service.you_tube_video_upload.create_you_tube_video_upload(
  customer_id: customer_id,
  you_tube_video_upload: video_upload,
)

video_upload_resource_name = nil
File.open(video_file_path, "rb") do |stream|
  response = upload.start(
    stream: stream,
    content_type: "application/octet-stream",
  )
  video_upload_resource_name = response.resource_name
  puts "Created YouTube video upload: #{video_upload_resource_name}"
end
      

Perl

This example is not yet available in Perl; you can take a look at the other languages.
    

curl

# 
# Use the --i curl parameter to capture response headers in the $RESPONSE
# variable.
FILE_SIZE=$(wc -c < "${VIDEO_FILE_NAME}" | tr -d '\r')
RESPONSE=$(curl -i -f -v -s --request POST \
"https://googleads.googleapis.com/resumable/upload/v${API_VERSION}/customers/${CUSTOMER_ID}/youTubeVideoUploads:create" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--header "X-Goog-Upload-Protocol: resumable" \
--header "X-Goog-Upload-Command: start" \
--header "X-Goog-Upload-Header-Content-Length: ${FILE_SIZE}" \
--data @- <<EOF
{
  "customer_id": "${CUSTOMER_ID}",
  "you_tube_video_upload": {
    "video_title": "${VIDEO_TITLE}",
    "video_description": "${VIDEO_DESCRIPTION}",
    "video_privacy": "UNLISTED"
  }
}
EOF
)

# Extract the value of the "x-goog-upload-url" header from the HTTP response.
UPLOAD_URL=$(echo "${RESPONSE}" \
  | grep -i '^x-goog-upload-url' \
  | awk '{print $2}' \
  | tr -d '\r')
CHUNK_SIZE=$(echo "${RESPONSE}" \
  | grep -i '^x-goog-upload-chunk-granularity' \
  | awk '{print $2}' \
  | tr -d '\r')
      

Se você estiver usando REST, a seção a seguir descreve como gerenciar o upload de vídeo.

2. Fazer upload do vídeo

Ao fazer upload com REST, CreateYouTubeVideoUpload usa um protocolo de upload retomável de duas etapas :

  1. Iniciar a sessão de upload: envie uma solicitação POST inicial para o CreateYouTubeVideoUpload endpoint de upload (/upload/v26/customers/{customer_id}/youTubeVideoUploads:create) com x-goog-upload-command: start (e, opcionalmente, x-goog-upload-header-content-length para declarar o tamanho do arquivo). A resposta retorna o URL da sessão de upload no cabeçalho de resposta HTTP x-goog-upload-url, além de metadados, como o tamanho esperado do bloco.
  2. Transmitir e finalizar os bytes de vídeo:envie o payload de vídeo binário para o endpoint x-goog-upload-url com x-goog-upload-command: upload, finalize. Quando o upload terminar, a resposta vai retornar o resource_name criado (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}).

Para uma descrição completa dos cabeçalhos HTTP usados no protocolo de upload de vídeo, consulte o exemplo de código a seguir:

# Take the first ${CHUNK_SIZE} bytes of the video file and upload them.
head -c ${CHUNK_SIZE} ${VIDEO_FILE_NAME} | curl -i -v -X PUT "${UPLOAD_URL}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--header "X-Goog-Upload-Offset: 0" \
--header "X-Goog-Upload-Command: upload" \
--header "Content-Length: ${CHUNK_SIZE}" \
--data-binary @-

# Query the status of the upload.
QUERY_RESPONSE=$(curl -i -s -X POST "${UPLOAD_URL}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--header "X-Goog-Upload-Command: query")

# Extract the value of the "x-goog-upload-size-received" header from the HTTP
# response.
UPLOADED_BYTES=$(echo "${QUERY_RESPONSE}" \
  | grep -i '^x-goog-upload-size-received' \
  | awk '{print $2}' \
  | tr -d '\r')

echo "Uploaded ${UPLOADED_BYTES} bytes."

REMAINING_BYTES=$((FILE_SIZE - UPLOADED_BYTES))
echo "${REMAINING_BYTES} bytes remaining to upload."

FINALIZE_RESPONSE=$(tail -c ${REMAINING_BYTES} ${VIDEO_FILE_NAME} | curl -v -X PUT "${UPLOAD_URL}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--header "X-Goog-Upload-Offset: ${UPLOADED_BYTES}" \
--header "X-Goog-Upload-Command: upload, finalize" \
--data-binary @-)
UPLOADED_VIDEO_RESOURCE_NAME=$(echo $FINALIZE_RESPONSE | jq -r '.resourceName')
      

3. Recuperar o estado de upload do vídeo

Depois de iniciar um upload de vídeo, consulte o estado de processamento dele consultando os campos selecionáveis do recurso you_tube_video_upload (resource_name, video_upload_id, channel_id, video_id, state, e video_privacy) com GAQL até que state = 'PROCESSED' (os campos INPUT_ONLY não podem ser selecionados no GAQL):

Java

// Retrieve the metadata of the newly uploaded video.
String query =
    String.format(
        "SELECT "
            + "you_tube_video_upload.resource_name, "
            + "you_tube_video_upload.video_id, "
            + "you_tube_video_upload.state "
            + "FROM you_tube_video_upload "
            + "WHERE you_tube_video_upload.resource_name = '%s'",
        videoUploadResourceName);

try (GoogleAdsServiceClient googleAdsServiceClient =
    googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
  SearchGoogleAdsStreamRequest request =
      SearchGoogleAdsStreamRequest.newBuilder()
          .setCustomerId(Long.toString(customerId))
          .setQuery(query)
          .build();

  ServerStream<SearchGoogleAdsStreamResponse> stream =
      googleAdsServiceClient.searchStreamCallable().call(request);

  for (SearchGoogleAdsStreamResponse response : stream) {
    for (GoogleAdsRow googleAdsRow : response.getResultsList()) {
      YouTubeVideoUpload video = googleAdsRow.getYouTubeVideoUpload();
      System.out.printf(
          "Video with ID %s was found in state %s.%n",
          video.getVideoId(), video.getState());
    }
  }
}
      

C#

// Retrieve the metadata of the newly uploaded video.
string query = $@"
    SELECT
      you_tube_video_upload.resource_name,
      you_tube_video_upload.video_id,
      you_tube_video_upload.state
    FROM you_tube_video_upload
    WHERE you_tube_video_upload.resource_name = '{videoUploadResourceName}'";

GoogleAdsServiceClient gaService = client.GetService(
    Services.V26.GoogleAdsService);

gaService.SearchStream(customerId.ToString(), query,
    delegate (SearchGoogleAdsStreamResponse resp)
    {
        foreach (GoogleAdsRow row in resp.Results)
        {
            Console.WriteLine(
                $"Video with ID {row.YouTubeVideoUpload.VideoId} was found in " +
                $"state {row.YouTubeVideoUpload.State}.");
        }
    }
);
      

PHP

// Retrieve the metadata of the newly uploaded video.
$query = sprintf(
    "SELECT you_tube_video_upload.resource_name, "
    . "you_tube_video_upload.video_id, "
    . "you_tube_video_upload.state "
    . "FROM you_tube_video_upload "
    . "WHERE you_tube_video_upload.resource_name = '%s'",
    $videoUploadResourceName
);

$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
$stream = $googleAdsServiceClient->searchStream(
    SearchGoogleAdsStreamRequest::build($customerId, $query)
);

foreach ($stream->iterateAllElements() as $googleAdsRow) {
    /** @var GoogleAdsRow $googleAdsRow */
    printf(
        "Video with ID '%s' was found in state '%s'.%s",
        $googleAdsRow->getYouTubeVideoUpload()->getVideoId(),
        YouTubeVideoUploadState::name($googleAdsRow->getYouTubeVideoUpload()->getState()),
        PHP_EOL
    );
}
      

Python

# Retrieve the metadata of the newly uploaded video.
query: str = f"""
    SELECT
      you_tube_video_upload.resource_name,
      you_tube_video_upload.video_id,
      you_tube_video_upload.state
    FROM you_tube_video_upload
    WHERE you_tube_video_upload.resource_name = '{video_upload_resource_name}'"""

ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService")
stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream(
    customer_id=customer_id, query=query
)

for row in itertools.chain.from_iterable(batch.results for batch in stream):
    video = row.you_tube_video_upload
    print(
        f"Video with ID {row.you_tube_video_upload.video_id} was found in state {row.you_tube_video_upload.state}."
    )
      

Ruby

# Retrieve the metadata of the newly uploaded video.
query = <<~EOQ
  SELECT
    you_tube_video_upload.resource_name,
    you_tube_video_upload.video_id,
    you_tube_video_upload.state
  FROM you_tube_video_upload
  WHERE you_tube_video_upload.resource_name = '#{video_upload_resource_name}'
EOQ

responses = client.service.google_ads.search_stream(
  customer_id: customer_id,
  query: query,
)

responses.each do |batch|
  batch.results.each do |row|
    puts "Video with ID #{row.you_tube_video_upload.video_id} was found in " \
      "state #{row.you_tube_video_upload.state}."
  end
end
      

Perl

This example is not yet available in Perl; you can take a look at the other languages.
    

curl

curl -i -v -X POST \
"https://qa-prod-googleads.sandbox.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:search" \
--header "Content-Type: application/json" \
  --header "Developer-Token: ${DEVELOPER_TOKEN}" \
  --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
  --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
  --data @- <<EOF
{
  "query": "SELECT you_tube_video_upload.resource_name, you_tube_video_upload.video_id, you_tube_video_upload.state FROM you_tube_video_upload WHERE you_tube_video_upload.resource_name = '$UPLOADED_VIDEO_RESOURCE_NAME'"
}
EOF
      

Gerenciar uploads

Depois que um upload de vídeo for concluído, você poderá usá-lo como um recurso de vídeo.

Usar o vídeo enviado

Depois que um vídeo atinge o estado PROCESSED, você pode encontrar o ID do vídeo do YouTube de 11 caracteres no campo video_id do recurso YouTubeVideoUpload.

Use este video_id para criar um YoutubeVideoAsset com MutateAssets e vincular o nome do recurso resultante (customers/{customer_id}/assets/{asset_id}) às suas campanhas ou anúncios:

  1. Crie o YoutubeVideoAsset transmitindo youtube_video_id para AssetService.MutateAssets:

    POST https://googleads.googleapis.com/v26/customers/{customer_id}/assets:mutate
    {
      "operations": [
        {
          "create": {
            "name": "Product Launch Video",
            "youtubeVideoAsset": {
              "youtubeVideoId": "dQw4w9WgXcQ"
            }
          }
        }
      ]
    }
    
  2. Vincule o Asset a um AssetGroup ou AdGroupAd:

    • Performance Max:crie um AssetGroupAsset usando AssetGroupAssetService.MutateAssetGroupAssets com field_type definido como YOUTUBE_VIDEO:

      POST https://googleads.googleapis.com/v26/customers/{customer_id}/assetGroupAssets:mutate
      {
        "operations": [
          {
            "create": {
              "assetGroup": "customers/{customer_id}/assetGroups/{asset_group_id}",
              "asset": "customers/{customer_id}/assets/{asset_id}",
              "fieldType": "YOUTUBE_VIDEO"
            }
          }
        ]
      }
      
    • Geração de Demanda:faça referência a customers/{customer_id}/assets/{asset_id} em a lista videos de um DemandGenVideoResponsiveAdInfo objeto ao chamar AdGroupAdService.MutateAdGroupAds:

      POST https://googleads.googleapis.com/v26/customers/{customer_id}/adGroupAds:mutate
      {
        "operations": [
          {
            "create": {
              "adGroup": "customers/{customer_id}/adGroups/{ad_group_id}",
              "status": "PAUSED",
              "ad": {
                "name": "Demand Gen Video Ad",
                "finalUrls": ["https://www.example.com"],
                "demandGenVideoResponsiveAd": {
                  "videos": [
                    {
                      "asset": "customers/{customer_id}/assets/{asset_id}"
                    }
                  ],
                  "logoImages": [
                    {
                      "asset": "customers/{customer_id}/assets/{logo_asset_id}"
                    }
                  ],
                  "headlines": [
                    {
                      "text": "Example Headline"
                    }
                  ],
                  "longHeadlines": [
                    {
                      "text": "Example Long Headline"
                    }
                  ],
                  "descriptions": [
                    {
                      "text": "Example Description"
                    }
                  ],
                  "businessName": {
                    "text": "Example Business"
                  }
                }
              }
            }
          }
        ]
      }
      
  3. Consulte os recursos YOUTUBE_VIDEO atuais usando GoogleAdsService.SearchStream:

    SELECT
      asset.id,
      asset.resource_name,
      asset.name,
      asset.type,
      asset.youtube_video_asset.youtube_video_id,
      asset.youtube_video_asset.youtube_video_title
    FROM asset
    WHERE asset.type = 'YOUTUBE_VIDEO'
      AND asset.youtube_video_asset.youtube_video_id = '{video_id}'
    

Atualizar metadados

Você pode atualizar a configuração de privacidade de um vídeo enviado por essa API usando o UpdateYouTubeVideoUpload método com update_mask definido como "video_privacy". Somente o campo video_privacy (PUBLIC ou UNLISTED, para vídeos enviados a um brand channel de propriedade do anunciante) pode ser atualizado após a criação. video_title, video_description, channel_id e video_content_metadata são imutáveis.

Remover uploads

Se você precisar excluir vídeos enviados com a API Google Ads, transmita os customers/{customer_id}/youTubeVideoUploads/{video_upload_id} nomes de recursos no campo resource_names do RemoveYouTubeVideoUpload método. Isso remove o vídeo da Biblioteca de Recursos do Google Ads e do YouTube.