Локальная TV-программа через CCcam: настройка EPG (local tv guide)

Если вы уже настроили CCcam или OScam и каналы декодируются нормально — поздравляю, половина работы сделана. Но тут выясняется, что EPG либо пустой, либо показывает программу на польском, либо сдвинут на три часа. Это классическая история. Local tv guide — отдельная подсистема, никак не связанная с дескремблированием, и настраивать её нужно отдельно. Разберём всё по шагам: откуда брать XMLTV, как настроить маппинг, как автоматизировать обновление.

Что такое локальный EPG и почему он не работает через CCcam

CCcam и OScam занимаются ровно одним делом — передают ключи дескремблирования (ECM/EMM) между клиентом и сервером. Всё. Они не знают ничего про программу передач, не парсят метаданные, не касаются EIT-таблиц. Это не баг, это архитектура.

EPG живёт в другом месте. Телеканалы вещают программу передач прямо в DVB-потоке в виде таблиц EIT (Event Information Table). Ресивер их читает и отображает. Проблема в том, что многие операторы обрезают EIT до минимума — только Now/Next (текущая и следующая передача). Полной недельной сетки там нет.

Разница между DVB-EPG (Now/Next) и расширенным EPG (7+ дней)

DVB стандарт определяет несколько типов EIT-таблиц. Таблицы 0x4E и 0x4F — это Present/Following, то есть сейчас и следующая. Именно их гарантированно передают почти все операторы. Таблицы 0x50–0x5F и 0x60–0x6F — расширенный EPG на несколько дней вперёд. Многие спутниковые операторы либо не транслируют их вообще, либо заполняют только для своих premium-каналов.

Для локальных каналов ситуация ещё хуже. Региональные вещатели часто вообще не формируют EIT корректно. Так что если вы хотите нормальный local tv guide на 7–14 дней — внешний XMLTV источник обязателен.

Почему CCcam передаёт только дескремблирование, но не EPG

Протокол CCcam работает так: клиент посылает ECM (зашифрованный запрос ключа), сервер возвращает CW (Control Word) — 8 байт, которых достаточно для декодирования. Никакого EPG в этом протоколе нет и быть не может. То же самое с OScam — это CAM-эмулятор, а не мультимедийная система.

Встречал людей, которые думали, что «хороший» CCcam-сервер должен давать EPG. Нет. Это принципиально разные подсистемы.

Откуда ресивер берёт программу: поток DVB vs внешний XMLTV

Enigma2-ресивер (OpenATV, OpenPLi и другие дистрибутивы) умеет получать EPG двумя способами. Первый — читать EIT из DVB-потока в реальном времени. Второй — импортировать внешний файл в формате XMLTV через специальные плагины. TVHeadend работает аналогично: есть встроенный EIT grabber и поддержка внешнего XMLTV через EPG Grabber Modules.

При наличии обоих источников возникает конфликт приоритетов. Это отдельная история — разберём в разделе про типичные проблемы.

Источники XMLTV для локальной TV-программы

XMLTV — это XML-формат для хранения и передачи TV-программ. Де-факто стандарт для всего, что не DVB. Поддерживается Enigma2, TVHeadend, Kodi, Plex и десятками других приложений.

Что такое XMLTV формат и его структура

Базовая структура файла выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<tv generator-info-name="tv_grab_ru" source-info-url="...">
  <channel id="channel.one.ru">
    <display-name lang="ru">Первый канал</display-name>
    <icon src="https://example.com/icon.png" />
  </channel>
  <programme start="20260508180000 +0300" stop="20260508190000 +0300" channel="channel.one.ru">
    <title lang="ru">Вечерние новости</title>
    <desc lang="ru">Выпуск новостей...</desc>
    <category lang="ru">Новости</category>
  </programme>
</tv>

Ключевые атрибуты: start и stop — время в формате YYYYMMDDHHMMSS с timezone offset. Атрибут channel в тэге <programme> должен точно совпадать с id в <channel>. Несовпадение channel id — самая частая причина пустого EPG.

Критерии выбора источника: частота обновления, глубина, язык

На что смотреть при выборе XMLTV источника:

  • Глубина — минимум 7 дней, идеально 14. Меньше 3 дней — практически бесполезно.
  • Частота обновления — раз в сутки достаточно для большинства каналов. Для спортивных нужно чаще, там расписание меняется в последний момент.
  • Правильный timezone — для российских каналов offset должен соответствовать реальному: +0300 для Москвы, +0500 для Екатеринбурга и т.д. Фиксированный UTC без offset — источник проблем при переходах на летнее/зимнее время.
  • Язык метаданных — title и desc должны быть на русском, иначе EPG будет нечитаемым.
  • Покрытие каналов — проверяйте, есть ли ваши локальные и региональные каналы, а не только федеральные.

