streaming multicast IPTV to HLS (nginx+RTMP)

Получаем контент 239.192.1.1, 239.192.1.2 и 239.192.1.3. Будем раздавать его через WEB по протоколу HLS, что позволяет смотреть видео не только на компьютере с flash, но и на устройствах под управлением iOS(iPhone/iPad), а также на Android.

Для этого будем использовать nginx c поддержкой RTMP-модуля, модуль распространяется по лицензии BSD. Он собирается и работает под Linux и FreeBSD.

Собираем nginx с поддержкой RTMP-модуля:
cd NGINX source directory & run this:

./configure --add-module=/path/to/nginx-rtmp-module
make
make install

RTMP поддерживает ограниченный набор кодеков, а для просмотра HLS на iPhone нужно кодировать в H264 и AAC.
Для multicast-потока потребуется перекодировка, для этого будем использовать FFMPEG.


nginx-rtmp.conf:
user www;
worker_processes 1;

worker_rlimit_nofile 65535;

worker_priority -5;

error_log  /var/log/http/rtmp-error.log error;


events {
    worker_connections  1024;
    use kqueue; # freebsd specific
}

http {
    include       /usr/local/etc/nginx/mime.types;
    default_type  application/octet-stream;


    sendfile       on;    tcp_nopush     on;
    tcp_nodelay    on;
    reset_timedout_connection on;

    server {
        listen xx.219.128.139:80 default_server accept_filter=httpready rcvbuf=4096 sndbuf=262144 backlog=8192;

        server_name  "";

        access_log  /var/log/http/access-rtmp.log main buffer=16k;

        location / {
            root    /var/www;
            index   index.html;
            expires 30d;
        }

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            index index.m3u8;
            add_header Cache-Control no-cache;
            alias /var/tmp/hls;
        }
    }
}

rtmp_auto_push on;

rtmp {
   server {
        listen 1935;
        chunk_size 4096;
        ping 30s;
        notify_method get;

        application iptv_backend {
            live on;
            allow publish 127.0.0.1;
            deny publish all;
            exec_static /usr/local/bin/ffmpeg -loglevel error -re -threads 0 -i udp://239.192.1.1:1234 -tune zerolatency -preset ultrafast -profile:v main -level 4.0 -c:v libx264 -vf yadif=0:-1:0 -c:a libfaac -ar 44100 -ac 2 -f flv rtmp:
//localhost/iptv/ch01 2>>/var/log/http/ffmpeg-ch01.log;
            exec_static /usr/local/bin/ffmpeg -loglevel error -re -threads 0 -i udp://239.192.1.2:1234 -tune zerolatency -preset ultrafast -profile:v main -level 4.0 -c:v libx264 -vf yadif=0:-1:0 -c:a libfaac -ar 44100 -ac 2 -f flv rtmp:
//localhost/iptv/ch02 2>>/var/log/http/ffmpeg-ch02.log;
            exec_static /usr/local/bin/ffmpeg -loglevel error -re -threads 0 -i udp://239.192.1.3:1234 -tune zerolatency -preset ultrafast -profile:v main -level 4.0 -c:v libx264 -vf yadif=0:-1:0 -c:a libfaac -ar 44100 -ac 2 -f flv rtmp:
//localhost/iptv/ch03 2>>/var/log/http/ffmpeg-ch03.log;
            respawn on;
            exec_kill_signal 9;
            respawn_timeout 10s;
        }

        application iptv {
            live on;
            allow publish 127.0.0.1;
            deny publish all;
            hls on;
            hls_type live;
            hls_path /var/tmp/hls;
            hls_fragment 5s;
            hls_playlist_length 60s;
        }
    }
}

Чтобы не нагружать HDD, /var/tmp/hls разместим в RAM (TMPFS):

/etc/fstab
# Device                Mountpoint      FStype  Options                         Dump    Pass#
tmpfs                   /var/tmp/hls    tmpfs   rw,noexec,size=1048576000       0       0

В результате даже при нереально высокой нагрузке на CPU, контент отдаётся вполне приемлемо.

last pid: 33377;  load averages: 24.18, 19.76, 18.00                                                                                                                                                                 up 0+00:50:25  22:07:55
50 processes:  4 running, 46 sleeping
CPU: 94.6% user,  0.0% nice,  4.6% system,  0.8% interrupt,  0.0% idle
Mem: 1015M Active, 294M Inact, 457M Wired, 417M Buf, 2169M Free



В /var/www создаём тестовую страницу для проверки вещания index.html следующего содержания:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>IPTV</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="http://p.jwpcdn.com/6/10/jwplayer.js"></script>

<script type="text/javascript">

$(document).ready(function() {

if (navigator.userAgent.match(/android/i) != null) {
 jwplayer("videoPlayer").setup({
    playlist: [
    {
     title: "1tv",
     sources: [
        {
          file: "http://xx.219.128.139/hls/ch01.m3u8"
        }
     ]},{
     title: "1",
     sources: [
        {
          file: "http://xx.219.128.139/hls/ch02.m3u8"
        }
     ]},{
     title: "2",
     sources: [
        {
          file: "http://xx.219.128.139/hls/ch03.m3u8"
        }
     ]},{
     title: "3",
     sources: [
        {
          file: "http://xx.219.128.139/hls/ch04.m3u8"
        }
     ]}

    ],
  androidhls: true,
  type: "mp4",
  primary: "html5",
  autostart: false,
  stretching: "fill",
  width:  920,
  height: 576,
  listbar: { position: "right", size: 200 }
 });

} else {
jwplayer("videoPlayer").setup({
playlist: [
{
title: "1",
sources: [
{
file: "rtmp://xx.219.128.139/iptv/ch01"
},
{
file: "http://xx.219.128.139/hls/ch01.m3u8"
}
]},{
title: "2",
sources: [
{
file: "rtmp://xx.219.128.139/iptv/ch02"
},
{
file: "http://xx.219.128.139/hls/ch02.m3u8"
}
]},{
title: "3",
sources: [
{
file: "rtmp://xx.219.128.139/iptv/ch03"
},
{
file: "http://xx.219.128.139/hls/ch03.m3u8"
}
]}
    ],
    primary: "flash",
    autostart: false,
    stretching: "fill",
    width:  920,
    height: 576,
    listbar: { position: "right", size: 200 }
  });
}


});
</script>

</head>
<body>

<h3>IPTV</h3>
<center><div id="videoPlayer">Player loading...</div><br/></center>

</body>
</html>




Сервер включен в коммутатор Juniper EX, так как мы принимаем multicast-трафик, на коммутаторе нужно сконфигурировать igmp-snooping:


protocols {
    igmp-snooping {
        vlan all;
        vlan IPTV-WEB {
            data-forwarding {
                source {
                    groups 239.192.1.0/24;
                }
            }
        }
        vlan SERVER-WEB {
            data-forwarding {
                receiver {
                    source-vlans IPTV-WEB;
                    install;
                }
            }
        }
    }
}
 
IPTV-WEB - источник многоадресного трафика
SERVER-WEB - сервер.






   

Комментарии

Популярные сообщения из этого блога

using pg_partman to help partitioning postgresql for zabbix