Видеотрансляции на сайте

Для транскодирования и записи в очередной раз будем использовать VLC. В качестве RTMP-сервера задействуем Erlyvideo, ядро которого распространяется под лицензией GPL. В одной из предыдущих записей я уже описывал возможное решение с использованием Red5. Запись оказалась довольно интересной, поэтому теперь предложу еще одно решение с учетов современных тенденций и инструментов.
Приведу общую схему, где в качестве примеры указаны IP-камеры c видеопотоками в MPEG-4 и H264:
Схема трансляции
Как видно на диаграмме, для транскодирования используется VLC, а H264-поток забирается Erlyvideo напрямую, благо это он умеет. Для организации HTTP Live Streaming также используется VLC, настройки которого мы увидим ниже.
По традиции, детали установки приведу для Debian Squeeze 6.0 amd64, поскольку для этой архитектуры существует репозиторий Erlyvideo. Сразу оговорюсь, трансляция в примерах ведется без звука.
1. Подготовка
Добавляем репозитории для Debian Multimedia, nginx и Erlyvideo:
/etc/apt/sources.list.d/debian-multimedia.list
deb http://www.deb-multimedia.org squeeze main non-free
deb-src http://www.debian-multimedia.org squeeze main non-free
/etc/apt/sources.list.d/erlyvideo.list
deb http://debian.erlyvideo.org binary/
/etc/apt/sources.list.d/nginx.list
deb http://nginx.org/packages/debian/ squeeze nginx
deb-src http://nginx.org/packages/debian/ squeeze nginx
Обновляем репозитории
apt-get update
Обращаю ваше внимание, что репозиторий Erlyvideo добавлен для будущего обновления Debian до Wheezy, т.к. последняя версия Erlyvideo из пакетов ставится только на эту версию дистрибутива.
2. Установка ffmpeg, libvpx, fdk-aac, x264, openssl
apt-get install make automake g++ gcc autoconf lua5.1 liblua5.1-0-dev libtag1-dev \
libdvbpsi-dev libcdio-dev libvcdinfo-dev libcddb2-dev libmad0-dev libfaad-dev liba52-0.7.4-dev \
libmpeg2-4-dev libzvbi-dev libflac-dev libdca-dev libdirac-dev libdvdnav-dev libdvdread-dev libfaac-dev \
libgcrypt11-dev libgnutls-dev libgpac-dev libiso9660-dev libjpeg62 libltdl-dev libmp3lame-dev \
libmodplug-dev libpng12-dev libraw1394-dev libschroedinger-dev libspeex-dev libtag1-dev \
libtasn1-3-dev libtheora-dev libtwolame-dev libvcdinfo-dev libvorbis-dev build-essential \
librtmp-dev checkinstall git libopencore-amrnb-dev libopencore-amrwb-dev pkg-config yasm zlib1g-dev

# x264
cd /usr/local/src
git clone --depth 1 git://git.videolan.org/x264
cd x264
./configure --enable-pic --enable-shared
make
sudo checkinstall --pkgname=x264 --pkgversion="3:$(./version.sh | \
awk -F'[" ]' '/POINT/{print $4"+git"$5}')" --backup=no --deldoc=yes \
--fstrans=no --default

# fdk-aac
cd /usr/local/src
git clone --depth 1 git://github.com/mstorsjo/fdk-aac.git
cd fdk-aac
autoreconf -fiv
./configure --with-pic --enable-shared
make
sudo checkinstall --pkgname=fdk-aac --pkgversion="$(date +%Y%m%d%H%M)-git" --backup=no \
--deldoc=yes --fstrans=no --default

# libvpx
cd /usr/local/src
git clone --depth 1 http://git.chromium.org/webm/libvpx.git
cd libvpx
./configure --enable-pic --enable-shared --disable-unit-tests
make
sudo checkinstall --pkgname=libvpx --pkgversion="1:$(date +%Y%m%d%H%M)-git" --backup=no \
--deldoc=yes --fstrans=no --default

# ffmpeg
cd /usr/local/src
git clone --depth 1 git://source.ffmpeg.org/ffmpeg
cd ffmpeg
./configure --enable-gpl --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb \
--enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis \
--enable-libvpx --enable-libx264 --enable-nonfree --enable-version3 --enable-pic --enable-shared
make
sudo checkinstall --pkgname=ffmpeg --pkgversion="5:$(date +%Y%m%d%H%M)-git" --backup=no \
--deldoc=yes --fstrans=no --default

# openssl
# !!!ДЛЯ КОРРЕКТНОЙ РАБОТЫ ERLYVIDEO на Debian Squeeze!!!
# !!! Для Debian Wheezy можно apt-get install libssl1.0.0 !!!
cd /usr/local/src
wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
tar -xvzf openssl-1.0.1c.tar.gz
cd openssl-1.0.1c
./config --prefix=/usr zlib-dynamic --openssldir=/etc/ssl shared
make
sudo checkinstall --pkgname=openssl --pkgversion="5:$(date +%Y%m%d%H%M)-git" --backup=no \
--deldoc=yes --fstrans=no --default

