上傳新參照

注意:YouTube Content ID API 為 YouTube 內容合作夥伴使用,並未開放所有開發人員或所有 YouTube 使用者存取。如果 Google API 控制台顯示的服務中沒有 YouTube Content ID API,請參閱 YouTube 說明中心,進一步瞭解 YouTube 合作夥伴計畫。

這個程式碼範例示範如何使用 YouTube Content ID API 上傳 reference。如要上傳reference,你必須先建立asset,並設定資產的擁有權比對政策。這個範例將逐步說明所有步驟。

這個範例顯示為與程式碼相關章節有關的一系列步驟。您可以在本頁結尾處找到完整指令碼。程式碼是以 Python 編寫。您也可以使用其他熱門程式設計語言適用的用戶端程式庫。

範例指令碼不會處理任何錯誤。

需求條件

在這個步驟中,我們會將 OAuth 2.0 授權加入指令碼中。如此一來,執行指令碼的使用者就能授權指令碼執行歸因於使用者帳戶的 API 要求。

建立 client_secrets.json 檔案

YouTube Content ID API 需要 client_secrets.json 檔案 (含有 API 控制台中的資訊),才能進行驗證。此外,您需要註冊應用程式。如需驗證功能運作方式的完整說明,請參閱驗證指南

 {
  "web": {
    "client_id": "INSERT CLIENT ID HERE",
    "client_secret": "INSERT CLIENT SECRET HERE",
    "redirect_uris": [],
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token"
  }
}

將驗證碼加入指令碼

如要啟用使用者驗證和授權功能,您必須新增下列 import 陳述式:

from oauth2client.file import Storage
from oauth2client.client import flow_from_clientsecrets
from oauth2client.tools import run

接下來,我們會使用步驟 2a 中設定的用戶端密鑰建立 FLOW 物件。如果使用者授權我們的應用程式代表使用者提交 API 要求,產生的憑證會儲存在 Storage 物件中,以供日後使用。如果憑證過期,使用者需要重新授權應用程式。

將下列程式碼新增至 main 函式的結尾:

  # Set up a Flow object to be used if we need to authenticate.
  FLOW = flow_from_clientsecrets('client_secrets.json',
      scope='https://www.googleapis.com/auth/youtubepartner',
      message='error message')

  # The Storage object stores the credentials. If it doesn't exist, or if
  # the credentials are invalid or expired, run through the native client flow.
  storage = Storage('yt_partner_api.dat')
  credentials = storage.get()
  
  if (credentials is None or credentials.invalid or
      credentials.token_expiry <= datetime.now()):
    credentials = run(FLOW, storage)

建立 httplib2 物件並附加憑證

使用者授權指令碼後,我們會建立 httplib2.Http 物件來處理 API 要求,並將授權憑證附加至該物件。

新增下列匯入陳述式:

  import httplib2

然後將下列程式碼新增至 main 函式的結尾:

  # Create httplib2.Http object to handle HTTP requests and
  # attach auth credentials.
  http = httplib2.Http()
  http = credentials.authorize(http)

取得服務

成功授權後,程式碼即可取得相關作業所需的服務。首先,它會建立 service 物件,提供所有 YouTube Content ID API 服務的存取權。然後,程式碼會使用 service 物件取得其呼叫的四個資源特定服務。

from apiclient.discovery import build

# ...

service = build("youtubePartner", "v1", http=http, static_discovery=False)
# ...
asset_service = service.assets()
# ...
ownership_service = service.ownership()
# ...
match_policy_service = service.assetMatchPolicy()
# ...
reference_service = service.references()

建立資產

上傳 reference 的第一步是建立 asset。首先,我們建立一個僅設定資產標題的簡易 metadata 物件。接著,程式碼會將該物件新增至 asset_body,後者也會識別資產的類型。asset_body 物件會依序做為 asset_service.insert() 方法的輸入。此方法會建立資產並傳回其專屬 ID。