Бесплатные публичные grabber-скрипты и self-hosted решения

Проект XMLTV (xmltv.org) предоставляет набор grabber-скриптов: tv_grab_ru, tv_grab_eu_epgdata, tv_grab_fi и другие. Устанавливаются через пакетный менеджер:

# Debian/Ubuntu
apt-get install xmltv-util

# Проверить доступные grabbers
tv_grab_ru --capabilities

# Настройка
tv_grab_ru --configure --config-file /etc/xmltv/tv_grab_ru.conf

# Тестовый запуск
tv_grab_ru --config-file /etc/xmltv/tv_grab_ru.conf --days 7 --output /tmp/epg_ru.xml

Grabber-скрипты парсят сайты вещателей или используют публичные API. Результат — стандартный XMLTV файл, который можно отдавать ресиверам по HTTP.

Размещение XMLTV на собственном веб-сервере для локальной сети

Если в сети несколько ресиверов — имеет смысл один раз скачать EPG на сервер и раздавать его по HTTP. Конфиг nginx минимальный:

server {
    listen 8080;
    root /var/www/epg;
    location / {
        add_header Content-Type application/xml;
        gzip_static on;
    }
}

Кладёте файл в /var/www/epg/epg.xml (или epg.xml.gz), и все ресиверы в сети обращаются к http://192.168.1.100:8080/epg.xml. Обновление — через cron на этом же сервере.

Настройка EPG на Enigma2 ресиверах (OpenATV, OpenPLi)

Enigma2 — операционная система большинства спутниковых ресиверов Vu+, Dreambox, GigaBlue и других. Для импорта внешнего EPG используется плагин EPGImport.

Установка плагина EPGImport через ipk/opkg

# Обновить список пакетов
opkg update

# Установить плагин
opkg install enigma2-plugin-extensions-epgimport

# Перезапустить Enigma2
init 4 && sleep 3 && init 3

После установки плагин появится в Plugins → EPGImport. Но сам по себе он ничего не сделает — нужно добавить источник.

Создание sources файла /etc/epgimport/myepg.sources.xml

Структура файла источников:

<?xml version="1.0" encoding="UTF-8"?>
<sources>
  <sourcecat sourcecatname="Мои источники EPG">
    <source type="gen_xmltv" nocheck="1">
      <description>Российское ТВ 7 дней</description>
      <url>http://192.168.1.100:8080/epg.xml.gz</url>
    </source>
    <source type="gen_xmltv" nocheck="1">
      <description>Украинское ТВ</description>
      <url>http://192.168.1.100:8080/epg_ua.xml</url>
    </source>
  </sourcecat>
</sources>

Файл кладётся в /etc/epgimport/myepg.sources.xml. EPGImport автоматически подхватывает все *.sources.xml файлы из этой директории.

Маппинг каналов: channel_id_format и rytec.channels.xml

Это самое болезненное место. EPGImport должен понять, какой channel id в XMLTV соответствует какому каналу в Enigma2. Для этого используется файл маппинга.

Посмотреть service reference канала в Enigma2 можно через Info. Выглядит примерно так: 1:0:1:283D:7DF:13E:820000:0:0:0. Файл маппинга:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="channels2html.xsl"?>
<channels>
  <channel id="channel.one.ru">1:0:1:283D:7DF:13E:820000:0:0:0</channel>
  <channel id="rossiya.1.ru">1:0:1:3D9:7DF:13E:820000:0:0:0</channel>
</channels>

Файл кладётся в /etc/epgimport/. Сообщество Rytec публикует готовые маппинги для распространённых спутников и операторов — это сильно экономит время. Но для локальных и региональных каналов часто придётся добавлять записи вручную.

Настройка cron для автоматического импорта

Создайте скрипт /usr/script/epgimport.sh:

#!/bin/sh
/usr/bin/python /usr/lib/enigma2/python/Plugins/Extensions/EPGImport/EPGImport.py

Добавьте в crontab (crontab -e):

15 4 * * * /usr/script/epgimport.sh > /tmp/epgimport.log 2>&1

Запуск в 4:15 ночи — разумный выбор. EPG обновился, к утреннему прайм-тайму всё готово.

Проверка через journalctl и /tmp/epgimport.log

# Проверить лог импорта
cat /tmp/epgimport.log