hash x264 ffmpeg ffplay ffprobe
ldconfig
3. Установка VLC
cd /usr/local/src
wget http://download.videolan.org/pub/videolan/vlc/2.0.3/vlc-2.0.3.tar.xz
tar -xvJf vlc-2.0.3.tar.xz
cd vlc-2.0.3/contrib
mkdir native
cd native
../bootstrap
make .live555
cd /usr/local/src/vlc-2.0.3
./configure --enable-faad --disable-pulse --disable-alsa --disable-qt4 --disable-skins2 --disable-v4l2 \
--disable-xvideo --disable-glx --disable-visual --enable-realrtsp --enable-flac --disable-dbus \
--disable-xcb > /tmp/1 2> /tmp/2
# В файле /tmp/2 можно будет смотреть ошибки и предупреждения процесса конфигурирования
# Если будет какая-нибудь ошибка, то необходимо установить соответствующий пакет Debian и
# запустить configure еще раз
make
adduser ipcam
cp -r /usr/local/src/vlc-2.0.3 /home/ipcam/vlc
chown -R /home/ipcam/vlc ipcam:ipcam
#!Запускать vlc от пользователя ipcam!
4. Установка nginx
apt-get install nginx
5. Установка Erlyvideo
#!!! Если установлен Debian Wheezy, то apt-get install erlyvideo должно сработать
cd /usr/local/src/
wget http://debian.erlyvideo.org/binary/erlyvideo_2.10.18_amd64.deb
dpkg -i --force-depends erlyvideo_2.10.18_amd64.deb
6. Конфигурация VLC
Создаем скрипт /home/ipcam/start_vlc.sh (не забудьте поменять CONTROLPASSWORD):
#!/bin/sh
/home/ipcam/vlc/vlc -vv --sout-keep -I telnet --telnet-host=127.0.0.1 -R \
--udp-caching=1000 --http-caching=1000 --telnet-password=CONTROLPASSWORD \
--vlm-conf /home/ipcam/config --repeat --no-ffmpeg-hurry-up --no-sout-transcode-hurry-up \
--rt-priority --http-reconnect --sout-transcode-high-priority --loop --no-play-and-stop \
--extraintf logger --logfile=/var/log/vlc/vlc.log --no-sout-audio \
--network-caching=3000 --sout-mux-caching=1000
Для простоты и удобства запуска будем использовать VLM. Файл /home/ipcam/config:
# MPEG-4 IP-камера
new mpeg4mux broadcast enabled
# H264 IP-камера
new h264mux broadcast enabled

setup mpeg4mux input "URL видеопотока камеры, например, rtsp://x.x.x.x/mpeg4/media.amp"
setup h264mux input "URL видеопотока камеры, например, rtsp://x.x.x.x/live/ch00_0"

# !!!Замените, где нужно СЕРВЕР!!!
# Пример транскодирования MPEG-4 в AVC + HLS
# Вероятнее всего, что параметры, наподобие vb, width, height, fps необходимо будет поднастроить.
setup mpeg4mux output '#transcode{vcodec=h264,venc=x264{cabac=yes,nf=yes,chroma-me=yes,partitions=-parti8x8-parti4x4-partp8x8-partb8x8,me=dia,keyint=15,min-keyint=8,scenecut=0,ipratio=0.71,bframes=0,qcomp=0.6,qpmin=10,qpmax=51,qpstep=4,ref=1,direct=auto,trellis=0,bpyramid=no,mixed-refs=no,weightb=no,8x8dct=no,fast-pskip=yes,mbtree=no,weightp=0,aq-mode=0,lookahead=0},vb=800,width=480,height=360,acodec=none,fps=15}:duplicate{dst="std{access=http,mux=ts,dst=:9090}",dst="std{access=livehttp{seglen=15,delsegs=true,numsegs=5,index=/usr/share/nginx/html/mpeg4mux/video.m3u8,index-url=http://СЕРВЕР/mpeg4mux/video-######.ts},mux=ts{use-key-frames},dst=/usr/share/nginx/html/mpeg4mux/video-######.ts}"}'

# Пример HLS + запись трансляции в файл
setup h264mux output '#duplicate{dst=std{access=file{append},mux=ts,dst=/home/record/record.mp4},dst=std{access=livehttp{seglen=10,delsegs=true,numsegs=5,index=/usr/share/nginx/html/h264mux/video.m3u8,index-url=http://СЕРВЕР/h264mux/video-######.ts},mux=ts,dst=/usr/share/nginx/html/h264mux/video-######.ts}}'

