Update PVideoDl to support custom download strategies and enhance cookie handling. Added new downloader registration system, updated README for clarity on downloaders, and introduced cookies configuration in settings. Frontend now includes a dedicated tab for download strategies and API endpoints for listing them.
This commit is contained in:
@@ -7,8 +7,11 @@
|
||||
- **Прямые файлы** (`.zip`, `.pdf`, `.mp4`, …) качаются через `httpx` по chunk'ам.
|
||||
- **Видео с сайтов** (YouTube и сотни других) — через `yt-dlp`.
|
||||
- Прогресс течёт в UI по **SSE** в реальном времени.
|
||||
- Две вкладки: **Активные** (что качается сейчас и завершилось за последний час)
|
||||
и **История** (все завершённые загрузки).
|
||||
- Три вкладки: **Активные** (что качается сейчас и завершилось за последний час),
|
||||
**История** (все завершённые загрузки) и **Загрузчики** (какие стратегии скачивания
|
||||
сейчас доступны).
|
||||
- Если ссылка не прямой файл и ни один загрузчик её не поддерживает — загрузка
|
||||
завершается явной ошибкой (а не молчаливой попыткой угадать).
|
||||
|
||||
## Стек
|
||||
|
||||
@@ -29,10 +32,44 @@ app/
|
||||
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 (пул воркеров)
|
||||
services/ downloader.py (реестр стратегий), worker.py (пул воркеров)
|
||||
extractors/ расширения для сайтов с непрямыми ссылками
|
||||
frontend/ SvelteKit SPA → собирается в frontend/build
|
||||
```
|
||||
|
||||
### Расширения: сайты с непрямыми ссылками
|
||||
|
||||
Выбор стратегии — цепочка обработчиков с приоритетами (`pick_downloader`):
|
||||
кастомные экстракторы (priority > 0) перехватывают URL раньше встроенных
|
||||
`HttpxDownloader` (прямые файлы) и `YtDlpDownloader` (универсальный фолбэк).
|
||||
|
||||
Добавить сайт = положить один файл в `app/services/extractors/`. Чаще всего хватает
|
||||
**резолвера** — достать прямую ссылку (и при нужде `Referer`/`Cookie`), а
|
||||
скачивание, прогресс и `(n)`-имена наследуются:
|
||||
|
||||
```python
|
||||
# app/services/extractors/my_site.py
|
||||
import re
|
||||
from app.services.downloader import Resolved, SiteExtractor, register
|
||||
|
||||
@register
|
||||
class MySite(SiteExtractor):
|
||||
priority = 100
|
||||
|
||||
@classmethod
|
||||
def matches(cls, url: str) -> bool:
|
||||
return "my-site.com/watch/" in url
|
||||
|
||||
async def resolve(self, url: str) -> Resolved:
|
||||
# ... найти настоящую ссылку (запрос/скрейпинг) ...
|
||||
return Resolved(download_url=real_url, headers={"Referer": url})
|
||||
```
|
||||
|
||||
Модули пакета авто-загружаются на старте (`load_extractors()`). Готовый образец —
|
||||
[google_drive.py](app/services/extractors/google_drive.py). Если сайту нужен
|
||||
нестандартный процесс (HLS, сегменты) — наследуйся прямо от `Downloader` и
|
||||
переопредели `download()` целиком.
|
||||
|
||||
## Запуск — готовые скрипты
|
||||
|
||||
В корне лежат скрипты-обёртки (Linux/macOS — `.sh`, Windows — `.bat`):
|
||||
@@ -80,6 +117,7 @@ cd frontend && npm run dev
|
||||
| `POST` | `/api/downloads` | Добавить ссылки (`{"urls": [...]}`) |
|
||||
| `GET` | `/api/downloads` | Список всех загрузок |
|
||||
| `DELETE` | `/api/downloads/{id}` | Удалить задачу |
|
||||
| `GET` | `/api/downloaders` | Список загруженных стратегий |
|
||||
| `GET` | `/api/events` | SSE-поток обновлений прогресса |
|
||||
| `GET` | `/api/health` | Проверка живости |
|
||||
|
||||
@@ -93,6 +131,11 @@ cd frontend && npm run dev
|
||||
| `PVDL_WORKERS` | `3` | Сколько воркеров параллельно |
|
||||
| `PVDL_HOST` | `127.0.0.1` | Хост сервера |
|
||||
| `PVDL_PORT` | `8000` | Порт сервера |
|
||||
| `PVDL_COOKIES_FROM_BROWSER` | — | Cookies для yt-dlp из браузера: `chrome`, `firefox`, `edge`… (можно `chrome:Профиль`) |
|
||||
| `PVDL_COOKIES_FILE` | — | Cookies для yt-dlp из файла (формат Netscape `cookies.txt`) |
|
||||
|
||||
> Cookies нужны для сайтов, которые блокируют анонимные запросы (возрастной гейт,
|
||||
> логин, гео) и отдают ошибки вроде `HTTP 410 Gone`. Достаточно одного из вариантов.
|
||||
|
||||
## Тесты
|
||||
|
||||
|
||||
Reference in New Issue
Block a user