# Системный журнал Enigma2
journalctl -u enigma2 -n 100 | grep -i epg

# Альтернатива — посмотреть через logread (busybox)
logread | grep EPGImport

В логе будут строки типа Loaded 4521 events for channel.one.ru. Если количество 0 — проблема с маппингом.

Настройка EPG на TVHeadend и интеграция с OScam

TVHeadend — популярное решение для тех, кто строит домашний медиасервер на Raspberry Pi или x86 Linux. Как правило, он работает в паре с OScam, который выступает CAM-сервером.

Подключение XMLTV grabber через Configuration → Channel/EPG → EPG Grabber Modules

В веб-интерфейсе TVHeadend: Configuration → Channel/EPG → EPG Grabber Modules. Здесь два варианта: Internal (встроенные парсеры EIT) и External (внешние скрипты).

Для XMLTV выбираем тип XMLTV и указываем либо путь к файлу, либо URL. Конфигурационные файлы TVHeadend хранятся в /home/hts/.hts/tvheadend/. Файл конфигурации EPG grabber:

cat /home/hts/.hts/tvheadend/epggrab/config
{
    "cron": "15 4 * * *",
    "eit": {
        "enabled": true,
        "priority": 5
    },
    "xmltv": {
        "enabled": true,
        "priority": 10
    }
}

External: XMLTV — указание пути к скрипту или socket

Если используете grabber-скрипт, укажите полный путь:

/usr/bin/tv_grab_ru --config-file /etc/xmltv/tv_grab_ru.conf --days 7

TVHeadend выполнит этот скрипт по расписанию и прочитает stdout как XMLTV. Альтернатива — указать path к готовому XML файлу, который обновляет отдельный cron.

Internal grabbers (xmltv-util) и расписание

Cron expression в TVHeadend использует стандартный синтаксис. Примеры:

  • 15 4 * * * — каждый день в 4:15
  • */30 * * * * — каждые 30 минут (для спортивных каналов с частыми изменениями)
  • 0 2,14 * * * — дважды в день, в 2:00 и 14:00

Маппинг XMLTV channel-id на каналы TVH

После первого запуска grabber TVHeadend создаёт список EPG-каналов. Перейдите в Electronic Program Guide → EPG Channels и свяжите каждый EPG-канал с физическим каналом через Map to channel. Можно сделать авто-маппинг через Channels → Map services, но для региональных каналов с нестандартными именами придётся вручную.

Если names не совпадают — используйте regex маппинг. В поле Channel Name можно задать регулярное выражение: например, Первый.* сопоставится с «Первый канал HD» и «Первый канал».

Совместная работа TVHeadend и OScam через newcamd порт

OScam настраивается как CAM-сервер через протокол newcamd. По умолчанию порт 15050. В файле /etc/oscam/oscam.server:

[reader]
label                 = newcamd_local
protocol              = newcamd
device                = 127.0.0.1,15050
key                   = 0102030405060708091011121314
user                  = tvheadend
password              = secret123
caid                  = 1810,0622
ident                 = 1810:000000

В TVHeadend: Configuration → CAs → Add, выбрать тип Newcamd, указать 127.0.0.1:15050, логин и пароль. EPG при этом работает совершенно независимо от дескремблирования — OScam не имеет к нему никакого отношения. Это важно понимать: если EPG не работает — проблема не в OScam.

Автоматическое обновление и кэширование EPG

Ручное обновление EPG — это не автоматизация. Один раз настроили cron, забыли.

Cron-задачи для скачивания XMLTV

Скрипт обновления /usr/script/epg_update.sh:

#!/bin/sh
EPG_URL="http://192.168.1.100:8080/epg.xml.gz"
EPG_DIR="/tmp"
LOG="/tmp/epg_update.log"

echo "$(date): Начало обновления EPG" >> $LOG
wget -q -O ${EPG_DIR}/epg.xml.gz ${EPG_URL} 2>> $LOG
if [ $? -ne 0 ]; then
    echo "$(date): Ошибка скачивания EPG" >> $LOG
    exit 1
fi

gunzip -f ${EPG_DIR}/epg.xml.gz 2>> $LOG
echo "$(date): EPG скачан и распакован" >> $LOG

# Для Enigma2:
/usr/bin/python /usr/lib/enigma2/python/Plugins/Extensions/EPGImport/EPGImport.py >> $LOG 2>&1
echo "$(date): Импорт завершён" >> $LOG

Crontab:

15 4 * * * /usr/script/epg_update.sh

