В предыдущем видео я разобрался получением необходимых токенов и созданием сервиса для работы с YouTube API на Python. Сегодня сделаю загрузку видео.
Важное дополнение про блокировку видео , см. коммент .
Мда, подтверждаю проблему. Похоже корни здесь https://developers.google.com/youtube/v3/revision_history#release_notes_07_28_2020 .
После блокировки на почту gmail на аккаунте канала приходит письмо:
«Наши специалисты проверили ваши материалы и обнаружили, что в них нарушаются правила YouTube, а именно правила в отношении спама, мошенничества и обмана. В связи с этим мы установили ограниченный доступ для следующего контента на вашем канале»
Пока предполагаю что видео загруженное через приложение в статусе теста нельзя сделать публичным даже руками, пока нашел только это https://support.google.com/youtube/answer/7300965 «вы не сможете обжаловать наше решение, если ролик был загружен с помощью неподтвержденного сервиса API. Чтобы вернуть доступ к видео, вам потребуется загрузить его снова. Для этого воспользуйтесь подтвержденным API или добавьте контент напрямую на сайте YouTube» .
Самое обидное что этого ограничения вроде бы нет для проектов созданных до 28 июля 2020 года, а я их вдруг решил почистить и удалил все старые неделю назад и теперь не могу проверить :((( .
Навожу порядок в коде
В предыдущих сериях весь код, включая токены, я намеренно делал в одном файле. Так удобнее для видео. Но код растет и ориентироваться в одном файле теперь стало неудобно. Поэтому я его немного причесал, сделал пакет для YouTube API, попрятал токены и выложил все это на GitHub. Конкретно для сегодняшнего видео сделал отдельную ветку.
https://github.com/Denis070/azzrael-yt/tree/video-upload
Ничего слишком сложного, если с Питоном немножко знакомы, то разберетесь. А здесь буду говорить только о двух конкретных функциях, а все остальное см. предыдущие серии сериала Разбираюсь с YouTube API и здесь по тегу YouTube API .
Полезные ссылки
- https://github.com/youtube/api-samples/blob/master/python/upload_video.py
- https://developers.google.com/youtube/v3/docs/videos/insert
- https://developers.google.com/youtube/v3/guides/uploading_a_video
Код загрузки видео с помощью YouTube API и Python
** здесь только две основные функции
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
''' Upload videos to Channel via YouTube API https://developers.google.com/youtube/v3/docs/videos/insert https://developers.google.com/youtube/v3/guides/uploading_a_video https://github.com/youtube/api-samples/blob/master/python/upload_video.py ''' def video_upload(video_path, title, **kwargs): print("** upload video") # chunksize размер блока в БАЙТАХ (int), чем хуже соединение, тем мельче блок # напр. для мобильного трафа норм 1024*1024*3 = 3М # -1 => видос будет грузиться целиком, быстрее на норм сети и при обрыве все равно будет докачка media = MediaFileUpload(video_path, chunksize=-1, resumable=True) # список полей см здесь https://developers.google.com/youtube/v3/docs/videos/insert meta = { 'snippet': { 'title' : title, 'description' : kwargs.get("description", "empty desc") }, # All videos uploaded via the videos.insert endpoint from unverified API projects created after 28 July 2020 # will be restricted to private viewing mode. To lift this restriction, # each API project must undergo an audit to verify compliance # --- т.е. для прилки в статусе теста тут всегда приват, иначе видос будет заблокирован 'status':{ 'privacyStatus':kwargs.get("privacy", "private") } } insert_request = get_service_creds("youtube", "v3").videos().insert( part=','.join(meta.keys()), body=meta, media_body=media ) r = resumable_upload(insert_request) print(r) ''' Resumable Upload by chunks возмобновляемая загрузка файла, см. https://github.com/youtube/api-samples/blob/master/python/upload_video.py но здесь я сильно упростил ''' def resumable_upload(request, retries = 5): while retries > 0: try: status, response = request.next_chunk() if response is None: continue # next chunk, will be None until the resumable media is fully uploaded if 'id' not in response: raise Exception("no id found while video uploading") return response # success except Exception as e: print(e) retries -= 1 sleep(randrange(5)) return None |
Пояснения в видео и в комментариях к коду.
Возможные проблемы
- Не забывайте о SCOPES, для загрузки обязательно нужно разрешение ‘https://www.googleapis.com/auth/youtube.upload‘ , если вдруг сначала запросили юзера без этого разрешения и получили токен, то нужно добавить скоп и запросить права повторно см. предыдущую серию.
- Загрузка видео жрет огромное количество квот. На данный момент 1600 из 10000 доступных в сутки.
- Если при загрузке не поставить приватный статус при загрузке через приложение в режиме тестирования, то видео получит статус заблокировано и его можно будет только удалить и перезалить (с тратой квот) или подавать апелляцию (что глупо).
- Мелкие чанки выгодны на мобильном или просто плохом интернете и больших файлах.
- Мой код в функции resumable_upload намеренно упрощен. Не нужно в нем сильно увеличивать количество попыток — каждый запрос к апишке, даже если он не успешный — сжирает квоту.
- Сейчас в 2021 YT при загрузке видео делает автоматическую проверку каждого видео на соответствие правилам. Если долбить API однотипным виде с однотипными описаниями и заголовками, то могут валиться ошибки вроде “Не удалось выполнить проверку”. Это, конечно, проблема при отладке скрипта, но кто говорил что будет легко.