Django YouTube API上传失败与iPhone

时间:2019-04-01 19:11:34

标签: python django youtube

我可以通过Django应用程序将视频上​​传到YouTube,但是只有从笔记本电脑上传视频时才可以。当我通过iPhone上传同一视频时,YouTube出现“正在处理放弃”错误。

我正在使用Django 1.11.20和Python 2.7运行Ubuntu 16.04.3。我在视图中使用一个函数来接收上载的文件,如果文件大小超过2.5兆字节,请从/ tmp目录中获取文件,如果文件大小小于2.5兆字节,请从内存中处理文件。

当我从笔记本电脑上传视频文件时,此方法有效,但当我从iPhone上传视频文件时,此方法失败。

要清楚,我没有从Django / Python中得到错误。该文件似乎可以上传,处理和删除。但是在YouTube收到它之后,我进入了YouTube Studio,它显示了“正在放弃处理。无法处理此视频”错误。

def upload_to_youtube(request):
    if request.method == 'POST' and request.FILES['video']:
        video_file = request.FILES['video']
        if video_file.size >= 2621440:
            fname = request.FILES['video'].file.name
            storage = DjangoORMStorage(CredentialsModel, 'id', request.user.id, 'credential')
            credentials = storage.get()
            client = build('youtube', 'v3', credentials=credentials)

            body = {...}

        with tempfile.NamedTemporaryFile('wb', suffix='yt-django') as tmpfile:
        with open(fname, 'rb') as fileobj:
            tmpfile.write(fileobj.read())
            insert_request = client.videos().insert(
                        part=','.join(body.keys()),
            body=body,
            media_body=MediaFileUpload(
                tmpfile.name, chunksize=-1, resumable=True)
            )
            insert_request.execute()
    else:
            storage = DjangoORMStorage(CredentialsModel, 'id', request.user.id, 'credential')
            credentials = storage.get()
            client = build('youtube', 'v3', credentials=credentials)

            body = {...}

            with tempfile.NamedTemporaryFile('wb', suffix='yt-django') as tmpfile:
                tmpfile.write(request.FILES['video'].read())
        insert_request = client.videos().insert(
            part=','.join(body.keys()),
                body=body,
            media_body=MediaFileUpload(
            tmpfile.name, chunksize=-1, resumable=True)
        )
        insert_request.execute()

最初认为这是由于文件大小所致,因此我写了一张支票以对文件进行处理(如果文件大小为2.5 mb或更小),而是从内存处理文件。但是,即使从笔记本电脑发送了<2.5mb的文件,它仍然可以正常上传。我不确定Django / Python代码中是否存在iOS上载有问题的内容,或者是否在YouTube的一端。

1 个答案:

答案 0 :(得分:0)

好的,看来我已经知道了。遵循YouTube开发人员的说明,我将实际的视频上传内容从服务器上传到YouTube的功能上,这会给我带来任何错误。我没有遇到任何错误,但是从那以后它一直有效。这是新代码:

    if request.method == 'POST' and request.FILES['video']:
        video_file = request.FILES['video']
        if video_file.size >= 2621440:
            fname = request.FILES['video'].file.name
            messages.success(request, "Equal to or over 2.5 megabytes, saving to disk and uploading")
            storage = DjangoORMStorage(CredentialsModel, 'id', request.user.id, 'credential')
            credentials = storage.get()
            client = build('youtube', 'v3', credentials=credentials)

            body = {
                'snippet': {
                    'title': 'Upload Youtube Video',
                    'description': 'Video Description',
                    'tags': 'django,howto,video,api',
                    'categoryId': '27'
                },
                'status': {
                    'privacyStatus': 'unlisted'
                }
            }

            with tempfile.NamedTemporaryFile('wb', suffix='yt-django') as tmpfile:
                with open(fname, 'rb') as fileobj:
                    tmpfile.write(fileobj.read())
                    insert_request = client.videos().insert(
                        part=','.join(body.keys()),
                        body=body,
                        media_body=MediaFileUpload(
                            tmpfile.name, chunksize=-1, resumable=True)
                    )
                    resumable_upload(insert_request)
        else:
            messages.success(request, "Under 2.5 megabytes, uploading from memory")
            storage = DjangoORMStorage(CredentialsModel, 'id', request.user.id, 'credential')
            credentials = storage.get()
            client = build('youtube', 'v3', credentials=credentials)

            body = {
                'snippet': {
                    'title': 'Upload Youtube Video',
                    'description': 'Video Description',
                    'tags': 'django,howto,video,api',
                    'categoryId': '27'
                },
                'status': {
                    'privacyStatus': 'unlisted'
                }
            }

            with tempfile.NamedTemporaryFile('wb', suffix='yt-django') as tmpfile:
                tmpfile.write(request.FILES['video'].read())
                insert_request = client.videos().insert(
                    part=','.join(body.keys()),
                    body=body,
                    media_body=MediaFileUpload(
                        tmpfile.name, chunksize=-1, resumable=True)
                )
                resumable_upload(insert_request)

def resumable_upload(request):
    httplib2.RETRIES = 1
    MAX_RETRIES = 10
    RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected, httplib.IncompleteRead, 
        httplib.ImproperConnectionState, httplib.CannotSendRequest, httplib.CannotSendHeader, httplib.ResponseNotReady, 
        httplib.BadStatusLine)
    RETRIABLE_STATUS_CODES = [500, 502, 503, 504]

    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, 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)