# IPTV Checker (iptvc) [![Последний релиз](https://img.shields.io/gitea/v/release/IPTV/iptvc?gitea_url=https%3A%2F%2Fgit.axenov.dev&display_name=release&color=green&cacheSeconds=600)](https://git.axenov.dev/IPTV/iptvc/releases/latest) Консольная программа для проверки IPTV-плейлистов в формате m3u или m3u8. > **Веб-сайт:** [m3u.su](https://m3u.su) > Документация: [m3u.su/docs](https://m3u.su/docs) > Telegram-канал: [@iptv_aggregator](https://t.me/iptv_aggregator) > Исходный код: [git.axenov.dev/IPTV](https://git.axenov.dev/IPTV) ## Установка Достаточно скачать и распаковать архив с подходящим исполняемым файлом [со страницы последнего релиза](https://git.axenov.dev/IPTV/iptvc/releases/latest): | ОС | Скачать для `amd64` | Скачать для `arm64` | | ------- | ---------------------------------- | ---------------------------------- | | Linux | [linux_amd64.zip][linux_amd64] | [linux_arm64.zip][linux_arm64] | | MacOS | [darwin_amd64.zip][darwin_amd64] | [darwin_arm64.zip][darwin_arm64] | | Windows | [windows_amd64.zip][windows_amd64] | [windows_arm64.zip][windows_arm64] | [linux_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/linux_amd64.zip [darwin_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/darwin_amd64.zip [windows_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/windows_amd64.zip [linux_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/linux_arm64.zip [darwin_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/darwin_arm64.zip [windows_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/windows_arm64.zip ## Компиляция Для сборки потребуется Go версии 1.23.6 или выше. Контейнерная сборка выполняется на Go 1.25. ```bash git clone https://git.axenov.dev/IPTV/iptvc.git cd iptvc make help go build -o iptvc . ``` Для быстрого запуска из исходников используйте `go run .`. Для запуска тестов и статического анализа: ```bash go test ./... go vet ./... ``` Кросс-компиляция и упаковка релизов выполняются целями `make linux`, `make win`, `make darwin` и `make release`. Архивы создаются в каталоге `bin/`; архитектура задаётся переменной `GOARCH`, например `make linux GOARCH=arm64`. ## Быстрый старт Открыть терминал в директории, куда распакован исполняемый файл `iptvc`. Выполнить `./iptvc help` для получения краткой справки. Если был клонирован репозиторий, то вместо `./iptvc` можно запустить `go run .` или `make help`. Ниже рассмотрены простые примеры использования программы для проверки плейлистов. ### Проверка файла плейлиста 1. Скачать любой файл плейлиста, сохранив его в файл с именем, например, `mypls.m3u` 2. Выполнить команду `./iptvc check -f mypls.m3u` Можно указывать множество разных файлов (каждый с `-f`) и комбинировать с другими аргументами. ### Проверка плейлиста по ссылке 1. Найти прямую ссылку на плейлист в интернете, например, `http://m3u.su/XYZ` 2. Выполнить команду `./iptvc check -u http://m3u.su/XYZ` Можно указывать множество разных ссылок (каждый с `-u`) и комбинировать с другими аргументами. ### Проверка плейлиста из ini-списка Подробности об ini-файле и его формате можно прочесть здесь: https://git.axenov.dev/IPTV/playlists 1. Скачать файл [`playlists.ini`](https://git.axenov.dev/IPTV/playlists/raw/branch/master/playlists.ini) или создать локальный файл в аналогичном формате (например, `./test.ini`) 2. Выполнить команду `./iptvc check` или `./iptvc check -i playlist.ini` для проверки всех плейлистов из файла `./playlists.ini` 3. Выполнить команду `./iptvc check -i test.ini -c ABC`, чтобы проверить только плейлист с кодом `ABC` из файла `./test.ini` Если `-i` не указан явно, то будет попытка прочитать файл `playlists.ini`, находящийся в одной директории с iptvc. Аргумент `-i` можно указывать только однажды, но его можно комбинировать с `-f` и `-u`. ### Флаги команды `check` Источники плейлистов: * `--file|-f PATH` — локальный файл плейлиста M3U/M3U8; флаг можно указывать несколько раз; * `--url|-u URL` — удалённый плейлист по HTTP/HTTPS; флаг можно указывать несколько раз; * `--code|-c CODE` — код плейлиста из ini-файла; флаг можно указывать несколько раз; * `--ini|-i PATH` — путь к ini-файлу; * `--tags|-t PATH` — путь к файлу тегов каналов. Управление выводом и повторными проверками: * `--json|-j` — вывести результаты проверки в формате JSON; * `--quiet|-q` — подавить журналы, не отключая вывод JSON; * `--verbose|-v` — включить подробный журнал; * `--random|-r N` — выбрать N случайных плейлистов из ini-файла; * `--repeat N` — повторить проверку N раз, значение `0` означает бесконечный цикл; * `--playlists-all-cooldown N` — ждать N миллисекунд между полными циклами проверки; значение также можно задать через `check.playlists.all-cooldown`. Параметры проверки и кеша также можно переопределить CLI-флагами. Полный список доступен через `./iptvc check --help`. Например, можно получить только json с результатами, передать его в `jq` и, отфильтровав результат, вывести названия оффлайн каналов: ``` ./iptvc check ... -j -q | jq '.[].channels[] | select(.isOnline == false).title' ``` > [!NOTE] > Набери `./iptvc help` для получения помощи. ## Веб-интерфейс Программа включает встроенный веб-сервер для просмотра плейлистов и результатов их проверки. ### Запуск ``` ./iptvc serve -i playlists.ini -p 8800 ``` ### Параметры команды `serve` * `-p, --port` — порт для веб-сервера (переопределяет `config.yml` и `SERVER_PORT`); * `--host` — хост для привязки (переопределяет `config.yml` и `SERVER_HOST`); * `--check` — включить фоновую проверку плейлистов (по умолчанию выключена). При указании `--check` доступны флаги проверки: * `-i, --ini` — путь к ini-файлу (по умолчанию `./playlists.ini`); * `-t, --tags` — путь к файлу тегов (по умолчанию `./channels.json`); * `-r, --random` — проверить N случайных плейлистов из ini-файла; * `--playlists-all-cooldown N` — пауза между полными циклами проверки в миллисекундах; если флаг не указан, используется `check.playlists.all-cooldown` из конфигурации; * `--repeat` — количество циклов проверки (по умолчанию `0` — бесконечно). ### Конфигурация Приоритет настроек (от низшего к высшему): 1. **Значения по умолчанию** — встроены в код; 2. **`config.yml`** — YAML-файл в корне проекта (путь можно задать через флаг `--config`); 3. **Переменные окружения** — переопределяют значения из `config.yml` (если заданы); 4. **CLI-флаги** — переопределяют значения из окружения и `config.yml` (если заданы явно). Флаги `--port` и `--host` переопределяют конфигурацию только если переданы явно. Если флаг не указан, используется значение из переменной окружения, затем из `config.yml`, затем значение по умолчанию. Файл `.env` загружается автоматически, переменные из него применяются как переменные окружения. #### `config.yml` ```yaml app: title: IPTV Checker timezone: GMT debug: false log_level: info server: host: localhost port: 8800 site: base-url: http://localhost:8800 repo-url: https://git.axenov.dev/IPTV/iptvc page-size: 0 favicon: header: title: IPTV Checker navigation: [] footer-links: [] check: start-on-serve: false playlists: user-agent: - Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer timeout: 10000 # ms, максимальное время ожидания запроса all-cooldown: 60000 # ms, пауза между полными циклами проверки one-cooldown: 0 # ms, задержка после каждого плейлиста max-routines: 5 # максимальное количество параллельных проверок per-routine: 1 # количество плейлистов на одну процедуру channels: user-agent: Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer timeout: 10000 # ms, максимальное время ожидания запроса byte-range: 512 # байт, объём данных для получения от сервера cooldown: 0 # ms, задержка после каждого канала max-routines: 50 # максимальное количество параллельных проверок per-routine: 10 # количество каналов на одну процедуру cache: enabled: false host: localhost port: 6379 username: password: db: 1 ttl: 1800 ``` `check.playlists.all-cooldown` задаёт паузу между полными циклами проверки. Она используется командами `check` и `serve` и больше не применяется дополнительно внутри одного цикла. `check.playlists.one-cooldown` задаёт паузу между отдельными плейлистами, а `check.channels.cooldown` — между каналами одного плейлиста. Параметры задержек могут быть заданы как число или диапазон `[min, max]` в миллисекундах. При диапазоне для каждой операции выбирается случайное значение. `user-agent` может быть строкой или массивом строк; при массиве выбирается случайное значение. Остальные параметры задаются скалярами. #### Переменные окружения | Переменная | Соответствует в `config.yml` | Описание | | ---------------- | ---------------------------- | ----------------------------------- | | `APP_DEBUG` | `app.debug` | Режим отладки | | `APP_TITLE` | `site.header.title` | Заголовок сайта | | `APP_TIMEZONE` | `app.timezone` | Часовой пояс | | `APP_URL` | `site.base-url` | Базовый URL для ссылок | | `CACHE_ENABLED` | `cache.enabled` | Включить кеш (KeyDB/Redis) | | `CACHE_HOST` | `cache.host` | Хост KeyDB/Redis | | `CACHE_PORT` | `cache.port` | Порт KeyDB/Redis | | `CACHE_USERNAME` | `cache.username` | Имя пользователя KeyDB/Redis | | `CACHE_PASSWORD` | `cache.password` | Пароль KeyDB/Redis | | `CACHE_DB` | `cache.db` | Номер БД KeyDB/Redis | | `CACHE_TTL` | `cache.ttl` | TTL записей в кеше (сек) | | `WEB_PORT` | `server.port` | Порт веб-сервера | | `WEB_HOST` | `server.host` | Хост для привязки | | `CHECK_PLAYLISTS_ALL_COOLDOWN` | `check.playlists.all-cooldown` | Пауза между циклами проверки (мс) | | `CHECK_PLAYLISTS_ONE_COOLDOWN` | `check.playlists.one-cooldown` | Пауза между плейлистами (мс) | | `CHECK_CHANNELS_COOLDOWN` | `check.channels.cooldown` | Пауза между каналами (мс) | | `PAGE_SIZE` | `site.page-size` | Размер страницы (0 — без пагинации) | | `REPO_URL` | `site.repo-url` | Ссылка на репозиторий | ### Маршруты | Метод | Путь | Описание | | ----- | ----------------------- | ---------------------------------------- | | GET | `/` | Главная страница со списком плейлистов | | GET | `/page/{N}` | Страница N списка плейлистов | | GET | `/{code}` | Редирект на прямую ссылку плейлиста | | GET | `/{code}.m3u[8]` | Редирект на прямую ссылку плейлиста | | GET | `/{code}/details` | Страница с описанием плейлиста | | GET | `/api/playlists/{code}` | JSON: информация о плейлисте | | GET | `/api/version` | JSON: версии компонентов | | GET | `/api/health` | JSON: состояние сервиса | | GET | `/api/stats` | JSON: статистика по плейлистам и каналам | ### Связь с проверкой Веб-сервер отображает данные из кеша KeyDB/Redis, который заполняется командой `check`. Если кеш недоступен, все плейлисты отображаются со статусом `unknown`. Для обновления данных в фоне запустите `serve` с флагом `--check`: ``` ./iptvc serve -i playlists.ini -p 8800 --check ``` Результаты проверок появляются на веб-страницах немедленно после проверки каждого плейлиста, не дожидаясь завершения полного цикла. После завершения цикла приложение ждёт значение `check.playlists.all-cooldown` и затем начинает следующий цикл. Можно запускать `serve` и `check` отдельными процессами: ``` ./iptvc check --repeat 0 --playlists-all-cooldown 60000 & ./iptvc serve ``` Или используйте Docker Compose. Перед запуском подготовьте `.env`, `config.yml`, `playlists.ini` и `channels.json` в рабочем каталоге: ```bash cp .env.example .env cp config.yml.example config.yml docker compose up -d --build docker compose logs -f iptvc docker compose down ``` Compose запускает сервисы `iptvc`, `keydb` и `docs`. В текущем `compose.yml` контексты сборки указаны как `./iptvc` и `./docs`, поэтому запуск из одного только каталога этого репозитория может потребовать внешней структуры проекта или корректировки контекстов. ## Результаты проверки Программа логирует процесс и результаты своей работы. Рассмотрим лог на примере. В рабочей директории лежит файл `playlists.ini`, в котором минимально описано два плейлиста: ```ini [first] pls='https://example.com/list1.m3u' [second] pls='https://example.com/list2.m3u' ``` Программа запущена следующим образом: `./iptvc check -c first` (чтобы проверить только плейлист с кодом `first` из ini-файла). Вывод будет примерно таким: ``` 2025/01/02 12:34:00 Loading playlists from ini-file: /home/user/playlists.ini 2025/01/02 12:34:00 Loaded 2 playlists 2025/01/02 12:34:00 [001/001] Playlist [first] 2025/01/02 12:34:00 Fetching... (https://example.com/list1.m3u) 2025/01/02 12:34:00 Parsing content... 2025/01/02 12:34:00 Parsed, checking channels (114)... 2025/01/02 12:34:00 Check parameters calculated: count=114 timeout=8.00s routines=12 2025/01/02 12:34:12 Checked successfully! online=101 onlinePercent=88.60% offline=13 offlinePercent=11.40% elapsedTime=12.39s ``` Разберём построчно: 1. Загрузка ini-файла 2. Файл загружен, в нём 2 плейлиста 3. Начало обработки плейлиста `first` 4. Скачивание плейлиста `first` по ссылке `https://example.com/list1.m3u` в оперативную память 5. Плейлист скачан, начало разбора плейлиста 6. Плейлист разобран, начало проверки каналов (114 штук) 7. Определены параметры проверки (подробности ниже) 8. (спустя время) Проверка успешно завершена: онлайн каналов 101 (88.60% от всех), оффлайн каналов 13 (11.40% от всех), затрачено 12 секунд. ### Параметры проверки Выше в п.7 видно некоторые служебные данные: * `timeout` — таймаут каждого запроса в секундах (макс. время ожидания ответа канала); * `routines` — количество одновременных проверок. Эти параметры рассчитываются динамически для каждого плейлиста в отдельности, исходя из количества каналов в каждом (`count`). См. [app/checker/checker.go](app/checker/checker.go) для подробностей. Идея в том, чтобы найти баланс между скоростью проверки и качеством: * чем ниже коэффициент `k`, тем больше горутин, меньше таймаут, быстрее проверка, хуже результаты; * чем выше коэффициент `k`, тем меньше горутин, больше таймаут, медленнее проверка, лучше результаты. На скорость проверки влияют: * количество горутин (чем выше, тем больше каналов проверяется параллельно); * таймаут (тем ниже, тем быстрее закончится проверка канала); * количество каналов (чем больше, тем дольше общий процесс); * скорость ответа сервера (чем выше, тем хуже) и количество данных, которые он отдаёт (чем больше, тем хуже). На качество проверки влияет таймаут: * чем выше, тем выше вероятность получить успешный ответ от сервера, транслирующего поток; * чем ниже, тем выше вероятность не дождаться успешного ответа и засчитать канал нерабочим. > [!NOTE] > Логика балансирования будет уточняться и корректироваться по мере развития проекта, исходя из реального применения. ### Коды возврата * 0 — успех * 1 — общая ошибка, см. вывод * 2 — команде `check` не переданы параметры `--file`, `--url` и `--code` ## Лицензия ПО распространяется на условиях [лицензии MIT](LICENSE).