# PVideoDl Локальная скачивалка файлов и видео с веб-интерфейсом. Запускается одной командой, открывается в браузере, принимает список ссылок, качает в фоне и показывает прогресс в реальном времени. - **Прямые файлы** (`.zip`, `.pdf`, `.mp4`, …) качаются через `httpx` по chunk'ам. - **Видео с сайтов** (YouTube и сотни других) — через `yt-dlp`. - Прогресс течёт в UI по **SSE** в реальном времени. - Две вкладки: **Активные** (что качается сейчас и завершилось за последний час) и **История** (все завершённые загрузки). ## Стек - Бэкенд: Python 3.12, FastAPI, Uvicorn, httpx, yt-dlp, aiosqlite, sse-starlette - Фронтенд: SvelteKit (SPA), TypeScript, Tailwind CSS v4, lucide-svelte - Менеджер зависимостей: `uv` ## Архитектура Реализации спрятаны за интерфейсами в `app/core/` — роуты и сервисы зовут абстракции, а не конкретику. Сегодня `asyncio.Queue` + SQLite, завтра Redis + Postgres — меняется только начинка обёртки. ``` app/ main.py точка входа, lifespan, отдача статики config.py настройки (env PVDL_*) models.py Pydantic-модели api/ роуты: downloads.py, events.py (SSE) core/ абстракции: queue.py, storage.py, events.py (EventBus) services/ downloader.py (httpx/yt-dlp), worker.py (пул воркеров) frontend/ SvelteKit SPA → собирается в frontend/build ``` ## Запуск — готовые скрипты В корне лежат скрипты-обёртки (Linux/macOS — `.sh`, Windows — `.bat`): ```bash # Прод: зависимости -> сборка фронта (если её нет) -> сервер ./run.sh # Windows: run.bat # Дев: бэкенд (:8000) + Vite dev-сервер (:5173) с hot-reload ./dev.sh # Windows: dev.bat ``` `run` открывает , `dev` — . Файлы складываются в `downloads/`. ## Запуск (прод, «для себя») — вручную Фронт собирается в статику, FastAPI отдаёт её с того же origin: ```bash # 1. зависимости uv sync cd frontend && npm install && npm run build && cd .. # 2. запуск uv run pvideodl ``` ## Запуск (дев) — два процесса ```bash # терминал 1 — бэкенд на :8000 uv run python -m app.main # терминал 2 — Vite dev-сервер на :5173 (проксирует /api на :8000) cd frontend && npm run dev ``` Открыть — с hot-reload фронта. ## API | Метод | Путь | Назначение | | -------- | --------------------- | ----------------------------------- | | `POST` | `/api/downloads` | Добавить ссылки (`{"urls": [...]}`) | | `GET` | `/api/downloads` | Список всех загрузок | | `DELETE` | `/api/downloads/{id}` | Удалить задачу | | `GET` | `/api/events` | SSE-поток обновлений прогресса | | `GET` | `/api/health` | Проверка живости | ## Настройки (переменные окружения) | Переменная | По умолчанию | Описание | | ------------------- | ------------------ | ---------------------------- | | `PVDL_DOWNLOAD_DIR` | `./downloads` | Куда складывать файлы | | `PVDL_DB_PATH` | `./app.db` | Файл SQLite | | `PVDL_STATIC_DIR` | `./frontend/build` | Собранная статика фронтенда | | `PVDL_WORKERS` | `3` | Сколько воркеров параллельно | | `PVDL_HOST` | `127.0.0.1` | Хост сервера | | `PVDL_PORT` | `8000` | Порт сервера | ## Тесты ```bash uv run pytest ``` ## Задел на будущее Эндпоинты `pause` / `resume` / `retry` и статус `PAUSED` лягут естественно — модель и слои уже к ним готовы. Тяжёлую инфраструктуру (Redis, Celery, WebSocket, Postgres) вводим только когда конкретная фича упрётся в текущую реализацию.