Изначально для вещания IPTV использовалас связка sasc-ng (дешифрование закрытых каналов) и getstream (ремультиплексирование и вещание в есть) на серверах и несколько спутниковых ресиверов. Примерно два года назад начал доработку getstream, основная цель — заменить дорогостоящие ресиверы и убрать нестабильный sasc-ng. Со временем этот проект стал известен как getstream_a84 (a84 — было названием моего аккаунта на bitbucket.org, от туда и приклеилось).
Приложение получилось вполне работоспособным, в отличии от sasc-ng не требовалось установки dvbloopback, стабильно работал с системами условного доступа DRE-Crypt и Irdeto.
Примерно год назад появилась необходимость разработать замену для getstream. Основная причина — архитектура getstream не позволяла с лёгкостью добавлять новый функционал. Даже доработка существующего кода доставляла много проблем. Новый проект получил название Astra.
Проект получился очень удачный, модульная архитектура в сочетании с Lua позволяет создавать гибкие конфигурации и выполнять различные действия во время работы приложения.
Ядро Астры можно использовать как фрэймворк для разработки различных приложений. В ядро входит:
- обработка событий. На данный момент поддерживает epoll, kqueue и poll
- работа с сетевыми сокетам
- таймер (работает за счёт прерывания обработчика событий)
- инициализация модулей
- логирование
- Lua
Функционал конечного приложения определяется набором модулей и протоколами (набор функций описывающих взаимодействие между модулями).
В дальнейшем планирую отделение ядра Астры в отдельный проект, на данный момент развитие идёт только в рамках IPTV. Astra по функционалу может полностью заменить getstream_a84 и даже больше.
Основные преимущества Астры перед гетстримом:
- модульность
- меньше нагрузка на CPU
- стабильно работает
- большие возможности в контроле, настройке, управлении
- удобно разрабатывать новый функционал
Небольшая демонстрация возможностей Астры — вещание в сеть, с DVB, нескольких каналов:
#!/usr/bin/env astra
require "base"
cam_1 = newcamd({
name = "Reader:0.01",
host = "card-server.local", port = "40001",
username = "user", password = "****",
key = "0102030405060708091011121314",
})
dvb_1 = {
adapter = 1, type = "S2",
tp = "12149:h:27500",
lnb = "10750:10750:10750"
}
s1 = make_stream({ name = "Stream 1", dvb = dvb_1 }, {
{ name = "Channel 1", pnr = 23150, cam = cam_1, addr = "239.255.1.1", analyze = true },
{ name = "Channel 2", pnr = 23010, cam = cam_1, addr = "239.255.1.2", analyze = true },
})
Вся логика описывается в Lua-скриптах. В примере используется функция make_stream (подключается из require «base»), она загружает модули с нужными параметрами, устанавливает между ними связь. Экземпляры загруженных модулей сохраняются в таблицу для последующего использования (плюс, если экземпляру модуля не присвоить переменную сборщик мусора его выгрузит).
Например можно добавить вывод статистики через веб-интерфейс (http://сервер:8000/):
function stat_cb(self, data)
if type(data) == 'table' then
local dvb_stat = s1.dvb:status()
local html = "<html><head><title>Stat</title></head><body><pre>"
html = html .. "<b>DVB</b> adapter:" .. s1.config.dvb.adapter ..
" lock:" .. tostring(dvb_stat.lock) ..
" signal:" .. tostring(dvb_stat.signal) .. "%" ..
" snr:" .. tostring(dvb_stat.snr) .. "%n"
for _,ch in pairs(s1.channels) do
local ch_stat = ch.analyze:status()
html = html .. " <b>" .. ch.config.name .. "</b>" ..
" ready:" .. tostring(ch_stat.ready) ..
" bitrate:" .. tostring(ch_stat.bitrate) ..
" scrambled:" .. tostring(ch_stat.scrambled) ..
"n"
end
html = html .. "</pre></body></html>"
self:send({
code = 200,
message = "OK",
headers = {
"Server: Astra " .. astra.version(),
"Content-Type: text/html; charset=utf-8",
"Content-Length: " .. #html,
"Connection: close"
},
content = html
})
end
end
stat = http_server({ port = 8000, callback = stat_cb })
Проект по большей части Open-source.
Исходный код и документация: https://bitbucket.org/cesbo/astra
Форум: http://cesbo.com/forum
Автор: and_cesbo