注意:YouTube Content ID API 供 YouTube 內容合作夥伴使用,僅供部分開發人員或 YouTube 使用者存取。如果您在 Google API 控制台中並未看到 YouTube Content ID API 提供服務,請參閱 YouTube 說明中心,進一步瞭解 YouTube 合作夥伴計畫。
這個程式碼範例示範如何使用 YouTube Content ID API 上傳 reference
。如要上傳reference
,請先建立asset
,並設定資產的擁有權和比對政策。這個範例會逐步引導您完成所有步驟。
本範例包含一系列步驟,以及程式碼的相關部分。你可以在本頁結尾找到完整指令碼。程式碼是以 Python 編寫。此外,我們也提供其他熱門程式設計語言的用戶端程式庫。
範例指令碼不會處理任何錯誤,
需求條件
- Python 2.5 以上版本
- google-api-python-client
在這個步驟中,我們會在指令碼中加入 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)
上傳參考資料
asset
、ownership
和 assetMatchPolicy
就緒後,指令碼會上傳 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__ = '[email protected] (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)