Local TV Guide: программа местного ТВ через CCcam
Если ты уже настроил CCcam или OScam, каналы открываются, картинка чистая — и тут заходишь в программу передач, а там либо пусто, либо какой-то чужеязычный EPG от немецкого или польского пакета. Это стандартная ситуация. Проблема не в настройках карточки, а в том, как вообще устроен EPG в DVB-системах. Ниже — полный разбор того, как получить нормальный local tv guide на своём ресивере.
Что такое local TV guide и почему его нет из коробки
CCcam и OScam занимаются одним делом — расшифровкой потока через ECM/EMM-обмен с сервером. Что именно транслируется внутри этого потока — не их забота. А EPG (Electronic Programme Guide) — это отдельная таблица стандарта DVB, называется EIT (Event Information Table). Она идёт в том же транспондере, что и канал, но содержит данные, которые решает отдавать сам провайдер.
EPG в DVB-потоке vs внешний XMLTV
Провайдер может слать EIT полностью, урезанно или вообще не слать — зависит от его политики. Большинство европейских спутниковых пакетов (Astra 19.2°E, Hotbird 13°E) отдают EIT только для своих каналов и только на своём языке. Для региональных и местных каналов там нередко пусто.
XMLTV — это открытый формат XML-файла с программой передач. Ресивер или плагин скачивает его из интернета, парсит и показывает в гиде. Формат не зависит от провайдера, поэтому можно собрать программу для любого канала — хоть регионального, хоть IPTV.
Почему через CCcam/OScam EPG приходит чужой или пустой
Когда ресивер принимает сигнал с Astra 19.2°E, он видит EIT от того провайдера, чей транспондер сканирует. Например, для Sky Deutschland — немецкий EPG на немецком. CCcam открыл тебе доступ к каналу, но EIT приходит тот же — немецкий. Ресивер честно его отображает.
Бывает и обратная ситуация: канал принимается через нестандартный транспондер или в пакете без EIT вообще — тогда в гиде пусто. Никакой магии нет: что провайдер положил в поток, то ресивер и показывает.
Разница между now/next и 7-дневным гидом
EIT делится на два раздела. Present/Following (now/next) — минимальный набор: текущая и следующая передача. Передаётся практически всегда. Schedule — расписание на 7-8 дней. Его отдают далеко не все провайдеры, и даже когда отдают — только для своих каналов. Именно поэтому на большинстве пакетов ресивер показывает "сейчас/дальше" но не строит недельный local tv guide.
Источники локального XMLTV для EPG
Для нормальной программы нужен внешний источник данных. Самый распространённый способ — XMLTV-файл, сгенерированный граббером. Граббер ходит на сайты телеканалов или агрегаторов и собирает расписание в стандартный формат.
Открытые XMLTV-сборщики (WebGrab+Plus, tv_grab_*)
WebGrab+Plus (WG++) — наиболее гибкий инструмент. Работает на Windows и Linux, поддерживает siteini-файлы для сотен сайтов с программой передач. Конфигурация — один файл WebGrab++.config.xml. Запускаешь скрипт, он собирает расписание и складывает в guide.xml.
Альтернатива — утилиты семейства tv_grab_* из пакета xmltv-utils. В Debian/Ubuntu устанавливается через apt install xmltv-utils. Для разных стран есть свои граббера: tv_grab_ru, tv_grab_uk_rt, tv_grab_de_tvtoday и т.д. Качество зависит от конкретного граббера — некоторые давно не обновлялись.
Формат XMLTV: channel id, programme, start/stop
Базовая структура выглядит так:
<?xml version="1.0" encoding="UTF-8"?>
<tv generator-info-name="WebGrab+Plus">
<channel id="channel1.example.com">
<display-name lang="ru">Первый канал</display-name>
</channel>
<programme start="20260427060000 +0300" stop="20260427070000 +0300" channel="channel1.example.com">
<title lang="ru">Утренние новости</title>
<desc lang="ru">Обзор главных событий дня</desc>
</programme>
</tv>
Ключевой момент — атрибуты start и stop содержат timestamp с часовым поясом. Если offset неверный, все передачи будут сдвинуты.
Где брать сетку для региональных каналов
Публичных агрегаторов хватает, но региональные каналы — отдельная история. Если канал вещает только в твоём городе и у него нет нормального сайта с расписанием, придётся писать собственный siteini для WG++ или граббер на Python. Это несколько часов работы, но для 5-10 важных региональных каналов оправдано.
Для крупных федеральных и европейских каналов siteini уже есть в репозитории WG++ на GitHub — там несколько сотен файлов для разных стран.
Кодировка UTF-8 и часовой пояс
Два источника головной боли. Кодировка: XMLTV должен быть в UTF-8. Если граббер отдаёт windows-1251 (частое явление для старых российских сайтов), кириллица на ресивере превратится в кракозябры. Конвертировать можно через iconv -f windows-1251 -t UTF-8 input.xml > output.xml.
Часовой пояс: в WG++ конфиг WebGrab++.config.xml содержит тег <postprocess> и <timespan>. Главное — чтобы offset в сгенерированном XML совпадал с реальным TZ канала. Московское время — +0300 без летнего перевода.
Настройка EPGImport на Enigma2 (OpenATV/OpenPLi)
EPGImport — стандартный плагин для Enigma2, умеет скачивать XMLTV, парсить и заполнять внутренний кеш EPG ресивера. Работает на VU+, Dreambox, GigaBlue и любом другом железе с Enigma2.
Установка плагина: opkg install enigma2-plugin-extensions-epgimport
Через SSH на ресивер:
opkg update
opkg install enigma2-plugin-extensions-epgimport
На прошивках OpenPLi плагин может быть в репозитории под именем epgimport без префикса. После установки он появится в меню: Плагины → EPGImport.
Структура /etc/epgimport/ — sources.xml и channels файлы
Плагин читает конфиги из /etc/epgimport/. Там два типа файлов:
- *.sources.xml — откуда тянуть XMLTV (URL или локальный путь)
- *.channels.xml — привязка channel id из XMLTV к ServiceReference ресивера
Пример mylocal.sources.xml:
<sources>
<source type="gen_xmltv" nocheck="1">
<description>Мой локальный EPG</description>
<url>http://192.168.1.10/epg/guide.xml.gz</url>
<channels>/etc/epgimport/mylocal.channels.xml</channels>
</source>
</sources>
Атрибут nocheck="1" отключает проверку даты файла — полезно при отладке.
Привязка XMLTV channel id к ServiceReference (1:0:1:...)
Это самое неочевидное место. Ресивер идентифицирует канал по ServiceReference — строке вида 1:0:19:2BB0:7FB:2:11A0000:0:0:0:. Нужно сказать EPGImport: данные из XMLTV с id channel1.example.com применять к каналу с таким SRef.
Пример mylocal.channels.xml:
<channels>
<channel id="channel1.example.com">1:0:19:2BB0:7FB:2:11A0000:0:0:0:</channel>
<channel id="channel2.example.com">1:0:1:4B1:41F:2:11A0000:0:0:0:</channel>
</channels>
Если один канал вещает и в HD и в SD на разных транспондерах — пропиши обе SRef через запятую в одном теге <channel>:
<channel id="channel1.example.com">1:0:19:2BB0:7FB:2:11A0000:0:0:0:,1:0:19:6D44:43F:1:11A0000:0:0:0:</channel>
Расписание автообновления и хранение epg.dat
В настройках EPGImport можно выставить время автозапуска. Лучшее время — 4:00-5:00 ночи, когда ресивер в режиме ожидания. Плагин умеет будить ресивер из deep standby для обновления EPG.
Данные кешируются в файл epg.dat. Путь по умолчанию зависит от прошивки: обычно /etc/enigma2/epg.dat или /hdd/epg.dat. Посмотреть текущий путь:
grep epgcache /etc/enigma2/settings
Перенос epg.dat в /media/hdd чтобы не терять при ребуте
На ресиверах без встроенного HDD epg.dat часто живёт в /tmp или во флеш-памяти, которая монтируется как tmpfs. После ребута — чисто, EPGImport запускается заново и снова тянет файл. Если интернет медленный или сервер недоступен — гид пустой до следующего цикла.
Решение: перенести кеш на HDD или USB. В /etc/enigma2/settings добавить или изменить строку:
config.misc.epgcache_filename=/media/hdd/epg.dat
После этого перезапустить Enigma2. Проверить что файл создался: ls -lh /media/hdd/epg.dat.
Альтернатива на OScam: rytec EPG и CrossEPG
Если хочется EPG без зависимости от внешнего интернет-источника — есть другой путь. Ряд спутниковых провайдеров транслируют программу передач прямо в потоке в форматах OpenTV, MHW2 или Freesat. OScam может их расшифровать, а CrossEPG — собрать.
rytec.channels.xml — стандарт привязки
Проект Rytec поддерживает стандартизированные channel id для крупных европейских каналов. Файл rytec.channels.xml — общий реестр привязок для сотен каналов. Если твой канал там есть — не нужно вручную выяснять SRef, всё уже прописано. EPGImport умеет использовать rytec channel id напрямую.
CrossEPG провайдеры (Sky, Rai, Polsat и т.д.)
CrossEPG — плагин, который умеет тянуть провайдерский EPG из потока без интернета. Поддерживаемые провайдеры включают Sky Italia, Sky Deutschland, Rai (MHW2), Polsat (OpenTV), Canal+ и ещё несколько десятков. Плюс умеет загружать XMLTV — то есть работает как замена EPGImport.
Установка аналогична: opkg install enigma2-plugin-extensions-crossepg.
OpenTV EPG vs MHW2 EPG vs Freesat
OpenTV — проприетарный формат, используется Polsat, Canal+, некоторыми Sky-пакетами. MHW2 — MediaHighway 2, используется Sky Italia и частично Sky Deutschland. Freesat — британский формат Freesat/BBC. Все три дают до 7 дней расписания без интернета, но только для каналов внутри своего пакета.
OScam расшифровывает ECM/EMM для доступа к каналам, и тот же поток содержит EPG-таблицы. CrossEPG их читает и складывает в epg.dat.
Когда XMLTV лучше, когда — провайдерский OpenTV
Провайдерский EPG хорош если ты смотришь каналы одного крупного пакета: 7 дней, не нужен интернет, работает из коробки на поддерживаемых провайдерах. XMLTV незаменим когда нужен local tv guide для региональных каналов, которых нет ни в одном спутниковом пакете, или когда каналы берутся из разных источников.
На практике многие делают так: CrossEPG для основного пакета + EPGImport с XMLTV для дополнительных каналов. Главное — не включать оба источника для одних и тех же каналов, иначе будут задвоенные записи.
Привязка XMLTV id к каналам ресивера
Самый трудоёмкий шаг — найти правильную ServiceReference для каждого канала. Без неё EPGImport не знает, к какому каналу привязать программу.
Где взять ServiceReference канала (lamedb или web-интерфейс :80)
Способ 1 — через OpenWebif. Открыть в браузере http://IP_ресивера/ (порт 80), перейти во вкладку Bouquets или Services, найти нужный канал и скопировать SRef из поля ServiceReference. Выглядит как 1:0:19:2BB0:7FB:2:11A0000:0:0:0:.
Способ 2 — через lamedb. База данных каналов лежит в /etc/enigma2/lamedb. Найти канал по имени:
grep -A2 -i "первый канал" /etc/enigma2/lamedb
Структура SRef: namespace:TSID:ONID:SID в hex, с префиксом типа сервиса. Цифра 1 в начале — DVB-S, 19 — тип сервиса (TV), дальше идут идентификаторы транспондера и сервиса.
Формат channels.xml: пример с реальным SRef
<channels>
<!-- Первый канал HD, Astra 1N 19.2E -->
<channel id="pervyi.russia.com">1:0:19:283D:41F:2:11A0000:0:0:0:</channel>
<!-- Россия 1 -->
<channel id="russia1.russia.com">1:0:19:2BB0:7FB:2:11A0000:0:0:0:</channel>
</channels>
channel id в channels.xml должен точно совпадать с channel id в XMLTV-файле. Регистр важен.
Скрипты автогенерации: rytec2epgimport, lamedb-парсеры
Если каналов сотни — ручная привязка нереальна. Есть несколько подходов:
rytec2epgimport— Python-скрипт, матчит имена каналов из lamedb с rhythm channel id по regex- AutoBouquetsMaker — плагин Enigma2, генерирует букеты и умеет экспортировать SRef
- Самописный парсер lamedb — несложно, формат текстовый, каналы идут блоками по 5 строк
Что делать если каналов сотни
Автоматика даёт ~60-70% совпадений по именам. Остальное — руками. Но начинать стоит именно с автоматики, потом чистить несовпадения. Записать channels.xml, запустить EPGImport в тестовом режиме, проверить лог на ошибки привязки — и доработать оставшееся.
И ещё важный момент: channels.xml могут перезаписываться при обновлении плагина EPGImport. Держи свою версию в /etc/epgimport/mylocal.channels.xml с нестандартным именем — она не затрётся.
Автообновление и cron на сервере OScam
Если сервер OScam уже работает — разумно поднять на нём и WebGrab++, чтобы не зависеть от публичных зеркал XMLTV. Один сбор → один файл → раздаётся всем ресиверам в локальной сети.
Запуск WebGrab+Plus по cron раз в сутки
Типичная запись в crontab (crontab -e от root или нужного пользователя):
0 4 * * * /opt/wg++/run.sh >> /var/log/wgpp.log 2>&1
Скрипт run.sh запускает WG++, после чего сжимает результат:
#!/bin/bash
cd /opt/wg++
mono WebGrab+Plus.exe /opt/wg++/config/
gzip -f /var/www/epg/guide.xml
cp /var/www/epg/guide.xml.gz /var/www/epg/guide_$(date +%Y%m%d).xml.gz
Для Linux-версии WG++ без mono используется нативный бинарник или .NET runtime.
Хостинг XMLTV на своём сервере (nginx + gzip)
Минимальный конфиг nginx для раздачи EPG:
server {
listen 80;
server_name _;
location /epg/ {
root /var/www;
autoindex off;
add_header Cache-Control "public, max-age=3600";
gzip_static on;
}
}
Файл /var/www/epg/guide.xml.gz будет отдаваться ресиверу напрямую. EPGImport умеет скачивать и распаковывать gz на лету.
Сжатие xml.gz и отдача ресиверу
Несжатый XMLTV на 200 каналов за 7 дней весит 50-150 МБ. Gzip сжимает до 5-15 МБ — в 10 раз. На медленном соединении или wi-fi это принципиально.
Но есть нюанс: на некоторых старых прошивках с busybox-окружением gunzip ограничен и не умеет распаковывать большие файлы. В этом случае лучше отдавать несжатый XML, добавив в nginx отдельный location без gzip_static.
Логи и контроль свежести (last-modified)
После каждого запуска cron нужно проверять что файл обновился. Добавить в run.sh:
if [ ! -f /var/www/epg/guide.xml.gz ]; then
echo "ERROR: guide.xml.gz not created" | mail -s "EPG FAIL" [email protected]
fi
echo "Updated: $(date)" >> /var/log/wgpp.log
На ресивере можно проверить дату файла через wget с флагом --spider:
wget --spider http://192.168.1.10/epg/guide.xml.gz 2>&1 | grep "Last-modified"
Диагностика: EPG пустой, неправильное время, не те передачи
EPGImport отработал без ошибок, но в программе пусто — это случается часто. Вот чеклист для разбора.
Проверка через telnet/ssh: cat /etc/epgimport/*.channels.xml
Первый шаг — убедиться что конфиги на месте:
ls -la /etc/epgimport/
cat /etc/epgimport/mylocal.channels.xml
cat /etc/epgimport/mylocal.sources.xml
Проверить что URL в sources.xml доступен с ресивера:
wget -O /tmp/test.xml.gz http://192.168.1.10/epg/guide.xml.gz
gunzip -t /tmp/test.xml.gz && echo "OK" || echo "CORRUPTED"
Если gunzip -t говорит CORRUPTED — файл битый или скачался не полностью.
Логи: /tmp/epgimport.log и tail enigma2 log
Лог EPGImport пишется в /tmp/epgimport.log. Смотреть через:
cat /tmp/epgimport.log | tail -50
Общий лог Enigma2 — /tmp/enigma2_debug.log. Там видны ошибки при загрузке плагинов и парсинге EPG:
tail -f /tmp/enigma2_debug.log | grep -i epg
Несовпадение TZ между сервером WG++ и ресивером
Передачи есть, но сдвинуты на час-два — почти всегда проблема часового пояса. Проверить TZ на ресивере:
date
cat /etc/timezone
Проверить что offset в XMLTV-файле соответствует реальному времени вещания канала. Если канал вещает по московскому времени (+0300), а в XML стоит UTC (+0000) — передачи будут на 3 часа раньше реального времени.
epg.dat повреждён — удалить и перегенерировать
Если после обновления прошивки или нештатного отключения EPG ведёт себя странно — скорее всего повреждён кеш:
rm /etc/enigma2/epg.dat
# или если перенесён на HDD:
rm /media/hdd/epg.dat
После удаления перезапустить Enigma2 и запустить EPGImport вручную из меню плагинов. Файл создастся заново.
Конфликт между MHW2 и XMLTV (двойные записи)
Если включены и CrossEPG с провайдерским EPG, и EPGImport с XMLTV — на одних каналах будут задвоенные или конфликтующие записи. Решение: в CrossEPG исключить каналы, для которых есть XMLTV-источник, или наоборот. Либо оставить только один источник.
Проверить текущую ситуацию: зайти на канал, нажать OK (вызов EPG) — если одна передача показывается дважды с разным временем, это конфликт источников.
Почему через CCcam передачи показываются на чужом языке?
EPG идёт в DVB-потоке от провайдера на языке его страны. CCcam расшифровывает картинку, но не меняет EIT — ресивер показывает то, что провайдер положил в поток. Если ты смотришь немецкий пакет, EPG будет на немецком. Решение — подключить внешний local tv guide через EPGImport: скачать XMLTV на нужном языке, прописать в sources.xml. Тогда программа будет на русском или любом другом языке, независимо от провайдерского потока.
Чем отличается XMLTV от OpenTV EPG?
OpenTV/MHW2 — это провайдерский EPG, который идёт прямо в спутниковом потоке. До 7 дней расписания, не нужен интернет, OScam/CrossEPG расшифровывают его из того же транспондера. Работает только для каналов конкретного пакета. XMLTV — внешний файл, который скачивается из интернета. Нужна сеть, но покрывает любые каналы включая региональные, IPTV, и те, у которых нет спутникового EPG вообще.
Куда положить epg.dat чтобы не терялся после перезагрузки?
В файле /etc/enigma2/settings выставить строку config.misc.epgcache_filename=/media/hdd/epg.dat. По умолчанию кеш хранится в /etc/enigma2/epg.dat или /hdd/epg.dat — на ресиверах без встроенного HDD это часто tmpfs, которая очищается при ребуте. Если HDD нет — подойдёт USB-флешка, примонтированная в /media/usb/.
Можно ли автоматически собрать channels.xml из lamedb?
Да. Скрипты типа lamedb2channels парсят /etc/enigma2/lamedb, матчат имена каналов с rytec.channels.xml по regex и генерируют файл привязки. Плагин AutoBouquetsMaker тоже умеет экспортировать SRef. Автоматика даёт ~60-70% совпадений — региональные и нестандартные каналы всё равно придётся прописывать вручную.
EPGImport показывает 'No data imported' — что делать?
Чеклист: 1) проверить интернет на ресивере — ping 8.8.8.8; 2) проверить URL источника — wget -O /tmp/t.xml.gz http://твой-url; 3) проверить валидность файла — gunzip -t /tmp/t.xml.gz; 4) убедиться что channel id в XMLTV точно совпадают с channel id в channels.xml (регистр, точки, дефисы); 5) запустить EPGImport из меню плагинов и смотреть /tmp/epgimport.log в реальном времени.
Сколько весит EPG на 7 дней для 200 каналов?
XMLTV в gzip — примерно 5-15 МБ, распакованный 50-150 МБ, итоговый epg.dat 20-40 МБ в зависимости от детализации описаний. На ресивере с 256 МБ RAM держать epg.dat в оперативной памяти тяжело — обязательно выносить на HDD или USB. Размер зависит от количества каналов и длины описаний передач: короткие XMLTV без synopsis весят в 3-4 раза меньше.
Можно ли использовать один XMLTV-источник на несколько ресиверов?
Да, и это правильная схема. Поднять nginx на сервере OScam, положить файл в /var/www/epg/guide.xml.gz, раздавать по http://IP_сервера/epg/guide.xml.gz. В sources.xml на каждом ресивере прописать этот URL. Один запуск WebGrab++ раз в сутки, один файл — сколько угодно клиентов. Публичные зеркала хуже: они могут лечь, сменить URL или поменять структуру channel id.