Nota: La API de YouTube Data está diseñada para que la usen los socios de contenido de YouTube y no es accesible para todos los desarrolladores ni para todos los usuarios de YouTube. Para acceder, se requiere una cuenta del Administrador de contenido de YouTube. Si tienes una cuenta de Administrador de contenido de YouTube, pero no ves la API de YouTube Data como uno de los servicios que se enumeran en la consola de Google Cloud, comunícate con tu administrador de socios o el equipo de asistencia para socios asignado.
En esta muestra de código, se muestra cómo subir un video de YouTube y aplicarle una política de monetización. Para monetizar un video, debes reclamarlo con un asset en el sistema de administración de derechos de YouTube. El ejemplo sube el video, crea un nuevo elemento, reclama el video con el elemento y aplica una política de monetización al video.
Este ejemplo se presenta como una serie de pasos a seguir, asociada a las secciones pertinentes del código. Puedes encontrar la secuencia de comandos completa al final de esta página. El código está escrito en Python. (También hay bibliotecas cliente disponibles para otros lenguajes de programación populares).
Requisitos
- Python 3.7 o una versión posterior
- google-api-python-client
Paso 1: Funciones de limpieza comunes
Las primeras secciones de la muestra de código realizan funciones básicas de administración que son comunes a muchas secuencias de comandos: analizan la línea de comandos, autentican al usuario y obtienen los servicios de API necesarios.
Analiza la línea de comandos
El método parse_options usa OptionParser de la biblioteca cliente de Python para crear un objeto options que contiene cada argumento de la línea de comandos como una propiedad. Los métodos posteriores recuperan valores del objeto options según sea necesario.
Los argumentos de la línea de comandos de la secuencia de comandos de ejemplo se enumeran a continuación. Los primeros dos (file y channelId) son obligatorios; el resto son opcionales.
-
file: Nombre y ubicación del archivo de video que se subirá.Example: --file="/home/path/to/file.mov"
-
channelId: Es el canal de YouTube al que quieres subir el video. El canal debe ser administrado por la cuenta de Administrador de contenido de YouTube del usuario autenticado. Puedes recuperar el ID del canal en la configuración de la cuenta de YouTube del usuario autenticado o con el métodochannels.list.Example: --channelId="UC_x5XG1OV2P6uZZ5FSM9Ttw"
-
title: Título del video que subirás. El valor predeterminado esTest title.Example: --title="Summer vacation in California"
-
description: Es una descripción del video que subes. El valor predeterminado esTest description.Example: --description="Had a great time surfing in Santa Cruz"
-
category: Es el ID de la categoría de video de YouTube asociada al video. El valor predeterminado es22, que hace referencia a la categoríaPeople & Blogs.Example: --category=22
-
keywords: Es una lista separada por comas de palabras clave asociadas con el video. El valor predeterminado es una string vacía.Example: --keywords="surfing, beach volleyball"
-
privacyStatus: Es el estado de privacidad del video. El comportamiento predeterminado es que un video subido sea visible de forma pública (public). Cuando subas videos de prueba, es posible que desees especificar un valor de argumento--privacyStatuspara asegurarte de que esos videos sean privados o no listados. Los valores válidos sonpublic,privateyunlisted.Example: --privacyStatus="private"
-
policyId: Es la política de monetización que se aplicará al video subido. La política debe estar asociada a la cuenta de Administrador de contenido de YouTube del usuario autenticado. El valor predeterminado es la política estándar de YouTube "monetizar".Example: --policyId="S309961703555739"
def parse_options(): parser = argparse.ArgumentParser( description="Uploads and claims a video on YouTube.") parser.add_argument("--file", required=True, help="Video file to upload") parser.add_argument("--title", default="Test Title", help="Video title") parser.add_argument("--description", default="Test Description", help="Video description") parser.add_argument("--category", default="22", help="Numeric video category. See https://developers.google.com/youtube/v3/docs/videoCategories/list") parser.add_argument("--keywords", default="", help="Video keywords, comma separated") parser.add_argument("--privacyStatus", default="public", choices=["public", "private", "unlisted"], help="Video privacy status: public, private or unlisted") parser.add_argument("--policyId", help="Optional id of a saved claim policy") parser.add_argument("--channelId", required=True, help="Id of the channel to upload to. Must be managed by your CMS account") return parser.parse_args()
Autoriza la solicitud
En este paso, incorporamos la autorización OAuth 2.0 en la secuencia de comandos. Esto permite que el usuario que ejecuta la secuencia de comandos autorice que esta realice solicitudes de API atribuidas a la cuenta del usuario.
Creación de un archivo client_secrets.json
El tipo de autorización que se muestra en el ejemplo requiere un archivo client_secrets.json, que contiene información de la consola de Google Cloud, para realizar la autorización. También debes registrar tu aplicación. Para obtener una explicación más completa sobre cómo funciona la autorización, consulta la guía de autorización. Ten en cuenta que esta muestra requiere que tanto la API de YouTube Data v3 como el servicio de la API de Content ID de YouTube estén configurados en la consola de Cloud para tu proyecto.
{ "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" } }
Código de autorización en la secuencia de comandos
La secuencia de comandos incluye estas instrucciones import para habilitar la autenticación y autorización de usuarios:
from oauth2client.file import Storage from oauth2client.client import flow_from_clientsecrets from oauth2client.tools import run
A continuación, el método get_authenticated_services crea un objeto FLOW con los datos del archivo client_secrets.json configurado en el paso anterior. Si el usuario autoriza a nuestra aplicación a enviar solicitudes a la API en su nombre, las credenciales resultantes se almacenan en un objeto Storage para su uso posterior. El usuario debe volver a autorizar nuestra aplicación si vencen las credenciales.
YOUTUBE_SCOPES = ( # An OAuth 2 access scope that allows for full read/write access. "https://www.googleapis.com/auth/youtube", # A scope that grants access to YouTube Partner API functionality. "https://www.googleapis.com/auth/youtubepartner") flow = flow_from_clientsecrets( CLIENT_SECRETS_FILE, scope=" ".join(YOUTUBE_SCOPES), message=MISSING_CLIENT_SECRETS_MESSAGE ) storage = Storage(CACHED_CREDENTIALS_FILE) credentials = storage.get() if credentials is None or credentials.invalid: credentials = run(flow, storage)
Obtén servicios
Después de que la autorización se realice correctamente, se deben obtener los servicios necesarios para las operaciones que queremos realizar. El ejemplo utiliza la API de datos de YouTube para subir el video y la API de Content ID de YouTube para crear el elemento y reclamar el video. Creamos servicios separados para proporcionar acceso autorizado a la funcionalidad de las dos APIs.
from googleapiclient.discovery import build import httplib2 YOUTUBE_API_SERVICE_NAME = "youtube" YOUTUBE_API_VERSION = "v3" YOUTUBE_CONTENT_ID_API_SERVICE_NAME = "youtubePartner" YOUTUBE_CONTENT_ID_API_VERSION = "v1" youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, http=credentials.authorize(httplib2.Http())) youtube_partner = build(YOUTUBE_CONTENT_ID_API_SERVICE_NAME, YOUTUBE_CONTENT_ID_API_VERSION, http=credentials.authorize(httplib2.Http()), static_discovery=False) return (youtube, youtube_partner)
Paso 2: Identifica al propietario del contenido
El usuario autenticado debe tener una cuenta de Administrador de contenido de YouTube para crear elementos y efectuar reclamos. La cuenta de Administrador de contenido contiene los objetos de administración de derechos de uno o más propietarios de contenido. El propietario del contenido es el propietario de los derechos de autor que tiene el derecho de decidir si se debe monetizar, realizar seguimiento o bloquear un video.
El método get_content_owner recupera el ID del propietario del contenido en la cuenta del Administrador de contenido del usuario autenticado. La mayoría de las cuentas tienen solo un propietario del contenido (el usuario autenticado), pero si la cuenta tiene varios propietarios de contenido, el método muestra el primero de ellos.
def get_content_owner_id(youtube_partner): try: content_owners_list_response = youtube_partner.contentOwners().list( fetchMine=True ).execute() except HttpError as e: if INVALID_CREDENTIALS in e.content: logging.error("The request is not authorized by a Google Account that " "is linked to a YouTube content owner. Please delete '%s' and " "re-authenticate with a YouTube content owner account." % CACHED_CREDENTIALS_FILE) exit(1) else: raise # This returns the CMS user id of the first entry returned # by youtubePartner.contentOwners.list() # See https://developers.google.com/youtube/partner/reference/rest/v1/contentOwners/list # Normally this is what you want, but if you authorize with a Google Account # that has access to multiple YouTube content owner accounts, you need to # iterate through the results. return content_owners_list_response["items"][0]["id"]
Paso 3: Sube el video
Para subir un video, compilamos un recurso JSON parcial que representa el video y lo pasamos al método videos.insert. Configuramos los metadatos del video con los valores del objeto options que se creó cuando analizamos la línea de comandos. Para el archivo multimedia en sí, usamos MediaFileUpload para poder usar la carga reanudable. Consulta Cómo subir un video para obtener más detalles.
El método upload devuelve el ID del video nuevo, y la secuencia de comandos debe pasar ese valor a otros métodos en pasos posteriores.
def upload(youtube, content_owner_id, options): if options.keywords: tags = options.keywords.split(",") else: tags = None insert_request = youtube.videos().insert( onBehalfOfContentOwner=content_owner_id, onBehalfOfContentOwnerChannel=options.channelId, part="snippet,status", body=dict( snippet=dict( title=options.title, description=options.description, tags=tags, categoryId=options.category ), status=dict( privacyStatus=options.privacyStatus ) ), # chunksize=-1 means that the entire file will be uploaded in a single # HTTP request. (If the upload fails, it will still be retried where it # left off.) media_body=MediaFileUpload(options.file, chunksize=-1, resumable=True) ) response = None error = None retry = 0 duration_seconds=0 while response is None: try: logging.debug("Uploading file...") start_seconds = time.time() status, response = insert_request.next_chunk() delta_seconds = time.time() - start_seconds duration_seconds += delta_seconds if "id" in response: return (response["id"], duration_seconds) else: logging.error("The upload failed with an unexpected response: %s" % response) exit(1) except HttpError as e: if e.resp.status in RETRIABLE_STATUS_CODES: error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status, e.content) else: raise except RETRIABLE_EXCEPTIONS as e: error = "A retriable error occurred: %s" % e if error is not None: logging.error(error) retry += 1 if retry > MAX_RETRIES: logging.error("No longer attempting to retry.") exit(1) max_sleep = 2 ** retry sleep_seconds = random.random() * max_sleep logging.debug("Sleeping %f seconds and then retrying..." % sleep_seconds) time.sleep(sleep_seconds)
Paso 4: Crea un activo
Para monetizar un video de YouTube, es necesario asociarlo antes con un elemento. El método create_asset crea un activo nuevo para el video recién subido.
Al igual que con el video, compilamos un recurso JSON parcial que identifica el tipo de elemento a crear (un video web) y proporciona un título y una descripción para el elemento nuevo. Pasamos el recurso JSON al método assets.insert, que crea el activo y devuelve su ID único. Nuevamente, la secuencia de comandos debe pasar ese valor a otros métodos en pasos posteriores.
def create_asset(youtube_partner, content_owner_id, title, description): # This creates a new asset corresponding to a video on the web. # The asset is linked to the corresponding YouTube video via a # claim that will be created later. body = dict( type="web", metadata=dict( title=title, description=description ) ) assets_insert_response = youtube_partner.assets().insert( onBehalfOfContentOwner=content_owner_id, body=body ).execute() return assets_insert_response["id"]
Paso 5: Actualiza la propiedad
Antes de poder monetizar un video, se debe informar a YouTube sobre quién es el propietario del elemento asociado. Entonces, con el recurso creado, ahora configuramos el ownership del recurso. En el ejemplo, se especifica que el propietario del contenido es el propietario del elemento en todo el mundo.
def set_asset_ownership(youtube_partner, content_owner_id, asset_id): # This specifies that content_owner_id owns 100% of the asset worldwide. # Adjust as needed. body = dict( general=[dict( owner=content_owner_id, ratio=100, type="exclude", territories=[] )] ) youtube_partner.ownership().update( onBehalfOfContentOwner=content_owner_id, assetId=asset_id, body=body ).execute()
Paso 6: Reclama el video
El siguiente paso es asociar el video subido con su elemento correspondiente reclamando el video. El reclamo proporciona el vínculo entre el video y el sistema de administración de derechos de YouTube, que establece la propiedad del video y permite que el propietario establezca una política de monetización.
El método claim_video reclama derechos audiovisuales. Si incluyes el parámetro policyId en la línea de comandos, el método aplica la política especificada al video. Si no lo incluyes, el método aplica la política estándar de "monetización".
def claim_video(youtube_partner, content_owner_id, asset_id, video_id, policy_id): # policy_id can be set to the id of an existing policy, which can be obtained # via youtubePartner.policies.list() # See https://developers.google.com/youtube/partner/reference/rest/v1/policies/list # If you later update that existing policy, the claim will also be updated. if policy_id: policy = dict( id=policy_id ) # If policy_id is not provided, a new inline policy is created. else: policy = dict( rules=[dict( action="monetize" )] ) body = dict( assetId=asset_id, videoId=video_id, policy=policy, contentType="audiovisual" ) youtube_partner.claims().insert( onBehalfOfContentOwner=content_owner_id, body=body ).execute()
Paso 7: Establece las opciones de publicidad
Ya reclamamos el video y le aplicamos una política de monetización. El último paso consiste en especificar qué tipo de anuncios se va a mostrar en el video. Cada vez que se aplica la política "monetizar", YouTube comprueba las opciones de anuncios y muestra el tipo de anuncios con los ingresos más altos que esté disponible.
La muestra le indica a YouTube que muestre anuncios in-stream TrueView con este video.
def set_advertising_options(youtube_partner, content_owner_id, video_id): # This enables the TrueView ad format for the given video. # Adjust as needed. body = dict( adFormats=["trueview_instream"] ) youtube_partner.videoAdvertisingOptions().update( videoId=video_id, onBehalfOfContentOwner=content_owner_id, body=body ).execute()
Muestra de código completa
A continuación, se incluye el ejemplo de trabajo completo upload_monetize_video_example.py:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright 2014 Google Inc. All Rights Reserved. # # 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 an asset, uploads and claims a video for that asset. Usage: $ python3 upload_monetize_video_example.py --file=VIDEO_FILE --channelId=CHANNEL_ID \\ [--title=VIDEO_TITLE] [--description=VIDEO_DESCRIPTION] [--category=CATEGORY_ID] \\ [--keywords=KEYWORDS] [--privacyStatus=PRIVACY_STATUS] [--policyId=POLICY_ID] You can also get help on all the command-line flags the program understands by running: $ python3 upload_monetize_video_example.py --help """ __author__ = 'jeffy+pub@google.com (Jeffrey Posnick)' import argparse import http.client as httplib import httplib2 import logging import os import random import sys import time from apiclient.discovery import build from apiclient.errors import HttpError from apiclient.http import MediaFileUpload from oauth2client.client import flow_from_clientsecrets from oauth2client.file import Storage from oauth2client.tools import run # Explicitly tell the underlying HTTP transport library not to retry, since # we are handling retry logic ourselves. httplib2.RETRIES = 1 # Maximum number of times to retry before giving up. MAX_RETRIES = 10 # Always retry when these exceptions are raised. RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected, httplib.IncompleteRead, httplib.ImproperConnectionState, httplib.CannotSendRequest, httplib.CannotSendHeader, httplib.ResponseNotReady, httplib.BadStatusLine,) # Always retry when an apiclient.errors.HttpError with one of these status # codes is raised. RETRIABLE_STATUS_CODES = (500, 502, 503, 504,) # The message associated with the HTTP 401 error that's returned when a request # is authorized by a user whose account is not associated with a YouTube # content owner. INVALID_CREDENTIALS = "Invalid Credentials" # 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 Cloud 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 # For more information about using OAuth2 to access Google APIs, please visit: # https://developers.google.com/accounts/docs/OAuth2 # For more information about the client_secrets.json file format, please visit: # https://developers.google.com/api-client-library/python/guide/aaa_client_secrets CLIENT_SECRETS_FILE = "client_secrets.json" # The local file used to store the cached OAuth 2 credentials after going # through a one-time browser-based login. CACHED_CREDENTIALS_FILE = "%s-oauth2.json" % sys.argv[0] YOUTUBE_SCOPES = ( # An OAuth 2 access scope that allows for full read/write access. "https://www.googleapis.com/auth/youtube", # A scope that grants access to YouTube Partner API functionality. "https://www.googleapis.com/auth/youtubepartner",) YOUTUBE_API_SERVICE_NAME = "youtube" YOUTUBE_API_VERSION = "v3" YOUTUBE_CONTENT_ID_API_SERVICE_NAME = "youtubePartner" YOUTUBE_CONTENT_ID_API_VERSION = "v1" # 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 at: %s with information from the Cloud console https://console.cloud.google.com/ For more information about the client_secrets.json file format, please visit: https://developers.google.com/api-client-library/python/guide/aaa_client_secrets """ % os.path.abspath(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS_FILE)) def parse_options(): parser = OptionParser() parser.add_option("--file", dest="file", help="Video file to upload") parser.add_option("--title", dest="title", help="Video title", default="Test Title") parser.add_option("--description", dest="description", help="Video description", default="Test Description") parser.add_option("--category", dest="category", help="Numeric video category. " + "See https://developers.google.com/youtube/v3/docs/videoCategories/list", default="22") parser.add_option("--keywords", dest="keywords", help="Video keywords, comma separated", default="") parser.add_option("--privacyStatus", dest="privacyStatus", help="Video privacy status: public, private or unlisted", default="public") parser.add_option("--policyId", dest="policyId", help="Optional id of a saved claim policy") parser.add_option("--channelId", dest="channelId", help="Id of the channel to upload to. Must be managed by your CMS account") (options, args) = parser.parse_args() return options def get_authenticated_services(): flow = flow_from_clientsecrets( CLIENT_SECRETS_FILE, scope=" ".join(YOUTUBE_SCOPES), message=MISSING_CLIENT_SECRETS_MESSAGE ) storage = Storage(CACHED_CREDENTIALS_FILE) credentials = storage.get() if credentials is None or credentials.invalid: credentials = run(flow, storage) youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, http=credentials.authorize(httplib2.Http())) youtube_partner = build(YOUTUBE_CONTENT_ID_API_SERVICE_NAME, YOUTUBE_CONTENT_ID_API_VERSION, http=credentials.authorize(httplib2.Http()), static_discovery=False) return (youtube, youtube_partner) def get_content_owner_id(youtube_partner): try: content_owners_list_response = youtube_partner.contentOwners().list( fetchMine=True ).execute() except HttpError, e: if INVALID_CREDENTIALS in e.content: logging.error("Your request is not authorized by a Google Account that " "is associated with a YouTube content owner. Please delete '%s' and " "re-authenticate with an account that is associated " "with a content owner." % CACHED_CREDENTIALS_FILE) exit(1) else: raise # This returns the CMS user id of the first entry returned # by youtubePartner.contentOwners.list() # See https://developers.google.com/youtube/partner/reference/rest/v1/contentOwners/list # Normally this is what you want, but if you authorize with a Google Account # that has access to multiple YouTube content owner accounts, you need to # iterate through the results. return content_owners_list_response["items"][0]["id"] def upload(youtube, content_owner_id, options): if options.keywords: tags = options.keywords.split(",") else: tags = None insert_request = youtube.videos().insert( onBehalfOfContentOwner=content_owner_id, onBehalfOfContentOwnerChannel=options.channelId, part="snippet,status", body=dict( snippet=dict( title=options.title, description=options.description, tags=tags, categoryId=options.category ), status=dict( privacyStatus=options.privacyStatus ) ), # chunksize=-1 means that the entire file will be uploaded in a single # HTTP request. (If the upload fails, it will still be retried where it # left off.) This is usually a best practice, but if you're using Python # older than 2.6 or if you're running on App Engine, you should set the # chunksize to something like 1024 * 1024 (1 megabyte). media_body=MediaFileUpload(options.file, chunksize=-1, resumable=True) ) response = None error = None retry = 0 duration_seconds=0 while response is None: try: logging.debug("Uploading file...") start_seconds = time.time() status, response = insert_request.next_chunk() delta_seconds = time.time() - start_seconds duration_seconds += delta_seconds if "id" in response: return (response["id"], duration_seconds) else: logging.error("The upload failed with an unexpected response: %s" % response) exit(1) except HttpError, e: if e.resp.status in RETRIABLE_STATUS_CODES: error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status, e.content) else: raise except RETRIABLE_EXCEPTIONS, e: error = "A retriable error occurred: %s" % e if error is not None: logging.error(error) retry += 1 if retry > MAX_RETRIES: logging.error("No longer attempting to retry.") exit(1) max_sleep = 2 ** retry sleep_seconds = random.random() * max_sleep logging.debug("Sleeping %f seconds and then retrying..." % sleep_seconds) time.sleep(sleep_seconds) def create_asset(youtube_partner, content_owner_id, title, description): # This creates a new asset corresponding to a video on the web. # The asset is linked to the corresponding YouTube video via a # claim that will be created later. body = dict( type="web", metadata=dict( title=title, description=description ) ) assets_insert_response = youtube_partner.assets().insert( onBehalfOfContentOwner=content_owner_id, body=body ).execute() return assets_insert_response["id"] def set_asset_ownership(youtube_partner, content_owner_id, asset_id): # This specifies that content_owner_id owns 100% of the asset worldwide. # Adjust as needed. body = dict( general=[dict( owner=content_owner_id, ratio=100, type="exclude", territories=[] )] ) youtube_partner.ownership().update( onBehalfOfContentOwner=content_owner_id, assetId=asset_id, body=body ).execute() def claim_video(youtube_partner, content_owner_id, asset_id, video_id, policy_id): # policy_id can be set to the id of an existing policy, which can be obtained # via youtubePartner.policies.list() # See https://developers.google.com/youtube/partner/reference/rest/v1/policies/list # If you later update that existing policy, the claim will also be updated. if policy_id: policy = dict( id=policy_id ) # If policy_id is not provided, a new inline policy is created. else: policy = dict( rules=[dict( action="monetize" )] ) body = dict( assetId=asset_id, videoId=video_id, policy=policy, contentType="audiovisual" ) claims_insert_response = youtube_partner.claims().insert( onBehalfOfContentOwner=content_owner_id, body=body ).execute() return claims_insert_response["id"] def set_advertising_options(youtube_partner, content_owner_id, video_id): # This enables the true view ad format for the given video. # Adjust as needed. body = dict( adFormats=["trueview_instream"] ) youtube_partner.videoAdvertisingOptions().update( videoId=video_id, onBehalfOfContentOwner=content_owner_id, body=body ).execute() if __name__ == '__main__': logging.basicConfig( level=logging.DEBUG, format="%(asctime)s [%(name)s] %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) options = parse_options() if options.file is None or not os.path.exists(options.file): logging.error("Please specify a valid file using the --file= parameter.") exit(1) # The channel ID looks something like "UC..." and needs to correspond to a # channel managed by the YouTube content owner authorizing the request. # youtube.channels.list(part="snippet", managedByMe=true, # onBehalfOfContentOwner=*CONTENT_OWNER_ID*) # can be used to retrieve a list of managed channels and their channel IDs. # See https://developers.google.com/youtube/v3/docs/channels/list if options.channelId is None: logging.error("Please specify a channel ID via the --channelId= parameter.") exit(1) (youtube, youtube_partner) = get_authenticated_services() content_owner_id = get_content_owner_id(youtube_partner) logging.info("Authorized by content owner ID '%s'." % content_owner_id) (video_id, duration_seconds) = upload(youtube, content_owner_id, options) logging.info("Successfully uploaded video ID '%s'." % video_id) file_size_bytes = os.path.getsize(options.file) logging.debug("Uploaded %d bytes in %0.2f seconds (%0.2f megabytes/second)." % (file_size_bytes, duration_seconds, (file_size_bytes / (1024 * 1024)) / duration_seconds)) asset_id = create_asset(youtube_partner, content_owner_id, options.title, options.description) logging.info("Created new asset ID '%s'." % asset_id) set_asset_ownership(youtube_partner, content_owner_id, asset_id) logging.info("Successfully set asset ownership.") claim_id = claim_video(youtube_partner, content_owner_id, asset_id, video_id, options.policyId) logging.info("Successfully claimed video.") set_advertising_options(youtube_partner, content_owner_id, video_id) logging.info("Successfully set advertising options.") logging.info("All done!")