Для загрузки видео с видеохостинга YouTube существует множество самых разнообразных модулей. Я сам делал небольшую функцию для загрузки с помощью парсинга разнообразных сайтов. Но, лучше, конечно же, использовать модули, которые уже заточены под то, чтобы выполнять определенные функции, а не изобретать велосипед, хотя, тут тоже вопрос спорный, вдруг ваш велосипед окажется лучше )) Я велосипед решил не изобретать, а использовал уже существующую библиотеку pytube. Таким образом, давайте создадим класс для загрузки видео с помощью данной библиотеки и, конечно же, Python.
Что потребуется?
Создаем файл модуля. Я назвал его просто: downloader.py. После этого нужно установить библиотеки. Конечно же, в данном случае основной библиотекой, которая будет использоваться для загрузки, будет pytube. Для его установки пишем в терминале:
Также я воспользовался еще двумя библиотеками, которые больше служат для вспомогательных целей, радовать глаз и ухо )). Библиотеку colorama я использовал для того, чтобы раскрасить вывод в терминале, а библиотеку chime для звукового сопровождения окончания загрузки видео, плейлиста или при возникновении ошибки, просто, чтобы привлечь внимание пользователя. Для их установки пишем в терминале:
После установки библиотек выполним импорт всего, что нужно для работы модуля, а также инициализируем модуль colorama:
Замена символов в названиях видео, приведение размера файла к удобочитаемому формату, загрузка субтитров
Перед тем, как создавать класс, давайте создадим вспомогательные функции, которые будут находиться вне класса. Для начала, создадим функцию get_size(bts, ending='iB'). На вход она принимает размер файла в байтах, а возвращает уже переконвертированное значение. Это нужно для того, чтобы размер видео отображался в более человеко читаемом формате, а именно, килобайтах, мегабайтах и выше.
Создадим переменную size, в которую запишем значение 1024, ведь в одном килобайте 1024 байта, а значит именно на это значение нужно поделить переданное в функцию число, чтобы получить нужный размер. Затем в цикле сравниваем полученное значение с size, и если оно меньше, возвращаем его из функции с суффиксом и двумя цифрами после запятой. Если же нет, делим на size и присваиваем значение bts. Таким образом, как только мы получим нужное значение, оно будет возвращено из функции.
Еще одна функция, которая будет нужна в данном модуле, это функция, которая выполняет замену всяческих знаков в тексте, вроде звездочек, кавычек и прочих. Для чего это нужно? Так как мы будем создавать папку для сохранения видео с названием канала или плейлиста, значит, нужно привести название к такому виду, чтобы его приняла операционная система. То же самое относиться и к названию видео.
Создадим функцию rep_symbol(text: str). На вход она получает текст, в котором нужно заменить символы, а возвращает уже очищенное значение. Здесь ничего мудрить не надо. Я просто сделал длинную строку, в которой перечислил все, что нужно заменять. Можно было бы использовать цикл, но почему-то я столкнулся с тем, что не все символы в нем заменяются. Это требует дополнительных экспериментов или нужно просто порыться в интернете. Тем не менее, работа данного выражения меня, пока, устраивает. Вот что у меня получилось:
Еще одна функция вне класса, из которой будем запускать все основные действия. Создадим функцию download(url: str, res: str). На вход она получает два значения — первое значение, это ссылка на видео или канал YouTube, второе значение — разрешение, которое нужно для скачивания. Для начала создаем экземпляр нашего будущего класса, в который передаем полученные значения. И после запускаем функцию start, созданную уже в классе.
Функция, которая потребуется для работы класса, но создания ее в классе не требуется. Это функция для загрузки субтитров. Почти у каждого видео есть субтитры, которые создаются автоматически. И иногда, попадаются субтитры загруженные пользователем. Мы будем загружать английские субтитры, если вы будете скачивать видео на английском языке. Они помогут понять то, о чем говорится в видео, ну или их можно просто перевести.
Создадим функцию srt_download(cap, path_save: str, title: str). На вход она принимает субтитры, путь для их сохранения и заголовок видео, для которого субтитры скачиваются. Запускаем цикл по ключам в заголовках, ищем в них автоматически созданные «a.en» или загруженные пользователем «en» субтитры. Если находим, сохраняем в файл с помощью функции pytube generate_srt_captions().
Но, здесь хочу сразу же сказать, что в том pytube, который устанавливается с помощью pip данная функция не работает. Это давняя проблема, которую почему-то разработчики решать не торопятся. Однако, покопавшись в форумах я нашел решение. Проблема заключается в неверном парсинге xml, код которого находиться в модуле captions.py. Я нашел целый код модуля, создал его и заменяю, если мне нужно загрузить, как в данном случае, субтитры. Модуль будет во вложении. Путь для замены в виртуальном окружении (примерный): venv/lib/python3.8/site-packages/pytube. А также, путь для замены в питоне вне виртуального окружения: .local/lib/python3.8/site-packages (12.1.0). С версией вашего питона определитесь сами )).
Созданные функции можно расположить как перед, так и после класса. Но, наверное, будет красивее и правильнее расположить их, все же после.
Что ж, на этом подготовительные работы можно завершить. Теперь пришла очередь писать логику класса.
Создание класса. Инициализация
Создадим класс YtDownload и функцию инициализации параметров __init__(self, url, res). Как видим, на входе данный класс принимает ссылку на видео или плейлист, а также желаемое качество для загружаемого видео. Их и нужно инициализировать. Инициализируем ссылку. А вот для разрешения пришлось написать условие, так как, почему-то не срабатывал параметр по умолчанию. То есть, если я передавал пустую строку, то она и подставлялась в значение res, вместо того, что было определено. Поэтому, делаем проверку, и, если пользователь не ввел значения, присваиваем разрешению видео значение 720.
Стартовая функция
Создадим функцию start(self), с которой и будет начинаться работа по загрузке видео. В данной функции проверим, является ли переданная ссылка ссылкой на YouTube. Для этого напишем условие, в котором проверяем, есть ли в переданной ссылке «youtube.com». Если нет, тогда сообщаем пользователю, что его ссылка не валидна и подаем звуковой сигнал.
Делаем проверку для определения, является ли переданная ссылка ссылкой на плейлист или просто на видео. Для этого ищем в ссылке слово «playlist». Если находим, запускаем функцию загрузки видео из плейлиста. Если не находим, создаем экземпляр класса YouTube, передаем в него полученные параметры, определяем путь к загружаемому видео и запускаем функцию загрузки видео, куда передаем созданный экземпляр класса и путь для загружаемого видео. Также заключим создание экземпляра в блок try — excepr, для того, чтобы обработать исключение в случае, если переданная пользователем ссылка будет с ошибками.
Проверка разрешения видео
Создадим функцию, которая будет проверять, является ли разрешение видео, которое передано пользователем доступно для загрузки. Я назвал функцию check_res(self, yt). На вход она принимает экземпляр созданного класса YouTube с параметрами.
Объявим пустой список, в который будем складывать полученные разрешения. С помощью функции streams.filter получим доступные для загрузки.
Теперь в цикле заберем все разрешения из полученного списка. Для этого придется заменить в каждом элементе некоторые значения, предварительно приведя его к строке и разбив по пробелам. После того, как мы сформируем список, делаем проверку, входит ли в него полученное от пользователя разрешение. Если да, возвращаем его обратно, если нет, возвращаем последнее значение из списка, так как именно оно является лучшим качеством для загрузки в данном контексте.
Загрузка одного видео
Для загрузки одного видео создадим функцию video_download(self, yt, path_save: str). На вход она принимает экземпляр класса YouTube с параметрами и путь для сохранения видео. Именно с помощью данной функции мы будем обрабатывать все видео входящие в плейлист.
Проверим разрешение загружаемого видео. Выведем сообщения в терминал о названии видео, авторе, размере и загружаемом разрешении.
Теперь создадим поток для загрузки видео, в котором отфильтруем только те видео, параметр progressive которых равен True, а также передадим в фильтр требуемое разрешение. Дополнительных проверок здесь уже не требуется, так как мы проверили разрешение ранее. Передадим путь для загрузки видео и название, которое заберем из его названия на сервисе. Выведем в терминал прогресс-бар.
После того, как видео будет загружено, попробуем загрузить субтитры. Так как если видео на английском языке, они могут понадобиться для лучшего понимания. Или их можно просто перевести с помощью переводчика. Запускаем функцию загрузки субтитров, в которую передаем параметр caption. Именно в нем находятся субтитры. Путь для сохранения субтитров, который будет таким же, как путь загружаемого видео и название видео взятое с сервиса с удаленными символами, которые будут препятствовать сохранению. После чего выводим сообщение о том, что видео загружено и проигрываем звуковое оповещение.
Загрузка плейлиста
Если пользователь передаст ссылку не на видео, а на плейлист, у нас должна быть функция, которая умеет загружать все видео из него. Создадим функцию playlist_download(self). Для начала создаем экземпляр класса Playlist, в который передаем ссылку. Затем посчитаем количество символов в сообщении, которое будем передавать при выводе в терминал «-», для отделения строк. Но это так, больше для декорации. Ну и, собственно, выведем само сообщение о загрузке плейлиста.
Запустим цикл, в котором пробежимся по списку полученных видео плейлиста. Для каждого видео будем создавать экземпляр класса YouTube, в который передадим нужные параметры. А именно ссылку на видео и определим параметр, который отвечает за функцию, используемую для показа прогресс-бара. Сформируем путь для загрузки видео. В данном случае, так как это плейлист, он будет отличаться от пути, по которому загружается одиночное видео. Передадим эти параметры в функцию загрузки видео. Так будем продолжать, пока ссылки в плейлисте не закончатся.
После того, как все видео из плейлиста будут загружены, выведем сообщение об этом в терминал и просигнализируем звуковым оповещением.
Обернем все в блок try — except, для того, чтобы обработать исключение, если пользователь передаст неправильную ссылку.
Пример работы с классом
Для примера создадим модуль main.py. Импортируем модуль с созданным нами классом.
И вызовем функцию загрузки видео, в которую передадим запрошенные у пользователя ссылку и разрешение.
Также, данную функцию можно использовать для загрузки в цикле видео из списка. Для примера:
Небольшое видео демонстрации работы класса:
А на этом, пожалуй, все.
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
Что потребуется?
Создаем файл модуля. Я назвал его просто: downloader.py. После этого нужно установить библиотеки. Конечно же, в данном случае основной библиотекой, которая будет использоваться для загрузки, будет pytube. Для его установки пишем в терминале:
pip install pytube
Также я воспользовался еще двумя библиотеками, которые больше служат для вспомогательных целей, радовать глаз и ухо )). Библиотеку colorama я использовал для того, чтобы раскрасить вывод в терминале, а библиотеку chime для звукового сопровождения окончания загрузки видео, плейлиста или при возникновении ошибки, просто, чтобы привлечь внимание пользователя. Для их установки пишем в терминале:
pip install colorama chime
После установки библиотек выполним импорт всего, что нужно для работы модуля, а также инициализируем модуль colorama:
Python:
import os
from colorama import Fore
from colorama import init
from pytube import exceptions
from pytube import YouTube
from pytube import Playlist
from pytube.cli import on_progress
import chime
init()
Замена символов в названиях видео, приведение размера файла к удобочитаемому формату, загрузка субтитров
Перед тем, как создавать класс, давайте создадим вспомогательные функции, которые будут находиться вне класса. Для начала, создадим функцию get_size(bts, ending='iB'). На вход она принимает размер файла в байтах, а возвращает уже переконвертированное значение. Это нужно для того, чтобы размер видео отображался в более человеко читаемом формате, а именно, килобайтах, мегабайтах и выше.
Создадим переменную size, в которую запишем значение 1024, ведь в одном килобайте 1024 байта, а значит именно на это значение нужно поделить переданное в функцию число, чтобы получить нужный размер. Затем в цикле сравниваем полученное значение с size, и если оно меньше, возвращаем его из функции с суффиксом и двумя цифрами после запятой. Если же нет, делим на size и присваиваем значение bts. Таким образом, как только мы получим нужное значение, оно будет возвращено из функции.
Python:
def get_size(bts, ending='iB'):
"""
Получает размера файла. Переводит размер в читаемый формат,
значение возвращает из функции.
:param bts: размер файла.
:param ending: суффикс для возвращаемого значения.
:return: возвращает размер файла в определенном формате.
"""
size = 1024
for item in ["", "K", "M", "G", "T", "P"]:
if bts < size:
return f"{bts:.2f} {item}{ending}"
bts /= size
Еще одна функция, которая будет нужна в данном модуле, это функция, которая выполняет замену всяческих знаков в тексте, вроде звездочек, кавычек и прочих. Для чего это нужно? Так как мы будем создавать папку для сохранения видео с названием канала или плейлиста, значит, нужно привести название к такому виду, чтобы его приняла операционная система. То же самое относиться и к названию видео.
Создадим функцию rep_symbol(text: str). На вход она получает текст, в котором нужно заменить символы, а возвращает уже очищенное значение. Здесь ничего мудрить не надо. Я просто сделал длинную строку, в которой перечислил все, что нужно заменять. Можно было бы использовать цикл, но почему-то я столкнулся с тем, что не все символы в нем заменяются. Это требует дополнительных экспериментов или нужно просто порыться в интернете. Тем не менее, работа данного выражения меня, пока, устраивает. Вот что у меня получилось:
Python:
def rep_symbol(text: str):
"""
Заменяются символы, которые могут вызвать ошибку при сохранении
видео или создании папки для него.
:param text: текст для замены символов.
:return: возвращает результат после замены символов.
"""
tex = text.replace("'", "").replace('"', '').replace('|', '_').replace(' | ', '_').replace('/', '_'). \
replace('\\', '_').replace('*', '_').replace('?', '').replace('<', '').replace('>', '_').replace(':', ''). \
replace(';', '').replace('.', '').strip()
return tex
Еще одна функция вне класса, из которой будем запускать все основные действия. Создадим функцию download(url: str, res: str). На вход она получает два значения — первое значение, это ссылка на видео или канал YouTube, второе значение — разрешение, которое нужно для скачивания. Для начала создаем экземпляр нашего будущего класса, в который передаем полученные значения. И после запускаем функцию start, созданную уже в классе.
Python:
def download(url: str, res: str):
"""
Создает экземпляр класса YtDownload, в который
передаются полученные параметры. Вызывается функция
проверки ссылок и определения типа загружаемого видео.
:param url: ссылка на видео или на плейлист.
:param res: желаемое качество видео.
"""
tube = YtDownload(url=url, res=res)
tube.start()
Функция, которая потребуется для работы класса, но создания ее в классе не требуется. Это функция для загрузки субтитров. Почти у каждого видео есть субтитры, которые создаются автоматически. И иногда, попадаются субтитры загруженные пользователем. Мы будем загружать английские субтитры, если вы будете скачивать видео на английском языке. Они помогут понять то, о чем говорится в видео, ну или их можно просто перевести.
Создадим функцию srt_download(cap, path_save: str, title: str). На вход она принимает субтитры, путь для их сохранения и заголовок видео, для которого субтитры скачиваются. Запускаем цикл по ключам в заголовках, ищем в них автоматически созданные «a.en» или загруженные пользователем «en» субтитры. Если находим, сохраняем в файл с помощью функции pytube generate_srt_captions().
Но, здесь хочу сразу же сказать, что в том pytube, который устанавливается с помощью pip данная функция не работает. Это давняя проблема, которую почему-то разработчики решать не торопятся. Однако, покопавшись в форумах я нашел решение. Проблема заключается в неверном парсинге xml, код которого находиться в модуле captions.py. Я нашел целый код модуля, создал его и заменяю, если мне нужно загрузить, как в данном случае, субтитры. Модуль будет во вложении. Путь для замены в виртуальном окружении (примерный): venv/lib/python3.8/site-packages/pytube. А также, путь для замены в питоне вне виртуального окружения: .local/lib/python3.8/site-packages (12.1.0). С версией вашего питона определитесь сами )).
Python:
for item in cap.lang_code_index.keys():
if item == 'a.en' or item == 'en':
with open(os.path.join(path_save, f'{rep_symbol(title)}.srt'), 'w', encoding='utf-8') as file:
file.write(cap[item].generate_srt_captions())
Python:
def srt_download(cap, path_save: str, title: str):
"""
Получает список доступных субтитров, проверяет, есть ли
субтитры с требуемым языком. Если есть, загружает.
Для данной функции требуется замена файла captions.py
в папке библиотеки pytube. Если не заменить, вызывается
ошибка парсинга. Проблема давняя, но почему-то официально
не решенная. Однако, на форумах нашел правильный вариант.
:param cap: список субтитров из видео.
:param path_save: путь для загрузки субтитров.
:param title: название для загружаемых субтитров.
"""
for item in cap.lang_code_index.keys():
if item == 'a.en' or item == 'en':
with open(os.path.join(path_save, f'{rep_symbol(title)}.srt'), 'w', encoding='utf-8') as file:
file.write(cap[item].generate_srt_captions())
Созданные функции можно расположить как перед, так и после класса. Но, наверное, будет красивее и правильнее расположить их, все же после.
Что ж, на этом подготовительные работы можно завершить. Теперь пришла очередь писать логику класса.
Создание класса. Инициализация
Создадим класс YtDownload и функцию инициализации параметров __init__(self, url, res). Как видим, на входе данный класс принимает ссылку на видео или плейлист, а также желаемое качество для загружаемого видео. Их и нужно инициализировать. Инициализируем ссылку. А вот для разрешения пришлось написать условие, так как, почему-то не срабатывал параметр по умолчанию. То есть, если я передавал пустую строку, то она и подставлялась в значение res, вместо того, что было определено. Поэтому, делаем проверку, и, если пользователь не ввел значения, присваиваем разрешению видео значение 720.
Python:
class YtDownload:
def __init__(self, url, res):
"""
Инициализируются параметры, переданные в класс.
Выполняется проверка на переданное значение разрешения.
Значение по умолчанию не подставляется, если передана
пустая строка, подставляется именно пустая строка.
:param url: ссылка на видео или плейлист YouTube.
:param res: желаемое разрешение видео.
"""
self.url = url
if res == '':
self.res = '720p'
else:
self.res = f'{res}p'
Стартовая функция
Создадим функцию start(self), с которой и будет начинаться работа по загрузке видео. В данной функции проверим, является ли переданная ссылка ссылкой на YouTube. Для этого напишем условие, в котором проверяем, есть ли в переданной ссылке «youtube.com». Если нет, тогда сообщаем пользователю, что его ссылка не валидна и подаем звуковой сигнал.
Python:
if 'youtube.com' not in self.url:
print(Fore.RED + 'Неверная ссылка')
chime.theme('mario')
chime.success()
return
Делаем проверку для определения, является ли переданная ссылка ссылкой на плейлист или просто на видео. Для этого ищем в ссылке слово «playlist». Если находим, запускаем функцию загрузки видео из плейлиста. Если не находим, создаем экземпляр класса YouTube, передаем в него полученные параметры, определяем путь к загружаемому видео и запускаем функцию загрузки видео, куда передаем созданный экземпляр класса и путь для загружаемого видео. Также заключим создание экземпляра в блок try — excepr, для того, чтобы обработать исключение в случае, если переданная пользователем ссылка будет с ошибками.
Python:
if 'playlist' in self.url:
self.playlist_download()
else:
try:
yt = YouTube(self.url, on_progress_callback=on_progress)
path_save = os.path.join(os.getcwd(), 'video', f'{rep_symbol(yt.author)}')
self.video_download(yt, path_save)
except exceptions.RegexMatchError:
print(Fore.RED + 'Неверная ссылка')
chime.theme('mario')
chime.success()
return
Python:
def start(self):
"""
Выполняется проверка, является ли ссылка валидной для YouTube.
Определяется тип переданной ссылки (плейлист или видео).
В зависимости назначения ссылки запускается загрузка или
плейлиста, или создается экземпляр класса YouTube с параметрами,
устанавливается путь для загрузки видео, запускается функция
загрузки видео с переданными параметрами.
:return: выход из функции.
"""
if 'youtube.com' not in self.url:
print(Fore.RED + 'Неверная ссылка')
chime.theme('mario')
chime.success()
return
if 'playlist' in self.url:
self.playlist_download()
else:
try:
yt = YouTube(self.url, on_progress_callback=on_progress)
path_save = os.path.join(os.getcwd(), 'video', f'{rep_symbol(yt.author)}')
self.video_download(yt, path_save)
except exceptions.RegexMatchError:
print(Fore.RED + 'Неверная ссылка')
chime.theme('mario')
chime.success()
return
Проверка разрешения видео
Создадим функцию, которая будет проверять, является ли разрешение видео, которое передано пользователем доступно для загрузки. Я назвал функцию check_res(self, yt). На вход она принимает экземпляр созданного класса YouTube с параметрами.
Объявим пустой список, в который будем складывать полученные разрешения. С помощью функции streams.filter получим доступные для загрузки.
Python:
res_list = []
check_res = yt.streams.filter(progressive=True)
Теперь в цикле заберем все разрешения из полученного списка. Для этого придется заменить в каждом элементе некоторые значения, предварительно приведя его к строке и разбив по пробелам. После того, как мы сформируем список, делаем проверку, входит ли в него полученное от пользователя разрешение. Если да, возвращаем его обратно, если нет, возвращаем последнее значение из списка, так как именно оно является лучшим качеством для загрузки в данном контексте.
Python:
for item in check_res:
res_list.append(str(item).split()[3].replace("res=", '').replace('"', ''))
if self.res not in res_list:
print(Fore.YELLOW + f'\nЗапрошенное разрешение недоступно\nБудет загружено: {res_list[-1]}\n')
return res_list[-1]
return self.res
Python:
def check_res(self, yt):
"""
Проверка разрешения введенного пользователем. Если требуемое разрешение недоступно,
либо отсутствует разрешение для видео по умолчанию, возвращается максимально доступное
разрешение доступное для данного видео.
:param yt: экземпляр класса YouTube с параметрами.
:return: возвращает разрешение видео.
"""
res_list = []
check_res = yt.streams.filter(progressive=True)
for item in check_res:
res_list.append(str(item).split()[3].replace("res=", '').replace('"', ''))
if self.res not in res_list:
print(Fore.YELLOW + f'\nЗапрошенное разрешение недоступно\nБудет загружено: {res_list[-1]}\n')
return res_list[-1]
return self.res
Загрузка одного видео
Для загрузки одного видео создадим функцию video_download(self, yt, path_save: str). На вход она принимает экземпляр класса YouTube с параметрами и путь для сохранения видео. Именно с помощью данной функции мы будем обрабатывать все видео входящие в плейлист.
Проверим разрешение загружаемого видео. Выведем сообщения в терминал о названии видео, авторе, размере и загружаемом разрешении.
Python:
res = self.check_res(yt)
print(Fore.GREEN + f'\nЗагружаю видео\n{"-" * 14}\n')
print(Fore.YELLOW + f' Название: "{yt.title}"')
print(Fore.YELLOW + f' Автор: "{yt.author}"')
print(Fore.YELLOW + f' Размер видео: '
f'{get_size(yt.streams.filter(progressive=True, resolution=res).first().filesize)}')
print(Fore.YELLOW + f' Качество: {res}\n')
print(Fore.GREEN + f"{'-' * 14}\n")
Теперь создадим поток для загрузки видео, в котором отфильтруем только те видео, параметр progressive которых равен True, а также передадим в фильтр требуемое разрешение. Дополнительных проверок здесь уже не требуется, так как мы проверили разрешение ранее. Передадим путь для загрузки видео и название, которое заберем из его названия на сервисе. Выведем в терминал прогресс-бар.
После того, как видео будет загружено, попробуем загрузить субтитры. Так как если видео на английском языке, они могут понадобиться для лучшего понимания. Или их можно просто перевести с помощью переводчика. Запускаем функцию загрузки субтитров, в которую передаем параметр caption. Именно в нем находятся субтитры. Путь для сохранения субтитров, который будет таким же, как путь загружаемого видео и название видео взятое с сервиса с удаленными символами, которые будут препятствовать сохранению. После чего выводим сообщение о том, что видео загружено и проигрываем звуковое оповещение.
Python:
yt.streams.filter(progressive=True, resolution=res).first().download(path_save, f'{rep_symbol(yt.title)}.mp4')
yt.register_on_progress_callback(on_progress)
srt_download(yt.captions, path_save, rep_symbol(yt.title))
print(Fore.BLUE + f'Видео загружено в папку: {os.path.join(path_save, f"{rep_symbol(yt.title)}.mp4")}\n')
chime.theme('big-sur')
chime.success()
Python:
def video_download(self, yt, path_save: str):
"""
Загружает видео, которое передается в экземпляре класса YouTube с параметрами.
Также передается путь для загрузки видео, который различается, в случае, если
загружается плейлист.
Выводиться в терминал информация о видео.
:param yt: экземпляр класса YouTube с параметрами.
:param path_save: путь к папке для загрузки видео.
"""
res = self.check_res(yt)
print(Fore.GREEN + f'\nЗагружаю видео\n{"-" * 14}\n')
print(Fore.YELLOW + f' Название: "{yt.title}"')
print(Fore.YELLOW + f' Автор: "{yt.author}"')
print(Fore.YELLOW + f' Размер видео: '
f'{get_size(yt.streams.filter(progressive=True, resolution=res).first().filesize)}')
print(Fore.YELLOW + f' Качество: {res}\n')
print(Fore.GREEN + f"{'-' * 14}\n")
yt.streams.filter(progressive=True, resolution=res).first().download(path_save, f'{rep_symbol(yt.title)}.mp4')
yt.register_on_progress_callback(on_progress)
srt_download(yt.captions, path_save, rep_symbol(yt.title))
print(Fore.BLUE + f'Видео загружено в папку: {os.path.join(path_save, f"{rep_symbol(yt.title)}.mp4")}\n')
chime.theme('big-sur')
chime.success()
Загрузка плейлиста
Если пользователь передаст ссылку не на видео, а на плейлист, у нас должна быть функция, которая умеет загружать все видео из него. Создадим функцию playlist_download(self). Для начала создаем экземпляр класса Playlist, в который передаем ссылку. Затем посчитаем количество символов в сообщении, которое будем передавать при выводе в терминал «-», для отделения строк. Но это так, больше для декорации. Ну и, собственно, выведем само сообщение о загрузке плейлиста.
Python:
pl = Playlist(self.url)
width_name = len(Fore.GREEN + f'Загружаю плейлист: "{pl.title}"')
print(Fore.GREEN + f'\n{"-" * (width_name - 5)}\nЗагружаю плейлист: "{pl.title}"\n{"-" * (width_name — 5)}')
Запустим цикл, в котором пробежимся по списку полученных видео плейлиста. Для каждого видео будем создавать экземпляр класса YouTube, в который передадим нужные параметры. А именно ссылку на видео и определим параметр, который отвечает за функцию, используемую для показа прогресс-бара. Сформируем путь для загрузки видео. В данном случае, так как это плейлист, он будет отличаться от пути, по которому загружается одиночное видео. Передадим эти параметры в функцию загрузки видео. Так будем продолжать, пока ссылки в плейлисте не закончатся.
Python:
for url in pl.video_urls:
yt = YouTube(url, on_progress_callback=on_progress)
path_save = os.path.join('video', rep_symbol(yt.author), rep_symbol(pl.title))
self.video_download(yt, path_save)
После того, как все видео из плейлиста будут загружены, выведем сообщение об этом в терминал и просигнализируем звуковым оповещением.
Python:
print(Fore.GREEN + f'{"-" * (width_name - 5)}\nПлейлист: "{pl.title}" загружен\n{"-" * (width_name - 5)}\n')
chime.theme('big-sur')
chime.success()
Обернем все в блок try — except, для того, чтобы обработать исключение, если пользователь передаст неправильную ссылку.
Python:
def playlist_download(self):
"""
Загрузка плейлиста с видео. Для каждого видео из списка полученного из плейлиста
создается экземпляр класса YouTube с параметрами. Он передается в функцию загрузки
видео, где выполняется его загрузка.
:return: выход из функции.
"""
try:
pl = Playlist(self.url)
width_name = len(Fore.GREEN + f'Загружаю плейлист: "{pl.title}"')
print(Fore.GREEN + f'\n{"-" * (width_name - 5)}\nЗагружаю плейлист: "{pl.title}"\n{"-" * (width_name - 5)}')
for url in pl.video_urls:
yt = YouTube(url, on_progress_callback=on_progress)
path_save = os.path.join('video', rep_symbol(yt.author), rep_symbol(pl.title))
self.video_download(yt, path_save)
print(Fore.GREEN + f'{"-" * (width_name - 5)}\nПлейлист: "{pl.title}" загружен\n{"-" * (width_name - 5)}\n')
chime.theme('big-sur')
chime.success()
except KeyError:
print(Fore.RED + 'Неверная ссылка')
chime.theme('mario')
chime.success()
return
Пример работы с классом
Для примера создадим модуль main.py. Импортируем модуль с созданным нами классом.
from downloader import download
И вызовем функцию загрузки видео, в которую передадим запрошенные у пользователя ссылку и разрешение.
Python:
download(url=input('Введите ссылку на видео или плейлист: '),
res=input('Введите желаемое качество видео (360, 480, 720): '))
Также, данную функцию можно использовать для загрузки в цикле видео из списка. Для примера:
Python:
with open('link.txt', 'r', encoding='utf-8') as file:
reader = file.readlines()
for link in reader:
download(link, '720')
Небольшое видео демонстрации работы класса:
А на этом, пожалуй, все.
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна