普通のシステムエンジニアの備忘録

きみひで と言います。個人勉強で触れた技術など備忘禄と時々日常を綴ります。

Django youtubeにアップロード する画面を作ってみよう

■目的

今目論んでいるアプリでは、ユーザーみんなで動画を共有出来たらいいなぁって考えてる。

ただ動画をサーバーにアップしてると容量も食うし、管理も大変そう。

なのでYoutubeにアップして、それのリンクをサイトでみられるようにする方針にしようと思う。

Youtubeをそのまま利用すればいいんじゃな?って意見もありそうですが、過去のデータとかを管理するのがやりにくそうなんで。

あとは純粋なAPIを使ってみたいと言う興味です!

 

■やってみよう

今回はこちらのサイトを参考にしました。

https://developers.google.com/youtube/v3/guides/uploading_a_video?hl=ja

 

どうやらAPIを使うにはGoogleのアカウントが必要らしい。

 

 

 

ログインして、以下に飛ぶ

https://console.developers.google.com/apis/

 

APIライブラリからYoutube Data API v3を有効化

 

f:id:kimihide1104:20190408205647p:plain

 

f:id:kimihide1104:20190408205549p:plain

次に認証情報の追加を求められるので入力してキー取得

 

f:id:kimihide1104:20190408210114p:plain


そこからさらに、使うドメインとか登録してOAuthクライアントIDを入手

 

f:id:kimihide1104:20190408212019p:plain

 

多分Googleアカウントの用意は出来たのでPythonさんにpip

pip install google-api-python-client

なんか古そうなのでこっちにした

google-api-python-client-py3

 

■上手くいかないので別のサイトを参考にしよう

https://qiita.com/mm_sys/items/4cd6822cbc59a9715ac7 

 

https://github.com/tokland/youtube-upload

 

 

■エラーは以下のような内容が出てた。


WARNING: Please configure OAuth 2.0

To make this sample run you will need to populate the client_secrets.json file
found at:

/Users/satoukinhide/PycharmProjects/django_app/sns/client_secret.json

with information from the Developers 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

 

Googleのブラウザから落としたJSONファイルに"redirect_uris": ""付け足したらエラーなくなった。

 

 

 

 

サンプルサイトのソースはPython2っぽかったので、Python3用にちょこちょこ変更した

#!/usr/bin/python

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, httplib2.NotConnected,
httplib2.IncompleteRead, httplib2.ImproperConnectionState,
httplib2.CannotSendRequest, httplib2.CannotSendHeader,
httplib2.ResponseNotReady, httplib2.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 Developers 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_secret.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 Developers 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 '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="22",
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))
 

 

次のエラーはこれ

Uploading file...
An HTTP error 403 occurred:
b'{\n "error": {\n "errors": [\n {\n "domain": "youtube.quota",\n "reason": "quotaExceeded",\n "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e."\n }\n ],\n "code": 403,\n "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e."\n }\n}\n'

 

要約すると、1日にリクエストできる容量(quota)を超えたとのこと。

調べると一日あたり10,000 quotaで動画一個あたり1600quotaとのこと。

少ない。。。

quotaの容量を増やすためには、何か登録が必要とのこと。

めんどくさいのでAPIYoutubeアップロード はここで終焉とする。