Tải lên video

YouTubeVideoUploadService cho phép bạn tải video lên YouTube ngay thông qua Google Ads API. Sau đó, bạn có thể sử dụng những video này để tạo thành phần video trong nhiều loại quảng cáo, chẳng hạn như chiến dịch Tối đa hoá hiệu suất hoặc chiến dịch Tạo nhu cầu.

Dịch vụ này giúp đơn giản hoá quy trình tạo quảng cáo dạng video bằng cách xử lý quy trình tải lên YouTube, đảm bảo rằng video được liên kết chính xác với tài khoản của bạn.

Khái niệm chính

Trước khi bắt đầu, bạn cần hiểu rõ cách quản lý video tải lên và các trạng thái mà video có thể trải qua.

Quyền sở hữu kênh

Khi tải video lên, bạn có thể chỉ định kênh YouTube đích bằng cách sử dụng trường channel_id trong tài nguyên YouTubeVideoUpload:

  • Kênh thuộc sở hữu của nhà quảng cáo (thương hiệu): Cung cấp channel_id của một kênh YouTube hiện có thuộc sở hữu của nhà quảng cáo. Tính năng này chỉ được hỗ trợ với quy trình xác thực người dùng; không thể sử dụng tính năng này với tài khoản dịch vụ.
  • Kênh do Google quản lý: Nếu bạn bỏ qua channel_id, video sẽ được tải lên một kênh YouTube do Google quản lý và được liên kết với tài khoản Google Ads.

Trạng thái tải lên

Vòng đời của một video tải lên YouTube được theo dõi bằng trường state. Enum YouTubeVideoUploadState xác định các trạng thái sau:

Tiểu bang Mô tả
PENDING Video đang được tải lên.
UPLOADED Video đã được tải lên thành công và đang được YouTube xử lý.
PROCESSED Video đã được xử lý xong và sẵn sàng để sử dụng.
FAILED Không thể hoàn tất quá trình tải lên hoặc xử lý.
REJECTED Video bị từ chối do không xác thực được hoặc vi phạm chính sách.
UNAVAILABLE Video không có trạng thái; video đó có thể đã bị gỡ bỏ khỏi YouTube.

Chế độ cài đặt quyền riêng tư

Trường video_privacy kiểm soát những người có thể xem video đã tải lên. Liệt kê YouTubeVideoPrivacy hỗ trợ:

  • PUBLIC: Bất kỳ ai trên YouTube cũng có thể xem video này. (Chỉ được phép đối với kênh thương hiệu).
  • UNLISTED: Video không tìm kiếm được nhưng bất kỳ ai có đường liên kết đều có thể xem. Đây là lựa chọn mặc định và duy nhất cho các kênh do Google quản lý.

Thông tin công bố về nội dung tạo sinh

Kể từ phiên bản 26, theo các quy định như Đạo luật về AI của Liên minh Châu Âu, nhà quảng cáo có thể công bố việc nội dung video được tải lên có chứa nội dung do AI tạo hoặc nội dung nghe nhìn giả tạo hay không.

Trường video_content_metadata trong YouTubeVideoUpload chứa VideoContentMetadata. Đặt trường generative_content_disclosure lồng nhau bằng cách sử dụng enum YouTubeVideoUploadGenerativeContentDisclosure:

Giá trị Mô tả
NON_GENERATIVE_CONTENT Nhà quảng cáo đã công bố rằng video này không phải do AI tạo.
GENERATIVE_CONTENT Nhà quảng cáo đã công bố rằng video này do AI tạo.

Tải video lên

Để tải video lên, bạn phải sử dụng yêu cầu nhiều phần cho phương thức CreateYouTubeVideoUpload. Yêu cầu này chứa cả siêu dữ liệu cho nội dung tải lên và tệp video.

1. Bắt đầu tải lên

Tạo một CreateYouTubeVideoUploadRequest nêu rõ:

  • customer_id: Mã khách hàng Google Ads của bạn.
  • you_tube_video_upload: Một đối tượng YouTubeVideoUpload có video_title, video_description và không bắt buộc là channel_id, video_privacy và bắt đầu từ phiên bản 26, video_content_metadata.

Nếu bạn đang sử dụng một thư viện ứng dụng, hãy gọi phương thức CreateYouTubeVideoUpload, truyền tệp video của bạn và quá trình tải video lên sẽ được xử lý nội bộ.

Java

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

C#

YouTubeVideoUploadServiceClient ytService = client.GetService(
    Services.V25.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

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

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')
      

Nếu bạn đang sử dụng REST, phần sau đây sẽ mô tả cách quản lý quá trình tải video lên.

2. Tải video lên

Khi bạn gửi yêu cầu REST đến phương thức CreateYouTubeVideoUpload, phản hồi sẽ chứa URL dùng để tải các byte video lên trong tiêu đề phản hồi HTTP x-goog-upload-url, cùng với siêu dữ liệu khác như kích thước dự kiến của mỗi phần đối với các tệp tải lên theo phần, theo giao thức tải lên có thể tiếp tục chuẩn của Google.

Bạn cũng có thể khai báo kích thước của video mà bạn sẽ tải lên ban đầu, khi bắt đầu quy trình, bằng tiêu đề của yêu cầu HTTP x-goog-upload-header-content-length.

Để xem nội dung mô tả đầy đủ về các tiêu đề HTTP được dùng trong giao thức tải video lên, hãy tham khảo mã ví dụ sau:

# 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. Truy xuất trạng thái tải video lên

Sau khi bắt đầu tải video lên, bạn có thể truy xuất trạng thái của video bằng cách truy vấn tài nguyên you_tube_video_upload bằng GAQL:

Java

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

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

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

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
      

Quản lý mục tải lên

Sau khi tải video lên, bạn có thể sử dụng video đó làm thành phần video.

Sử dụng video đã tải lên

Sau khi video đạt đến trạng thái PROCESSED, bạn có thể tìm thấy mã nhận dạng video trên YouTube của video đó trong trường video_id của tài nguyên YouTubeVideoUpload.

Sử dụng video_id này để tạo YoutubeVideoAsset bằng MutateAssets hoặc liên kết trực tiếp với các loại quảng cáo hỗ trợ video trên YouTube bằng cách tham chiếu mã video.

Cập nhật siêu dữ liệu

Bạn có thể cập nhật siêu dữ liệu của video được tải lên thông qua API này bằng phương thức UpdateYouTubeVideoUpload. Bạn chỉ có thể cập nhật các trường video_title, video_description và video_privacy.

Xoá video tải lên

Nếu bạn cần xoá video đã tải lên bằng Google Ads API, hãy sử dụng phương thức RemoveYouTubeVideoUpload. Thao tác này sẽ xoá video khỏi cả thư viện thành phần của Google Ads và YouTube.