Scripting way to upload videos to peertube and youtube
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.5 KiB

  1. #!/usr/bin/python
  2. # coding: utf-8
  3. # From Youtube samples : https://raw.githubusercontent.com/youtube/api-samples/master/python/upload_video.py
  4. import argparse
  5. import httplib
  6. import httplib2
  7. import os
  8. import random
  9. import time
  10. import google.oauth2.credentials
  11. import google_auth_oauthlib.flow
  12. from googleapiclient.discovery import build
  13. from googleapiclient.errors import HttpError
  14. from googleapiclient.http import MediaFileUpload
  15. from google_auth_oauthlib.flow import InstalledAppFlow
  16. # Explicitly tell the underlying HTTP transport library not to retry, since
  17. # we are handling retry logic ourselves.
  18. httplib2.RETRIES = 1
  19. # Maximum number of times to retry before giving up.
  20. MAX_RETRIES = 10
  21. # Youtube retriables cases
  22. RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected,
  23. httplib.IncompleteRead, httplib.ImproperConnectionState,
  24. httplib.CannotSendRequest, httplib.CannotSendHeader,
  25. httplib.ResponseNotReady, httplib.BadStatusLine)
  26. RETRIABLE_STATUS_CODES = [500, 502, 503, 504]
  27. CLIENT_SECRETS_FILE = 'youtube_secret.json'
  28. SCOPES = ['https://www.googleapis.com/auth/youtube.upload']
  29. API_SERVICE_NAME = 'youtube'
  30. API_VERSION = 'v3'
  31. # Authorize the request and store authorization credentials.
  32. def get_authenticated_service():
  33. flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
  34. credentials = flow.run_console()
  35. return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
  36. def initialize_upload(youtube, options):
  37. path = options.get('--file')
  38. print options.get('--name')
  39. tags = None
  40. if options.get('--tags'):
  41. tags = options.get('--tags').split(',')
  42. body=dict(
  43. snippet=dict(
  44. title=options.get('--name') or os.path.splitext(os.path.basename(path))[0],
  45. description=options.get('--description') or "",
  46. tags=tags,
  47. categoryId=str(options.get('--category') or 1),
  48. ),
  49. status=dict(
  50. privacyStatus=str(options.get('--privacy') or "private"),
  51. )
  52. )
  53. # Call the API's videos.insert method to create and upload the video.
  54. insert_request = youtube.videos().insert(
  55. part=','.join(body.keys()),
  56. body=body,
  57. media_body=MediaFileUpload(path, chunksize=-1, resumable=True)
  58. )
  59. resumable_upload(insert_request)
  60. # This method implements an exponential backoff strategy to resume a
  61. # failed upload.
  62. def resumable_upload(request):
  63. response = None
  64. error = None
  65. retry = 0
  66. while response is None:
  67. try:
  68. print 'Uploading file...'
  69. status, response = request.next_chunk()
  70. if response is not None:
  71. if 'id' in response:
  72. print 'Video id "%s" was successfully uploaded.' % response['id']
  73. else:
  74. exit('The upload failed with an unexpected response: %s' % response)
  75. except HttpError, e:
  76. if e.resp.status in RETRIABLE_STATUS_CODES:
  77. error = 'A retriable HTTP error %d occurred:\n%s' % (e.resp.status,
  78. e.content)
  79. else:
  80. raise
  81. except RETRIABLE_EXCEPTIONS, e:
  82. error = 'A retriable error occurred: %s' % e
  83. if error is not None:
  84. print error
  85. retry += 1
  86. if retry > MAX_RETRIES:
  87. exit('No longer attempting to retry.')
  88. max_sleep = 2 ** retry
  89. sleep_seconds = random.random() * max_sleep
  90. print 'Sleeping %f seconds and then retrying...' % sleep_seconds
  91. time.sleep(sleep_seconds)
  92. def run(options):
  93. youtube = get_authenticated_service()
  94. try:
  95. initialize_upload(youtube, options)
  96. except HttpError, e:
  97. print 'An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)