Хранение кэша: /etc/enigma2/epg.dat и его лимит размера

Файл /etc/enigma2/epg.dat — бинарный кэш EPG в Enigma2. На практике он вырастает до 50–200 МБ в зависимости от количества каналов и глубины программы. На старых ресиверах с 256 МБ flash-памяти это проблема.

Решение — симлинк на USB-накопитель:

# Остановить Enigma2
init 4
sleep 2

# Удалить старый epg.dat
rm /etc/enigma2/epg.dat

# Создать симлинк
ln -s /media/usb/epg.dat /etc/enigma2/epg.dat

# Запустить Enigma2
init 3

USB должен монтироваться автоматически при загрузке. Проверьте /etc/fstab или настройки automount вашего дистрибутива.

Сжатие .xml.gz vs raw XML

Сжатый XMLTV файл в 5–10 раз меньше оригинала. Для ресиверов на медленном Wi-Fi или при загрузке через мобильный интернет — существенная экономия. Enigma2 и TVHeadend оба поддерживают .xml.gz напрямую. Рекомендую всегда раздавать сжатый вариант.

Сжать вручную: gzip -9 epg.xml. Nginx с модулем gzip_static отдаёт .gz автоматически, если файл существует.

Время выполнения импорта: после полуночи, до прайм-тайма

Импорт большого XMLTV файла (100+ каналов, 14 дней) может занимать 3–10 минут на слабом железе. В это время EPG может быть временно недоступен. Поэтому запускать импорт лучше в 3–5 утра по местному времени, когда ресивером никто не пользуется. К завтраку local tv guide уже обновлён и работает корректно.

Типичные проблемы и их решение

Большинство проблем с EPG сводятся к трём вещам: неправильный маппинг channel id, неправильный timezone, повреждённый epg.dat. Диагностика простая — логи говорят всё.

EPG пустой после импорта — проблема маппинга channel id

Первый шаг диагностики:

cat /tmp/epgimport.log | grep -i "0 events"

Если видите «Loaded 0 events» для каналов — channel id в XMLTV не совпадает с маппинг-файлом. Проверьте:

# Какие channel id есть в XMLTV
grep '<channel id' /tmp/epg.xml | head -20

# Что в маппинг-файле
grep 'channel id' /etc/epgimport/myepg.channels.xml | head -20

Id должны совпадать символ в символ. Регистр имеет значение: «Channel.One.RU» и «channel.one.ru» — разные id.

Сдвиг времени программы на 1-3 часа — неправильный timezone в XMLTV

Проверьте несколько строк из файла:

grep '<programme' /tmp/epg.xml | head -5

Атрибут start должен содержать корректный offset: 20260508180000 +0300 для Москвы. Если там +0000 или +0100 — EPG будет врать. Это частая проблема с grabber-скриптами под европейские источники, которые дают CET вместо MSK.

Отдельная история — переход на летнее/зимнее время. Если XMLTV источник использует фиксированный offset (+0100), а регион перешёл на +0200 — получите сдвиг на час осенью и весной. Правильные источники используют именованные timezone (Europe/Moscow) или динамически корректируют offset.

EPG обновляется, но не отображается — повреждённый epg.dat

# Остановить Enigma2
init 4
sleep 2

# Удалить повреждённый кэш
rm /etc/enigma2/epg.dat

# Запустить
init 3

# Подождать загрузки и принудительно запустить импорт через плагин

После удаления epg.dat Enigma2 создаст его заново. Если проблема была в повреждённом файле — после следующего импорта всё заработает.

Часть каналов без EPG — отсутствие в источнике XMLTV

Региональные и локальные каналы часто отсутствуют в крупных XMLTV базах. Варианты:

  • Найти специализированный grabber для вашего региона
  • Написать собственный парсер (Python + requests + BeautifulSoup, сайты большинства вещателей публикуют программу)
  • Включить гибридный режим: для большинства каналов — внешний XMLTV, для региональных — DVB Now/Next

Для каналов с региональными вставками (например, местные новости вместо федерального блока) XMLTV в принципе не поможет — он отдаёт общефедеральную сетку. Это ограничение формата, а не ошибка настройки.

Конфликт DVB-EPG и импортированного — приоритет источников

В Enigma2 есть настройка Load EPG only on demand (Setup → System → EPG). Если включена — EPG загружается по запросу, а не непрерывно из DVB-потока. Это снижает нагрузку, но может замедлить появление EPG для каналов без внешнего XMLTV.

