참고: YouTube Content ID API는 YouTube 콘텐츠 파트너용이며 모든 개발자나 모든 YouTube 사용자가 액세스할 수 있는 것은 아닙니다. YouTube Content ID API가 Google 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를 사용하려면 인증을 수행하려면 API 콘솔의 정보가 포함된 client_secrets.json
파일이 필요합니다. 또한 애플리케이션을 등록해야 합니다. 인증이 작동하는 방법에 대한 자세한 설명은 인증 가이드를 참조하세요.
{ "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
객체 만들기 및 사용자 인증 정보 연결
사용자가 스크립트를 승인하면 API 요청을 처리하는 httplib2.Http
객체를 만들고 해당 객체에 승인 사용자 인증 정보를 첨부합니다.
다음 import 문을 추가합니다.
import httplib2
그리고 다음 코드를 main
함수 끝에 추가합니다.
# Create httplib2.Http object to handle HTTP requests and # attach auth credentials. http = httplib2.Http() http = credentials.authorize(http)
서비스 가져오기
승인에 성공하면 코드는 실행할 작업에 필요한 서비스를 가져옵니다. 먼저 모든 YouTube Content ID API 서비스에 대한 액세스를 제공하는 service
객체를 만듭니다. 그런 다음 코드는 service
객체를 사용하여 이 객체가 호출하는 4개의 리소스별 서비스를 가져옵니다.
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에 있는 동영상이 해당 저작물과 연결된 참조와 일치하는 것으로 확인되면 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)