#!/usr/bin/python '''Uploads a video to YouTube.''' from http import client import httplib2 import os import random import time import json import google.oauth2.credentials import google_auth_oauthlib.flow from googleapiclient.discovery import build from googleapiclient.errors import HttpError from googleapiclient.http import MediaFileUpload from google_auth_oauthlib.flow import InstalledAppFlow httplib2.RETRIES = 1 MAX_RETRIES = 10 RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, client.NotConnected, client.IncompleteRead, client.ImproperConnectionState, client.CannotSendRequest, client.CannotSendHeader, client.ResponseNotReady, client.BadStatusLine) RETRIABLE_STATUS_CODES = [500, 502, 503, 504] CLIENT_SECRETS_FILE = 'env/client_secret.json' SCOPES = ['https://www.googleapis.com/auth/youtube.upload', 'POST https://www.googleapis.com/upload/youtube/v3/thumbnails/set', 'https://www.googleapis.com/auth/youtube.force-ssl'] API_SERVICE_NAME = 'youtube' API_VERSION = 'v3' VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted') # Authorize the request and store authorization credentials. def get_authenticated_service(): if os.path.exists('env/credentials.json'): with open('env/credentials.json') as json_file: data = json.load(json_file) credentials = google.oauth2.credentials.Credentials( token=data['token'], refresh_token=data['refresh_token'], token_uri=data['token_uri'], client_id=data['client_id'], client_secret=data['client_secret'], scopes=data['scopes'] ) else: flow = InstalledAppFlow.from_client_secrets_file( CLIENT_SECRETS_FILE, SCOPES) credentials = flow.run_local_server() with open('env/credentials.json', 'w') as outfile: outfile.write(credentials.to_json()) return build(API_SERVICE_NAME, API_VERSION, credentials=credentials) def initialize_upload(youtube, options): tags = None if options['keywords']: tags = options['keywords'].split(',') body = dict( snippet=dict( title=options['title'], description=options['description'], tags=tags, categoryId=options['category'] ), status=dict( privacyStatus=options['privacyStatus'] ) ) # Call the API's videos.insert method to create and upload the video. insert_request = youtube.videos().insert( part=','.join(body.keys()), body=body, media_body=MediaFileUpload(options['file'], chunksize=-1, resumable=True) ) resumable_upload(insert_request) def resumable_upload(request): response = None error = None retry = 0 while response is None: try: print('Uploading file...') status, response = request.next_chunk() if response is not None: if 'id' in response: print('Video id "%s" was successfully uploaded.' % response['id']) else: exit('The upload failed with an unexpected response: %s' % response) 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: print(error) retry += 1 if retry > MAX_RETRIES: exit('No longer attempting to retry.') max_sleep = 2 ** retry sleep_seconds = random.random() * max_sleep print('Sleeping %f seconds and then retrying...' % sleep_seconds) time.sleep(sleep_seconds) if __name__ == '__main__': sample_options = { 'file': './test.mp4', 'title': 'Test Title', 'description': 'Test Description', 'category': 22, 'keywords': 'test, video', 'privacyStatus': 'private' } youtube = get_authenticated_service() try: initialize_upload(youtube, sample_options) except HttpError as e: print('An HTTP error %d occurred:\n%s' % (e.resp.status, e.content))