Initial implementation of yt-dlp HLS proxy server
- Flask app with HLS proxy routes (/hls, /player, /) - yt-dlp integration with 365-day in-memory cache - URL validation with allowed domains (youtube, pornhub, etc) - HTML5 HLS player with hls.js - Unit tests: URL validation, cache, error handling - Integration tests: ffmpeg-generated test video, full proxy chain - Environment-based configuration (PORT, CACHE_TTL, LOG_LEVEL) - MIT license
This commit is contained in:
@@ -1,61 +1,65 @@
|
||||
# Пишем прокси для yt-dlp, чтобы видосы смотреть в браузере без рекламы
|
||||
# Building a yt-dlp Proxy to Watch Videos in Browser Without Ads
|
||||
|
||||
## Введение
|
||||
## Introduction
|
||||
|
||||
Прокси-сервер для yt-dlp позволяет обойти рекламу и ограничения, связанные с просмотром видео на платформах, таких как YouTube. Этот инструмент может быть полезен для тех, кто хочет наслаждаться контентом без перерывов на рекламу или для тех, кто сталкивается с региональными ограничениями и прочей цензурой.
|
||||
A yt-dlp proxy server allows bypassing ads and restrictions when watching videos on platforms like YouTube. This tool is useful for those who want to enjoy content without ad breaks or for those facing regional restrictions and censorship.
|
||||
|
||||
## Задача
|
||||
## Task
|
||||
|
||||
Наша цель - создать простой прокси-сервер, который будет обрабатывать запросы вида http://localhost/www.youtube.com/watch&v=VIDEO_ID и возвращать страницу с HLS плеером. Как понятно из URL - в query будет передаваться URL видео, который нужно проксировать.
|
||||
Our goal is to create a simple proxy server that handles requests like `http://localhost/www.youtube.com/watch&v=VIDEO_ID` and returns a page with an HLS player. As clear from the URL - the video URL to be proxied is passed in the query.
|
||||
|
||||
Проксировать надо именно HLS поток, так как он позволяет минимизировать трафик и обеспечивает более плавное воспроизведение видео. Кроме того, HLS поддерживается большинством современных браузеров, что делает его идеальным выбором для нашего прокси-сервера.
|
||||
We need to proxy the HLS stream specifically, as it allows minimizing traffic and provides smoother video playback. Additionally, HLS is supported by most modern browsers, making it the ideal choice for our proxy server.
|
||||
|
||||
Сам прокси должен обрабатывать запросы вида http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID), где содержимоее Query String экранируется для использования query string и добавления к пути файлов HLS, таких как index.m3u8 и ts файлы. Например, запрос http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/index.m3u8 должен возвращать HLS плейлист для видео с указанным VIDEO_ID.
|
||||
The proxy should handle requests like `http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)`, where the Query String content is escaped for use as a query string and added to the path for HLS files such as index.m3u8 and ts files. For example, a request to `http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/index.m3u8` should return the HLS playlist for the video with the specified VIDEO_ID.
|
||||
|
||||
Задача же прокси будет в том, чтобы на запрос http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/index.m3u8, проксировать запрос к yt-dlp, который будет скачивать HLS плейлист для видео с указанным VIDEO_ID и возвращать его клиенту. Аналогично, при запросе http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/segment.ts, прокси должен проксировать запрос к yt-dlp для получения соответствующего сегмента видео и возвращать его клиенту.
|
||||
The proxy's task is: on request `http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/index.m3u8`, proxy the request to yt-dlp, which will download the HLS playlist for the video with the specified VIDEO_ID and return it to the client. Similarly, when requesting `http://localhost/hls/www.youtube.com/watch(v=VIDEO_ID)/segment.ts`, the proxy should proxy the request to yt-dlp to get the corresponding video segment and return it to the client.
|
||||
|
||||
Очевдино надо будет временно кэшировать сессии yt-dlp на какой-то срок в избежание повторного парсинга страницы видео при каждом запросе к HLS плейлисту и сегментам. Это позволит значительно улучшить производительность и снизить нагрузку на сервер.
|
||||
Obviously, we need to temporarily cache yt-dlp sessions for some period to avoid re-parsing the video page on each request to the HLS playlist and segments. This will significantly improve performance and reduce server load.
|
||||
|
||||
## Реализация
|
||||
## Implementation
|
||||
|
||||
Для реализации прокси-сервера для yt-dlp можно использовать Python и библиотеку Flask для создания веб-сервера. Также потребуется библиотека yt-dlp для взаимодействия с YouTube и другими платформами и получения HLS потоков.
|
||||
To implement the yt-dlp proxy server, you can use Python and the Flask library to create a web server. You will also need the yt-dlp library to interact with YouTube and other platforms and get HLS streams.
|
||||
|
||||
В качестве шаблонизатора HTML можно использовать Jinja2, который встроен в Flask, для динамической генерации страницы с HLS плеером на основе URL видео. Стили: `<link rel="stylesheet" href="https://unpkg.com/mvp.css">` для простого и чистого дизайна.
|
||||
As an HTML templating engine, you can use Jinja2, which is built into Flask, for dynamically generating the page with the HLS player based on the video URL. Styles: `<link rel="stylesheet" href="https://unpkg.com/mvp.css">` for a simple and clean design.
|
||||
|
||||
### Правила реализации
|
||||
### Implementation Rules
|
||||
|
||||
1. Минимальный MVP: реализуем только необходимое для HLS-проксирования одного URL видео на один запрос через `yt-dlp`.
|
||||
2. Минимальный стек: только Python, Flask, `yt-dlp` и внешний плеер для HLS; без Node.js и без сложных фреймворков.
|
||||
3. Один формат: поддерживаем только HLS (`.m3u8` + сегменты).
|
||||
4. Одна платформа в MVP: сначала PornHub; расширение на другие платформы — только после стабилизации.
|
||||
5. Простая маршрутизация: короткие и предсказуемые URL без лишней магии.
|
||||
6. Кэш внешний. Только HTTP заголовки для управления кэшем, без сложных in-memory решений. TTL кэша — 365 дней.
|
||||
7. Безопасность по минимуму, но обязательно: валидация входного URL, ограничение целевых доменов теми, которые поддерживаются yt-dlk, таймауты запросов.
|
||||
8. Ошибки и логи — только практичный минимум: понятные HTTP-ошибки и базовое структурированное логирование.
|
||||
9. Конфигурация только через переменные окружения: порт, TTL кэша, уровень логов и таймауты.
|
||||
10. HTTPS не в приложении: TLS завершается внешним reverse proxy (Nginx/Caddy/Traefik), Flask работает за ним.
|
||||
11. Тесты только на критичный путь: парсинг URL, кэш, проксирование плейлиста и сегмента, обработка ошибок.
|
||||
12. Документация и лицензия: только `README.md`, `AGENTS.md` и лицензия MIT.
|
||||
1. Minimum MVP: implement only what's necessary for HLS proxying one video URL per request through `yt-dlp`.
|
||||
2. Minimum stack: only Python, Flask, `yt-dlp` and external HLS player; no Node.js and no complex frameworks.
|
||||
3. One format: support only HLS (`.m3u8` + segments).
|
||||
4. One platform in MVP: first PornHub; extending to other platforms — only after stabilization.
|
||||
5. Simple routing: short and predictable URLs without extra magic.
|
||||
6. External cache. Only HTTP headers for cache management, no complex in-memory solutions. Cache TTL — 365 days.
|
||||
7. Security at minimum, but required: validate input URL, restrict target domains to those supported by yt-dlp, request timeouts.
|
||||
8. Errors and logs — only practical minimum: understandable HTTP errors and basic structured logging.
|
||||
9. Configuration only through environment variables: port, cache TTL, log level and timeouts.
|
||||
10. HTTPS not in application: TLS terminates at external reverse proxy (Nginx/Caddy/Traefik), Flask runs behind it.
|
||||
11. Tests only on critical path: URL parsing, cache, playlist and segment proxying, error handling.
|
||||
12. Documentation and license: only `README.md`, `AGENTS.md` and MIT license.
|
||||
|
||||
### Структура проекта
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
- app.py - основной файл приложения Flask, который будет обрабатывать входящие HTTP-запросы и взаимодействовать с yt-dlp через функции из dlp.py.
|
||||
- dlp.py - модуль для взаимодействия с yt-dlp, который будет содержать функции для получения HLS плейлистов и сегментов.
|
||||
функции:
|
||||
- get_hls_playlist(video_url): получает HLS плейлист для указанного видео в виде строки, которая может быть возвращена клиенту. Список сегментов должен быть отфильтрован так, чтобы включать только те, которые доступны для данного видео и поддерживаются yt-dlp.
|
||||
- get_hls_segment(video_url, segment_name): получает указанный сегмент видео: скачивает его с помощью yt-dlp и возвращает его содержимое в виде байтов, которые могут быть возвращены клиенту.
|
||||
- app.py - main Flask application file that handles incoming HTTP requests and interacts with yt-dlp through functions from dlp.py.
|
||||
- dlp.py - module for interacting with yt-dlp, containing functions to get HLS playlists and segments.
|
||||
functions:
|
||||
- get_hls_playlist(video_url): gets HLS playlist for the specified video as a string that can be returned to the client. The segment list should be filtered to only include those available for the given video and supported by yt-dlp.
|
||||
- get_hls_segment(video_url, segment_name): gets the specified video segment: downloads it using yt-dlp and returns its content as bytes that can be returned to the client. It should also use yt-dlp to download the segment since only yt-dlp can handle the necessary authentication and access control for the video content.
|
||||
|
||||
кэширование:
|
||||
- Кэширование сессий yt-dlp будет реализовано с помощью простого словаря в памяти, который будет хранить результаты парсинга видео для каждого VIDEO_ID. Без сложных in-memory решений, просто словарь с TTL для каждого ключа. TTL будет установлен на 365 дней, что позволит эффективно кэшировать результаты и минимизировать повторные запросы к yt-dlp.
|
||||
- utils.py - вспомогательные функции для валидации URL, управления кэшем и обработки ошибок.
|
||||
- tests/ - папка для тестов, которые будут проверять критичные пути приложения, такие как парсинг URL, кэширование, проксирование плейлиста и сегментов, а также обработку ошибок.
|
||||
- template/index.html - простой HTML-файл с формой для ввода URL видео.
|
||||
- template/player.html - HTML-файл с HLS плеером, который будет использоваться для воспроизведения видео, полученного через прокси.
|
||||
caching:
|
||||
- Caching of yt-dlp sessions will be implemented using a simple in-memory dictionary that will store video parsing results for each VIDEO_ID. No complex in-memory solutions, just a dictionary with TTL for each key. TTL will be set to 365 days, which will effectively cache results and minimize repeated requests to yt-dlp.
|
||||
- utils.py - helper functions for URL validation, cache management and error handling.
|
||||
- tests/ - folder for tests that will check critical application paths such as URL parsing, caching, playlist and segment proxying, and error handling.
|
||||
1. functions tests
|
||||
2. integration tests for the main application flow:
|
||||
signle integration test that will consist of server serving a single test video (use ffmpeg for generating it). it should query that server over proxy and check if it works properly.
|
||||
yt-dlp expects from the server a javascript player that it can recognize. also server should set a cookie on the video page and require that cookie for the HLS playlist and segments requests. this will ensure that only requests coming from the video page can access the HLS content, providing a basic level of security and preventing unauthorized access to the video streams.
|
||||
- templates/index.html - simple HTML file with form for video URL input.
|
||||
- templates/player.html - HTML file with HLS player that will be used to play video obtained through proxy.
|
||||
- requirements.txt
|
||||
- README.md
|
||||
- AGENTS.md
|
||||
- LICENSE
|
||||
```
|
||||
|
||||
Никаких файлов, кроме перечисленных выше, в проекте не будет. Все функции и логика будут реализованы в этих файлах, и не будет никаких дополнительных модулей или сложных структур данных.
|
||||
No files other than those listed above will be in the project. All functions and logic will be implemented in these files, and there will be no additional modules or complex data structures.
|
||||
|
||||
Reference in New Issue
Block a user