Для приоритизации внешнего XMLTV над DVB EIT в Enigma2 — используйте плагин CrossEPG, который позволяет гибко настраивать приоритеты по каналам. В TVHeadend приоритет задаётся числом в конфиге EPG grabber (выше число = выше приоритет).

Если оба источника активны и дают разные данные — TVH и Enigma2 используют последний записанный. Чтобы внешний XMLTV выигрывал, убедитесь что импорт запускается после, а не до сбора DVB EIT.

Правильно настроенный local tv guide через XMLTV всегда точнее DVB EIT для локальных каналов — просто потому что вещатели часто вообще не обновляют EIT-таблицы своевременно.

Часто задаваемые вопросы

Можно ли получать EPG через CCcam протокол?

Нет. CCcam передаёт только данные для дескремблирования — ECM/EMM ключи (Control Words). В протоколе CCcam нет ни одного поля для EPG. Программа передач — это отдельная подсистема: либо EIT-таблицы из DVB-потока, либо внешний XMLTV источник. Если EPG не работает — это не проблема вашего CCcam сервера.

Какой формат XMLTV поддерживает Enigma2 и TVHeadend?

Стандартный XMLTV DTD: корневой тэг <tv>, внутри <channel id="..."> с <display-name>, и <programme start="YYYYMMDDHHMMSS +ZZZZ" stop="..." channel="..."> с тэгами <title>, <desc>, <category>. Поддерживается как plain XML, так и сжатый .xml.gz — оба варианта корректно читаются без дополнительных настроек.

Где хранится база EPG в Enigma2 и можно ли её перенести?

Бинарный кэш EPG находится в /etc/enigma2/epg.dat. На ресиверах с малым объёмом flash (256 МБ) он может не помещаться. Решение — перенести на USB через симлинк: остановить Enigma2 командой init 4, удалить оригинальный файл, создать симлинк ln -s /media/usb/epg.dat /etc/enigma2/epg.dat, запустить обратно командой init 3. USB должен монтироваться автоматически при загрузке.

Почему EPG приходит со сдвигом по времени на местные каналы?

Причина — неправильный timezone offset в XMLTV файле. Атрибут start в тэге <programme> должен содержать корректный offset: +0300 для Москвы, +0100 для CET и так далее. Проверьте grep'ом первые строки вашего epg.xml. Если там +0000 — найдите grabber с поддержкой вашего региона или конвертируйте time offset вручную через скрипт.

Сколько дней программы можно загрузить через XMLTV?

Зависит от источника. Бесплатные публичные grabbers (tv_grab_ru и аналоги) обычно дают 3–7 дней. Self-hosted парсеры, работающие напрямую с сайтами вещателей, могут давать до 14 дней. Больше 14 дней редко имеет смысл — телеканалы сами не планируют сетку дальше чем на две недели, данные всё равно будут неточными.

Как часто обновлять EPG?

Для большинства случаев достаточно одного раза в сутки — обычно в 3–5 утра по локальному времени. К утру программа обновлена, ресивер никто не трогает. Исключение — спортивные каналы: там расписание меняется часто, иногда за несколько часов до эфира. Для них имеет смысл настроить обновление каждые 6–12 часов. Но чаще чем раз в час обновлять бессмысленно — источники сами обновляются не чаще.

Practical checklist for smooth viewing

Even the best CCCam or OSCam line needs two or three simple preparations. Update your receiver firmware, reset the ECM cache once a week and keep 15–20% free space on the USB stick or internal flash so that the reader can store keys without delays.

When tuning a dish, aim for MER/BER reserve: a two‑degree offset or a loose F‑connector often causes the “freezing” that users blame on cardsharing. Keep a short patch cord to test alternative routers, and save two profiles in OSCam — one for TCP, one for UDP — so you can switch instantly if your ISP starts filtering a protocol.

Utgard.tv monitors each hub 24/7, but you can speed up diagnostics by keeping a short log of your receiver actions. Note the time when you changed the channel, which CAID was active and whether you used Wi‑Fi or Ethernet. This tiny “journal” helps engineers reproduce your environment in the lab and return with a solution in minutes instead of hours.

  • Keep two line slots enabled: if the first server hits a maintenance window, the second one instantly takes over without re-entering credentials.
  • Run a monthly speed and latency test. Stable 1–2 Mbps with ping <80 ms is enough for SD/HD, but if jitter exceeds 20 ms, switch the router to wired mode.
  • Save the Utgard.tv status page and Telegram bot @utgard_tv_bot to bookmarks — they publish maintenance notices before SEMrush or uptime monitors raise alerts.