Использовать будем python и библиотеку tkinter и customtkinter. Наш будущий загрузчик видео будет выглядеть так:
Код будет достаточно простым, всего два модуля. Первый из них youtube_downloader.py
"""Youtube and UI module."""
from tkinter import filedialog
import customtkinter
from pytube import YouTube
class YouTubeDownloader(customtkinter.CTk):
"""Class is inherit from customtkinter."""
def __init__(self, *args, **kwargs):
"""Initilization."""
super().__init__(*args, **kwargs)
self.geometry("720x480")
self.title("Simple Youtube Downloader")
customtkinter.set_appearance_mode("System")
customtkinter.set_default_color_theme("blue")
self.create_widgets()
def create_widgets(self):
"""Create customtkinter UI."""
self.title_label = customtkinter.CTkLabel(self, text="Input video URL")
self.title_label.pack(padx=10, pady=10)
self.link_entry = customtkinter.CTkEntry(self, width=350, height=40)
self.link_entry.pack()
self.link_entry.bind('<Control-a>', self.on_select_all)
self.finish_label = customtkinter.CTkLabel(self, text="")
self.finish_label.pack(padx=10, pady=10)
self.progress_label = customtkinter.CTkLabel(self, text="0%")
self.progress_label.pack()
self.progress_bar = customtkinter.CTkProgressBar(self, width=400)
self.progress_bar.set(0)
self.progress_bar.pack(padx=10, pady=10)
self.download_button = customtkinter.CTkButton(
self,
text="Download video",
command=self.start_download
)
self.download_button.pack(padx=10, pady=10)
def on_select_all(self, event):
"""Enable CTRL+A in input field."""
event.widget.select_range(0, 'end')
event.widget.icursor('end')
return 'break'
def start_download(self):
"""Download video."""
try:
download_link = self.link_entry.get()
yt = YouTube(download_link, on_progress_callback=self.on_progress)
video = yt.streams.get_highest_resolution()
self.finish_label.configure(text="")
save_path = filedialog.askdirectory()
if not save_path:
self.finish_label.configure(text="Cancel downloading", text_color="red")
return
video.download(save_path)
self.finish_label.configure(
text=f"Downloaded in: {save_path}\nName: {yt.title}",
text_color="black"
)
except Exception as err:
self.finish_label.configure(
text=f"Downloaded error: {err}",
text_color="red"
)
def on_progress(self, stream, chunk, bytes_remaining):
"""Progress bar."""
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage_completed = bytes_downloaded / total_size * 100
per = str(int(percentage_completed))
self.progress_label.configure(text=per + "%")
self.progress_label.update()
self.progress_bar.set(float(percentage_completed) / 100)
Здесь мы описываем UI, включаем поддержку клавиши CTRL+A в строке ввода ссылки на видео с youtube, подключаем диалоговое окно, которое будет запрашивать директорию сохранения видео, а также реализуем саму загрузку видео с добавлением прогресс бара.
main.py
"""General module."""
from yt_downloader_gui.youtube_downloader import YouTubeDownloader
def main():
"""Create app and start."""
app = YouTubeDownloader()
app.mainloop()
if __name__ == "__main__":
main()
Создаем экземпляр нашего класса и запускаем.
Данный код я хочу выложить на PyPi. Для этого создадим следующий pyproject.toml файл
[tool.poetry]
name = "yt_downloader_gui"
version = "0.0.2"
description = "Simple GUI youtube downloader"
authors = ["Trusikhin Andrei <andrei.trusikhin@gmail.com>"]
license = "MIT"
readme = "README.md"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules"
]
[tool.poetry.urls]
"Homepage" = "https://github.com/Onder7994/yt_downloader_gui"
"Repository" = "https://github.com/Onder7994/yt_downloader_gui"
"Documentation" = "https://github.com/Onder7994/yt_downloader_gui#readme"
[build-system]
requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
build-backend = "poetry_dynamic_versioning.backend"
[tool.poetry.dependencies]
python = ">=3.10"
tk = "0.1.0"
customtkinter = "5.2.1"
packaging = "23.2"
pytube = "15.0.0"
[tool.poetry.scripts]
yt-dl-gui = "yt_downloader_gui.main:main"
[tool.ruff]
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
]
line-length = 88
indent-width = 4
[tool.ruff.lint]
select = ["E", "C", "F", "N", "D"]
ignore = []
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
Из кода видно, что после установки пакета у нас будет доступен cmd yt-dl-gui для запуска приложения.
Чтобы залить данный код на pypi, нужно выполнить следующие:
poetry config pypi-token.pypi <pypi_token>
poetry install
poetry build
poetry publish
Далее проверяем залитое приложение на pypi.
Теперь можно установить пакет через pip непосредственно из pypi:
pip3 install yt_downloader_gui
yt-dl-gui -- запуск приложения
Проект на pypi.
Проект на github.