Пишем простой загрузчик видео с YouTube

0
(0)

Использовать будем python и библиотеку tkinter и customtkinter. Наш будущий загрузчик видео будет выглядеть так:

Код будет достаточно простым, всего два модуля. Первый из них youtube_downloader.py

Python
"""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

Python
"""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 файл

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, нужно выполнить следующие:

Bash
poetry config pypi-token.pypi <pypi_token>
poetry install
poetry build
poetry publish

Далее проверяем залитое приложение на pypi.

Теперь можно установить пакет через pip непосредственно из pypi:

Bash
pip3 install yt_downloader_gui 
yt-dl-gui -- запуск приложения

Проект на pypi.

Проект на github.

Насколько статья полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Оставить комментарий