前回の記事(pythonでログ出力(loggingモジュール))では、
pythonでのログ出力と例外処理の継続処理を作成しました。
今回は、YouTubeAPIを利用したpythonによる動画のアップロードを
作成したいと思います。
このプログラムで出来る様になること
Youtubeの画面操作無しで、動画を投稿できるようになります。
さらにこのプログラムを応用することで、複数の動画を連続でアップロードしたり、 アップロード の自動化も望めます。
実際にアップロードした内容は以下です。130本近くの動画を再生リスト化しています。
手動でやった場合、数日作業になりますが、ここで作成するプログラムと他で作成しているプログラムの定期実行などと組み合わせれば、全て自動で行うことが可能です。

pythonのソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
import http.client import httplib2 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 argparser, run_flow # 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, http.client.NotConnected, http.client.IncompleteRead, http.client.ImproperConnectionState, http.client.CannotSendRequest, http.client.CannotSendHeader, http.client.ResponseNotReady, http.client.BadStatusLine) # Always retry when an apiclient.errors.HttpError with one of these status # codes is raised. RETRIABLE_STATUS_CODES = [500, 502, 503, 504] # 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.developers.google.com/. # Please ensure that you have enabled the YouTube Data API for your project. # For more information about using OAuth2 to access the YouTube Data API, see: # https://developers.google.com/youtube/v3/guides/authentication # For more information about the client_secrets.json file format, see: # https://developers.google.com/api-client-library/python/guide/aaa_client_secrets CLIENT_SECRETS_FILE = "client_secrets.json" # This OAuth 2.0 access scope allows an application to upload files to the # authenticated user's YouTube channel, but doesn't allow other types of access. YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload" YOUTUBE_API_SERVICE_NAME = "youtube" YOUTUBE_API_VERSION = "v3" # This variable defines a 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 will need to populate the client_secrets.json file found at: %s with information from the API Console https://console.developers.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)) VALID_PRIVACY_STATUSES = ("public", "private", "unlisted") def get_authenticated_service(args): flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_UPLOAD_SCOPE, message=MISSING_CLIENT_SECRETS_MESSAGE) storage = Storage("%s-oauth2.json" % sys.argv[0]) credentials = storage.get() if credentials is None or credentials.invalid: credentials = run_flow(flow, storage, args) return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, http=credentials.authorize(httplib2.Http())) 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, # The chunksize parameter specifies the size of each chunk of data, in # bytes, that will be uploaded at a time. Set a higher value for # reliable connections as fewer chunks lead to faster uploads. Set a lower # value for better recovery on less reliable connections. # # Setting "chunksize" equal to -1 in the code below 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) ) resumable_upload(insert_request) # This method implements an exponential backoff strategy to resume a # failed upload. def resumable_upload(insert_request): response = None error = None retry = 0 while response is None: try: print("Uploading file...") status, response = insert_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__': argparser.add_argument("--file", required=True, help="Video file to upload") argparser.add_argument("--title", help="Video title", default="Test Title") argparser.add_argument("--description", help="Video description", default="Test Description") argparser.add_argument("--category", default="10", help="Numeric video category. " + "See https://developers.google.com/youtube/v3/docs/videoCategories/list") argparser.add_argument("--keywords", help="Video keywords, comma separated", default="") argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES, default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.") args = argparser.parse_args() if not os.path.exists(args.file): exit("Please specify a valid file using the --file= parameter.") youtube = get_authenticated_service(args) try: initialize_upload(youtube, args) except HttpError as e: print("An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)) |
同じ内容をこちらにも記載しています。
基本的に、公式HPの内容をコピーして流用(※1)しています。
python3の環境であれば、ソースコードをそのままコピーすれば
利用できるはずです。(※2)
(動画のカテゴリは「音楽」、公開設定は「公開」でアップロードされます。)
(※1)公式HPのソースコードはpython2で書かれており、
私の環境はpython3.8なので、次の点を公式HPの内容から修正しています。
・import httplibをimport http.clientへ。
(httplib モジュールは、Python 3.0 では http.client に
リネームされました。参考にしたサイトはこちら)
・print “***” という記述をprint(“***”)記載へ。
・except ***Error , e: という記述をexcept HttpError as e:へ。
(※2)下記、事前準備有。
事前準備
次のコマンドでモジュールをインストールすることに加え、必要に応じて、足りないモジュールのインポートを行ってください。
1 2 |
pip install --upgrade google-api-python-client pip install oauth2client |
client_secrets.jsonファイルの準備
client_secrets.jsonファイルを準備して、 pythonのソースコードと同じフォルダに配置する必要があります。
手順は、次の4ステップです。
1.Google API コンソールでプロジェクトを 作成 。
2.プロジェクト内で「 YouTube Data API v3」を有効化。
3.認証情報を作成 。
4.認証情報をJSONとしてダウンロードし、「 client_secrets.json 」
と言う名前で pythonのソースコードと同じフォルダに配置 。
Google API コンソールでプロジェクトを 作成
Google API Console に移動します。[プロジェクトを作成] をクリックし、名前を入力して、[作成] をクリックします。
YouTube Data API v3を有効化
プロジェクトで Google Ads API を有効にする方法は、次のとおりです。
1.Google API コンソールで API ライブラリを開きます。プロンプトが表示されたら、プロジェクトのいずれかを選択するか、新しいプロジェクトを作成します。API ライブラリには、利用できるすべての API がプロダクト ファミリーと人気度によって分類され、表示されます。
2.リストに表示されない場合は、検索を使用して Google Ads API を見つけます。
3.API を選択し、[有効にする] ボタンをクリックします。
Google Ads API に Google API Console プロジェクトを設定する
認証情報を作成
[認証情報] ページから以下の手順を実行します。
1.[認証情報を作成] をクリックし、[OAuth クライアント ID] を選択します。
はじめてのアナリティクス API: インストール済みアプリケーション向け Python クイック スタート
2.[アプリケーションの種類] で [その他] を選択します。
3.認証情報の名前を指定します。
4.[作成] をクリックします。
認証情報のダウンロード
[認証情報] ページから 作成した認証情報を選択し、[JSON をダウンロード] をクリックします。
プログラムの実行
次のバッチ(youtubeUpload.py.bat)を、
pythonのソースコード「youtubeUpload.py」と
同じフォルダに配置して実行します。
なお、初めて実行した際に、ブラウザに遷移してGoogleアカウントの選択とYouTubeの管理許可を求める画面が表示されるので、画面に従って
許可する必要があります。
◆ youtubeUpload.py.bat の内容
1 2 3 |
python %~n0 --file [アップロードするファイルのパス] --noauth_local_webserver --title [動画のタイトル] --description [動画の説明] --keywords [動画のタグ] pause |
ソースコードのチューニングについて
前述の通り、今回紹介したソースコードは、 動画のカテゴリは「音楽」、
公開設定は「公開」でアップロードされます。
こちらの修正方法を記載します。
動画のカテゴリの変更方法
ソースコード内の以下の数値部分を修正します。
(設定する値は表を参照。)argparser.add_argument("--category", default="10"
id | カテゴリ |
1 | 映画とアニメ |
2 | 自動車と乗り物 |
10 | 音楽 |
15 | ペットと動物 |
17 | スポーツ |
19 | 旅行とイベント |
20 | ゲーム |
22 | ブログ |
23 | コメディー |
24 | エンターテイメント |
25 | ニュースと政治 |
26 | ハウツーとスタイル |
27 | 教育 |
28 | 科学と技術 |
公開設定の変更方法
やり方1: youtubeUpload.py.bat 内のpythonコマンドに--privacyStatus
[公開レベル] のオプションを付与する。
やり方2:VALID_PRIVACY_STATUSES[0]
を別の値に書き換える。
公開レベルについて
・public・・・公開
・private・・・非公開
・unlisted ・・・限定公開
VALID_PRIVACY_STATUSES について
次の値を持つようです。
VALID_PRIVACY_STATUSES = (“public”,”private”,”unlisted”)
例えば動画を限定公開にしたい場合、
VALID_PRIVACY_STATUSES[0] を VALID_PRIVACY_STATUSES[1] にします。
YouTube Data API v3 の制限について
無料アカウントの場合、1日6本までのアップロード制限があります。
詳しくはこちらに記載があります。(クォータの使用量)
簡単に解説すると、一日の使用制限が10000なのに対して、
動画1本のアップロードに1600消化する為、6本で9600が消化されてしまいます。
7本目をアップロードしようとした場合、次の様なメッセージが出力されます。
1 2 |
An HTTP error 403 occurred: The request cannot be completed because you have exceeded your XXX |
コメント