сontrol mpeg4mux play
сontrol h264mux play
Создаем директории для записи логов VLC и устанавливаем права:
mkdir /var/log/vlc
chown ipcam /var/log/vlc
Поясню некоторые детали. Удобство запуска через VLM заключается в том, что при этом поднимается telnet-интерфейс управления потоками, который можно использовать как для вручную, так и, например, различными скриптами. Запуск самого VLC идет от пользователя ipcam, поскольку от root’а его запускать нежелательно. HTTP Live Streaming обеспечивается с помощью модуля livehttp. Что касается транскодирования, то тут полет фантазии среди параметров x264 практически безграничен, но скажу сразу, что пока данный набор параметров себя оправдывает. К сожалению, рекомендуемое разработчиками кодирование CRF+VBV c Erlyvideo у меня нормально не заработало. В остальном, сильно рекомендую ознакомиться с конфигурацией VLM и x264.
7. Конфигурация Erlyvideo
Правим секцию rewrite в файле /etc/erlyvideo/erlyvideo.conf:
...
{rewrite, [
% Пример для транскодированного потока
{"video1", mpegts, "http://localhost:9090"},
% Пример для H264-потока с IP-камеры AirCam Ubiquiti
{"video2", rtsp, "rtsp://x.x.x.x/live/ch01_0",[{timeout,5000}]}
]}
...
8. Конфигурация nginx
Для корректной работы HLS добавляем в /etc/nginx/mime.types:
...
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
Создаем директории для файлов HLS:
mkdir /usr/share/nginx/html/mpeg4mux
mkdir /usr/share/nginx/html/h264mux
chown ipcam /usr/share/nginx/html/mpeg4mux /usr/share/nginx/html/h264mux
9. Запуск сервисов
su - ananin -c "/home/ipcam/start_vlc.sh &"
/etc/init.d/nginx start
/etc/init.d/erlyvideo start
Смотрим логи и проверяем, что все запустилось нормально.
10. Вывод на HTML-страницу
# Скачиваем flash-плеер, я рекомендую JW FLV Media Player, но можно попробовать и другой
wget http://www.longtailvideo.com/jw/upload/mediaplayer.zip
# Распаковываем и кладем файлы player.swf, swfobject.js и jwplayer.js в один каталог с предполагаемой
# HTML-страницей, где будем показывать видео
HTML-код:
...
<div id="mplayer">This will be replaced by the SWF.</div>
<script type="text/javascript">// <![CDATA[
   jwplayer('mplayer').setup({
     width: 640,
     height: 480,
     bufferlength: 1,
     autostart: true,
     mute: true,
     controlbar: 'none',
     provider: 'rtmp',
     streamer: 'rtmp://<СЕРВЕР>',
     file: 'video1',
     
     modes: [
         {type: 'flash', src: 'player.swf'},
         {type: 'html5',
            config: {
               file: 'http://СЕРВЕР/mpeg4mux/video',
               
               provider: 'http'
          }
       }
      ]
   });
// ]]></script>

...
11. TODO
Перечислю возможные улучшения, которые не будут лишними:
  1. Watchdog для проверки работспособности VLC, который будет перезапускать необходимые сервисы в случае потери потоков с камер
  2. Создание плейлиста для JW Player
  3. Logrotate для логов VLC
  4. Скрипт для организации архивов записей, реализуется через telnet-интерфейс VLC, задача не ахти простая, но интересная ;)
12. На будущее
На данный момент основными технологиями стриминга видео являются HTTP Live Streaming, вообще говоря, предназначенная для использования на устройствах Apple, вполне применимая в теории и на других устройствах, а также HTTP Dynamic Streaming от Adobe (в некотором смысле преемник RTMP).
Кроме того, сейчас активно развивается Adaptive Provider. В том числе, он обеспечит поддержку HLS на non-Apple устройствах, что позволит отказаться от RTMP. Для использования HDS, можно воспользоваться 3-ей версией Erlyvideo — Flussonic и его поддержкой HDS. Насколько я понял, в его ядро поддержка HLS не включена. Ну а наличие Open Source Media Framework позволяет создавать свои плееры для RTMP и HTTP-стриминга.
Ссылки:
  1. http://www.videolan.org
  2. http://erlyvideo.org/
  3. http://www.longtailvideo.com/players/jw-flv-player
  4. http://www.videolan.org/developers/x264.html
  5. http://deb-multimedia.org/
  6. http://www.debian.org/index.ru.html
  7. https://ffmpeg.org/trac/ffmpeg/wiki/UbuntuCompilationGuide
  8. https://developer.apple.com/resources/http-streaming/
  9. http://www.adobe.com/products/hds-dynamic-streaming.html
  10. http://nginx.org/ru/
Информация получена из http://flance.onego.ru/2012/09/07/387
Скопипастена для анализа и дальнейшей переработки.