Сбой загрузки API Django YouTube с iPhone

#python #django #youtube

#python #django #YouTube

Вопрос:

Я могу загружать видео на YouTube через свое приложение Django, но только тогда, когда они загружены с моего ноутбука. YouTube выдает мне ошибку «Обработка прервана», когда я загружаю одно и то же видео через свой iPhone.

Я запускаю Ubuntu 16.04.3 с версией Django 1.11.20 и Python 2.7. Я использую функцию в своих представлениях для получения загруженного файла и, если он превышает 2,5 мегабайта, извлекаю файл из каталога / tmp, а если он меньше 2,5 мегабайт, обрабатываю файл из памяти.

Это работает, когда я загружаю видеофайлы со своего ноутбука, но не работает, когда я загружаю видеофайлы со своего iPhone.

Чтобы было понятно, я не получаю ошибок от Django / Python. Файл, похоже, загружается, обрабатывается и удаляется просто отлично. Но после того, как YouTube получает его, я захожу в свою студию YouTube, и она выдает мне «Обработка прекращена. Это видео не удалось обработать», ошибка.

 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 МБ или меньше, вместо этого обработать его из памяти. Однако даже с файлом размером менее 2,5 Мб, отправленным с ноутбука, он все равно будет загружаться просто отлично. Я не уверен, есть ли что-то в моем коде Django / Python, что вызывает проблемы при загрузке на iOS, или это находится в конце YouTube.

Ответ №1:

Хорошо, похоже, я понял это. Следуя заметкам разработчика 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)