def _create_asset(service, title, metadata_type):
  metadata = {'title': title}
  asset_body = {'metadata': metadata, 'type': metadata_type}
  # Retrieve asset service.
  asset_service = service.assets()

  # Create and execute insert request.
  request = asset_service.insert(body=asset_body)
  response = request.execute()
  logger.info('Asset has been created.\n%s', response)
  asset_id = response['id']
  return asset_id

更新擁有權

建立 asset 後,指令碼會設定資產的 ownership。這個範例顯示內容擁有者擁有 100% 的資產,但該擁有權僅限於波蘭 (PL) 和英國 (GB)��

def _create_asset_ownership(service, asset_id, owner_name):
  ownership = {
      'owner': owner_name,
      'ratio' : 100,
      'type': 'include',
      'territories': ['PL', 'GB']}
  ownership_body = {'general': [ownership]}
  ownership_service = service.ownership()

  request = ownership_service.update(assetId=asset_id, body=ownership_body)
  response = request.execute()
  logger.info('Asset ownership has been created.\n%s', response)

更新資產的比對政策

建立參照之前,程式碼也必須更新與資產相關聯的 assetMatchPolicy 資源,藉此設定資產的比對政策。資產的比對政策會決定 YouTube 偵測到與資產相關聯的參考檔案符合時,會採取什麼行動。本例建立簡單的政策,追蹤全球任何超過 10 秒的相符項目。

def _create_match_policy(service, asset_id):
  match_policy_service = service.assetMatchPolicy()
  everywhere_policy_condition = {
      'requiredTerritories': {
          'type': 'exclude', 'territories': []},
      'requiredReferenceDuration': [{'low': 10}],
      'contentMatchType': 'video'}
  track_everywhere_rule = {
      'action': 'track',
      'condition': everywhere_policy_condition}
  request = match_policy_service.update(
      assetId=asset_id,
      body={
        'name': 'Track Everywhere 10s.',
        'description': 'Track Everywhere matches longer than 10s.',
        'rules': [track_everywhere_rule]})
  response = request.execute()
  logger.info('Asset match policy has been created.\n%s', response)

上傳參考文件

assetownershipassetMatchPolicy 準備就緒後,指令碼就會上傳 reference。並使用 MediaFileUpload 方法,以便利用支援續傳的上傳作業。請注意,reference_file 參數會指定要上傳的本機檔案名稱,並使用 reference_file 指令列選項將該值傳遞至指令碼。

def _create_reference(service, asset_id, reference_file):
  reference_service = service.reference()
  media = MediaFileUpload(reference_file, resumable=True)
  request = reference_service.insert(
      body={'assetId': asset_id, 'contentType': 'video'},
      media_body=media)
  status, response = request.next_chunk()
  while response is None:
    status, response = request.next_chunk()
    if status:
      logger.info("Uploaded %d%%.", int(status.progress() * 100))
  logger.info('Reference has been created.\n%s', response)
    

Full code sample

The complete working sample asset_reference_upload_example.py is listed below:

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Simple command-line sample for Youtube partner API.

Command-line application that creates asset, asset ownership, match policy
and reference.

Usage:
  $ python asset_reference_upload_example.py --reference_file=REFERENCE_FILE \
      --asset_title=ASSET_TITLE --owner=OWNER

You can also get help on all the command-line flags the program understands
by running:

  $ python asset_reference_upload_example.py --help
"""

__author__ = 'mateuszz+pub@google.com (Mateusz Zięba)'

import httplib2
import logging
import sys
import optparse
import os

from apiclient.discovery import build
from apiclient.errors import HttpError
from apiclient.http import MediaFileUpload
from oauth2client.file import Storage
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.tools import run

# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the Google API Console at
# https://console.cloud.google.com/.
# See the "Registering your application" instructions for an explanation
# of how to find these values:
# https://developers.google.com/youtube/partner/guides/registering_an_application
CLIENT_SECRETS = 'client_secrets.json'

# Helpful message to display if the CLIENT_SECRETS file is missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0

To make this sample run you need to populate the client_secrets.json
file found at:

%s

with information from the API Console
<https://console.cloud.google.com/>.

""" % os.path.join(os.path.dirname(__file__), CLIENT_SECRETS)

