上传视频

本指南提供并解释了使用 YouTube 数据 API 上传 YouTube 视频的 Python 脚本。该代码使用适用于 Python 的 Google API 客户端库。(其他流行编程语言的客户端库也可用。)

注意:示例脚本不进行错误处理。

  • Python 2.5 或更高版本

  • 安装适用于 PythonGoogle API 客户端库( google-api-python-client)

  • 向 Google 注册您的应用程序,以便它可以使用OAuth 2.0 授权访问用户数据的协议。

  • 使用 OAuth 2.0使用此脚本的步骤,您需要创建一个client_secrets.json文件,其中包含来自API Console. 该文件应与脚本位于同一目录中。

    {
     
    "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"
     
    }
    }

此请求上传视频并为视频设置各种元数据字段,包括其标题、描述、关键字和类别。命令行参数都在下一节中详细定义。

python upload_video.py --file="/tmp/test_video_file.flv"
                       --title="Summer vacation in California"
                       --description="Had fun surfing in Santa Cruz"
                       --keywords="surfing,Santa Cruz"
                       --category="22"
                       --privacyStatus="private"

在此示例中,脚本将为video视频构建并插入以下资源:

{
  "snippet": {
    "title": "Summer vacation in California",
    "description": "Had fun surfing in Santa Cruz",
    "tags": ["surfing", "Santa Cruz"],
    "categoryId": "22"
  },
  "status": {
    "privacyStatus": "private"
  }
}

下面的列表定义了脚本的命令行参数:

  • file:此参数标识您正在上传的视频文件的位置。

    Example: --file="/home/path/to/file.mov"
  • title:您上传的视频的标题。默认值为Test title

    Example: --title="Summer vacation in California"
  • description:您上传的视频的描述。默认值为Test description

    Example: --description="Had fun surfing in Santa Cruz"
  • category:与视频关联YouTube 视频类别的类别 ID 默认值为22,表示People & Blogs类别。

    Example: --category="22"
  • keywords:以逗号分隔的与视频相关的关键字列表。默认值为空字符串。

    Example: --keywords="surfing"
  • privacyStatus:视频的隐私状态。默认行为是让上传的视频公开可见 ( public)。上传测试视频时,您可能需要指定一个--privacyStatus参数值以确保这些视频是私有的或不公开的。有效值是publicprivateunlisted

    Example: --privacyStatus="private"

upload_video.py下面列出了该脚本的完整工作示例

#!/usr/bin/python

import httplib
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, 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 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, 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:
     
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, e:
   
print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  • 认证指南提供了实现完整的详细信息OAuth 2.0.

  • 参考文档解释了 a 中的字段 video 资源。