Около года назад я описывал самопальную систему стриминга live video с птичьей кормушки из говна и палок вебкамеры, ffmpeg и nginx.
Прошёл год, наука шагнула далеко вперёд, надо описать, что с тех пор изменилось-усовершенствовалось.
Во-первых, от использования ffserver получилось отказаться почти сразу же после написания прошлогодней статьи. «Получилось» — потому что связка ffmpeg+ffserver в настройке и работе, мягко говоря, хрупковата. Поэтому сразу после реализации механизмы были перепилены в сторону упрощения. В качестве сервера дистрибуции потока вместо ffserver стал использоваться nginx. Для этого nginx пришлось пропатчить волшебным патчем, добавляющим поддержку RTMP, HLS и MPEG-DASH. После этого nginx обретает умение принимать видеопоток по RTMP и раскидывать его в файлы, которые потом сам же nginx отдаёт браузерам, понимающим MPEG-DASH либо HLS. Точнее, в случае десктоп-устройств в качестве веб-клиента выступил flash-плеер Bitdash, который в то время (в версии 3.2.0) был доступен бесплатно с некоторыми ограничениями по трафику, которые меня вполне устроили.
Настройки Nginx в части обслуживания потока у меня имеют следующий вид:
ffmpeg -s 640x360 -f video4linux2 -i /dev/video1 -c:v libx264 \
-crf 27 -preset slow -bf 8 -g 100 -pix_fmt yuv420p10le -qmin 10 -qmax 43 -aq 1 \
-b:v 450k -bufsize 1200 -r 20 -an -f flv \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSans.ttf:text='%{localtime} $(cat /tmp/temperature)':fontcolor=white@0.9:fontsize=10:x=510:y=348" "rtmp://birdfeeder.online/live/test.flv live=1"
Результирующий поток имеет битрейт в пределах от 200 до 350 килобит в секунду. Файл /tmp/temperature формируется независимо по крону и, увы, для отображения изменений в нём весь ffmpeg приходится периодически перезапускать.
Во-вторых, перед началом нового сезона было решено вновь проверить возможность отказа от использования Adobe Flash. Это, как кажется, вполне удалось. Теперь для показа используется VideoJS-contrib-HLS, а соответствующий код в HTML-файле выглядит так:
<HEAD>
<link href="https://vjs.zencdn.net/5.8.8/video-js.css" rel="stylesheet">
<script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
</HEAD>
<BODY>
<video id=example-video width=640 height=360 class="video-js vjs-default-skin" poster="/images/poster.jpg" controls>
<source
src="https://birdfeeder.online/hls/test.m3u8"
type="application/x-mpegURL">
</video>
</center>
<script src="https://vjs.zencdn.net/5.8.8/video.js"></script>
<script src="videojs-contrib-hls.min.js"></script>
<script>
var player = videojs('example-video');
player.play();
</script>
</BODY>
Прошёл год, наука шагнула далеко вперёд, надо описать, что с тех пор изменилось-усовершенствовалось.
Во-первых, от использования ffserver получилось отказаться почти сразу же после написания прошлогодней статьи. «Получилось» — потому что связка ffmpeg+ffserver в настройке и работе, мягко говоря, хрупковата. Поэтому сразу после реализации механизмы были перепилены в сторону упрощения. В качестве сервера дистрибуции потока вместо ffserver стал использоваться nginx. Для этого nginx пришлось пропатчить волшебным патчем, добавляющим поддержку RTMP, HLS и MPEG-DASH. После этого nginx обретает умение принимать видеопоток по RTMP и раскидывать его в файлы, которые потом сам же nginx отдаёт браузерам, понимающим MPEG-DASH либо HLS. Точнее, в случае десктоп-устройств в качестве веб-клиента выступил flash-плеер Bitdash, который в то время (в версии 3.2.0) был доступен бесплатно с некоторыми ограничениями по трафику, которые меня вполне устроили.
Настройки Nginx в части обслуживания потока у меня имеют следующий вид:
nginx.conf:Сам поток по-прежнему формируется с использованием ffmpeg, берущего с вебкамеры raw YUV и преобразующего его в, прошу простить меня за это слово, FLV-контейнер с 10-bit H.264 потоком внутри и отдающего его nginx'у с помощью примерно следующей командной строки:
rtmp {
server {
listen [::]:1935;
application live {
allow publish <my-source-IP>;
allow publish <my-backup-source-IP>;
deny publish all;
allow play all;
live on;
publish_notify on;
play_restart on;
hls on;
hls_path /tmp/hls;
hls_fragment 10s;
dash on;
dash_path /tmp/dash;
}
}
}
sites-enabled/myserver.conf:
location /hls {
root /tmp;
types {
application/vnd.apple.mpegurl m3u8;
}
add_header Cache-Control no-cache;
}
location /dash {
root /tmp;
types {
application/vnd.apple.mpegurl m3u8;
application/dash+xml mpd;
}
add_header Cache-Control no-cache;
}
ffmpeg -s 640x360 -f video4linux2 -i /dev/video1 -c:v libx264 \
-crf 27 -preset slow -bf 8 -g 100 -pix_fmt yuv420p10le -qmin 10 -qmax 43 -aq 1 \
-b:v 450k -bufsize 1200 -r 20 -an -f flv \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSans.ttf:text='%{localtime} $(cat /tmp/temperature)':fontcolor=white@0.9:fontsize=10:x=510:y=348" "rtmp://birdfeeder.online/live/test.flv live=1"
Upd: как выяснилось, десятибитный поток не понимает никто, кроме хрома. Поэтому вернулись к стандарту:
ffmpeg -s 640x360 -f video4linux2 -i /dev/video1 -c:v libx264 \
-crf 27 -preset slow -bf 8 -g 100 -pix_fmt yuv420p -qmin 10 -qmax 43 -aq 1 \
-b:v 450k -bufsize 1200 -r 20 -an -f flv \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSans.ttf:text='%{localtime} $(cat /tmp/temperature)':fontcolor=white@0.9:fontsize=10:x=510:y=348" "rtmp://birdfeeder.online/live/test.flv live=1"
-crf 27 -preset slow -bf 8 -g 100 -pix_fmt yuv420p -qmin 10 -qmax 43 -aq 1 \
-b:v 450k -bufsize 1200 -r 20 -an -f flv \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSans.ttf:text='%{localtime} $(cat /tmp/temperature)':fontcolor=white@0.9:fontsize=10:x=510:y=348" "rtmp://birdfeeder.online/live/test.flv live=1"
Результирующий поток имеет битрейт в пределах от 200 до 350 килобит в секунду. Файл /tmp/temperature формируется независимо по крону и, увы, для отображения изменений в нём весь ffmpeg приходится периодически перезапускать.
Во-вторых, перед началом нового сезона было решено вновь проверить возможность отказа от использования Adobe Flash. Это, как кажется, вполне удалось. Теперь для показа используется VideoJS-contrib-HLS, а соответствующий код в HTML-файле выглядит так:
<HEAD>
<link href="https://vjs.zencdn.net/5.8.8/video-js.css" rel="stylesheet">
<script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
</HEAD>
<BODY>
<video id=example-video width=640 height=360 class="video-js vjs-default-skin" poster="/images/poster.jpg" controls>
<source
src="https://birdfeeder.online/hls/test.m3u8"
type="application/x-mpegURL">
</video>
</center>
<script src="https://vjs.zencdn.net/5.8.8/video.js"></script>
<script src="videojs-contrib-hls.min.js"></script>
<script>
var player = videojs('example-video');
player.play();
</script>
</BODY>
Что не решено:
- Не получилось придумать, как выводить изменения температуры. Несмотря на то, что показания термометра фиксируются каждую минуту, обновлять их вывод в кадр приходится путём перезапуска кодировщика. Это делается ежечасно.
- Не получилось придумать, как отвадить от кормушки голубей. Несмотря на качающийся подвес конструкции, несмотря на короткий «насест», некоторые из них умудряются балансировать и выгребать из кормушки семечки вниз. Внизу подоконник и стая ждущих собратьев. Результат — к весне подоконник по залежам гуано сравним с лучшими чилийскими птичьими пляжами.