# Set up a Flow object to be used if we need to authenticate.
FLOW = flow_from_clientsecrets(CLIENT_SECRETS,
           scope='https://www.googleapis.com/auth/youtubepartner',
           message=MISSING_CLIENT_SECRETS_MESSAGE)

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())


def _create_asset(service, title, metadata_type):
  metadata = {'title': title}
  asset_body = {'metadata': metadata, 'type': metadata_type}
  # Retrieve asset service.
  asset_service = service.assets()

  # Create and execute insert request.
  request = asset_service.insert(body=asset_body)
  response = request.execute()
  logger.info('Asset has been created.\n%s', response)
  asset_id = response['id']
  return asset_id


def _create_asset_ownership(service, asset_id, owner_name):
  ownership = {
      'owner': owner_name,
      'ratio' : 100,
      'type': 'include',
      'territories': ['PL', 'GB']}
  ownership_body = {'general': [ownership]}
  ownership_service = service.ownership()

  request = ownership_service.update(assetId=asset_id, body=ownership_body)
  response = request.execute()
  logger.info('Asset ownership has been created.\n%s', response)


def _create_match_policy(service, asset_id):
  match_policy_service = service.assetMatchPolicy()
  everywhere_policy_condition = {
      'requiredTerritories': {
          'type': 'exclude', 'territories': []},
      'requiredReferenceDuration': [{'low': 10}],
      'contentMatchType': 'video'}
  track_everywhere_rule = {
      'action': 'track',
      'condition': everywhere_policy_condition}
  request = match_policy_service.update(
      assetId=asset_id,
      body={
        'name': 'Track Everywhere 10s.',
        'description': 'Track Everywhere matches longer than 10s.',
        'rules': [track_everywhere_rule]})
  response = request.execute()
  logger.info('Asset match policy has been created.\n%s', response)


def _create_reference(service, asset_id, reference_file):
  reference_service = service.references()
  media = MediaFileUpload(reference_file, resumable=True)
  request = reference_service.insert(
      body={'assetId': asset_id, 'contentType': 'video'},
      media_body=media)
  status, response = request.next_chunk()
  while response is None:
    status, response = request.next_chunk()
    if status:
      logger.info("Uploaded %d%%.", int(status.progress() * 100))
  logger.info('Reference has been created.\n%s', response)


def _parse_options():
  parser = optparse.OptionParser(
      description='Creates asset, asset ownership, match policy and reference.')
  parser.add_option('--version',
                    default='v1',
                    type=str, help='API version.')
  parser.add_option('--reference_file', type=str,
                    help='File containing reference to be uploaded. Required')
  parser.add_option('--asset_title',
                    type=str, help='Asset title. Required')
  parser.add_option('--owner',
                    type=str, help='Content owner name. Required')
  (options, args) = parser.parse_args()

  if not options.reference_file:
    parser.error("--reference_file is required")
  if not options.asset_title:
    parser.error("--asset_title is required")
  if not options.owner:
    parser.error("--owner is required")
  return options


def main(argv):
  options = _parse_options()
  # If the Credentials don't exist or are invalid run through the native client
  # flow. The Storage object ensures that if successful the good
  # Credentials are written back to a file.
  storage = Storage('yt_partner_api.dat')
  credentials = storage.get()
  if credentials is None or credentials.invalid:
    credentials = run(FLOW, storage)

  # Create an httplib2.Http object to handle our HTTP requests and authorize it
  # with our good Credentials.
  http = httplib2.Http()
  http = credentials.authorize(http)

  service = build("youtubePartner", options.version, http=http, static_discovery=False)

  try:
    asset_id = _create_asset(service, options.asset_title, 'web')
    _create_asset_ownership(service, asset_id, options.owner)
    _create_match_policy(service, asset_id)
    _create_reference(service, asset_id, options.reference_file)

  except AccessTokenRefreshError:
    logger.info("The credentials have been revoked or expired, please re-run"
      " the application to re-authorize")

if __name__ == '__main__':
  main(sys.argv)