Мастерим компьютер для прямых интернет трансляций и записи с видеокамеры или системы ВКС


Мало кто знает, что в Пермском гос. университете есть пару специальных комнат для видеоконференсвязи (ВКС). Сегодня википедия бастует, так что приведу свое описание что такое ВКС.  Обе находятся в 8 корпусе и изредка используются. Сами по себе эти системы ВКС состоят из железок что на рисунке (это Tandberg C90, есть еще Tandberg C40 и Aethra Vega X5), поворотных камер и умеют в реалтайме передавать видео и презентации на другие подобные железки в других ВУЗах. Передают красиво, в HD или FullHD, могут на плазменную панель выводить презентацию, показывать удаленной стороне презентацию с нашего ноутбука, имеют эхоподавители ну и все дела. В образовании ВКС используется, обычно, для видеолекций с другими городами.

И все бы хорошо с этими устройствами, если бы только обычно не требовалось лекцию:
1) Записать
2) Вещать в интернет на каком-нибудь сайте
3) На сайте с вещанием повесить чат для обратной связи со зрителями
Конечно, желания писать, вещать, чатиться есть не только у нашего ВУЗа и под это желание выпушена специальная железка за кучу денег: Codian IP VCR 2210. Купили мы эту железку которая по бумажки FullHD (1920x1080) compitable, HD recording (1280x720) в mpeg, одновременно вещает в трех разных разрешениях на сайте, отдельно выводит презентацию и имеет встроенный чат. Поставили и на первой попавшейся конференции использовали, в результате чего выяснилось:

1) FullHD compitable надо переводить как маркетинговые привычные ДО FullHD, т.е. железка получает видео в разрешении до FullHD, но писать его может только в HD (1280х720), а, учитывая очень древний кодек mpeg1 и необходимость перекодировать видео из оригинального h.264 в mpeg, то качество так себе.
2) Писать видео железяка может в HD, но если одновременно хочется это же видео вещать, то разрешение уменьшается до SD - обычного разрешения аналогового телевидения. При этом вещается тоже не FullHD, а сильно пережатое SD, о чем и написано в инструкции мелким шрифтом на хренадцатой странице и о чем маркетологи в своих иллюстрациях как-то забывают упомянуть. При таком разрешении о возможности разглядеть формулы на доске не можут быть и речи. Только если рисунки. КРУПНЫЕ РИСУНКИ. Без мелких деталей :)

3) После обновления прошивки чата никакого не обнаружилось кроме пустого места там где ему следовало бы быть. А на сайте производителя появилась опция доукомплектования чатом всего за 80 т.р.! На вопрос поставщику: "Где чат?", он очень удивился: "Не было там никогда никакого чата".
4) Не смотря на возможность вещания на сайте не только лектора, но и его презентации, презентация гонится не видеопотоком, как можно было бы подумать, а просто сменяющимися jpeg-картинками и требует от посетителей установленной java. Т.е. если лектор вставит в презентацию видеоролик, то видеоролик на сайте превратиться в слайдшоу по кадру в секунду. Конечно, про слайдшоу в технических спецификациях вообще ничего не сказано.
5) На страницу с трансляцией нельзя дать прямую ссылку, необходимо обязательно попасть на страницу сайта, на которой выполнить неочевидные нажатия пары кнопок.
6) Ах, да. Хотя прямо с железяки записанное видео и можно хранить, но не больше 4 записей. Т.е. после того как сделана запись, ее необходимо ручками переносить на другой сайт и как-то всем рассказывать куда на какой сайт переехала запись трансляции.
7) Нельзя темизировать страницу с трансляцией. Повсюду надписи codian, cisco с дурацкими логотипами там где должны быть надписи и логотипы Пермского Государственного Национального Исследовательского Университета.
В итоге: деньги потрачены, но получившееся решение задач 1,2,3 не соответствует потребностям образования. И... решено наваять "на коленке" и из подручных материалов систему для записи, прямой трансляции, с сайтом и чатом.

Мастерим компьютер для записи и прямых трансляций с видеокамеры или системы ВКС

Итак, попробуем на коленке собрать компьютер который сможет:
А) Записывать видеосигнал со входа HDMI
Б) Записываемый сигнал вещать в интернете с разным битрейтом или разрешем
В) Будет содержать на себе сайт с чатом
Г) Вещаемый сигнал будет передавать дальше на HDMI-выход
Д) Имеет отдельный аудиовход для записи звука (например, с аудиомикшера)
В такой постановке задачи решение получается универсальным, потому что есть очень много устройств отдающих видео по HDMI: системы ВКС (включая наш Tandberg), видеокамеры, компьютеры, видеомикшеры, передвижные телевизионные станции и можно просто в разрыв HDMI подключить такой компьютер и обеспечить запись и одновременное вещание на сайте.
Ну и осталось добавить удобства для использования в университете:
Е) Возможность подключения по Wi-Fi и передачу сигнала на внешний вещательный сервер в ЦОД, чтобы толпа зрителей не забила весь канал Wi-Fi. Пригодится для вещания с мест где нет проводной сети.
Ж) Там где в университете есть проводная сеть, компьютер автоматически подключался по PPPoE и автоматически запускал трансляцию. Это чтобы в таких случаях можно было притащить куда-то компьютер без монитора и клавиатуры, подключить к сети и он начал показывать то что ему в HDMI-вход подают.
З) А, ну еще хорошо бы уметь работать с USB-вебкамерами. Качество у них так себе, но на всякий случай - вдруг пригодится
И) Решение должно быть бюджетным, в том смысле что дешевле коробочных Havision, продаваемых за миллион деревянных

Выбираем железо

Для кодирования FullHD, да еще и в три потока, процессорной мощности мало не бывает. Но и компьютер таскать с собой придется, так что он должен быть легким и компактным. Поэтому двухпроцессорные компьютеры сразу отпали (большие, тяжелые, шумные), а самый мощный однопроцессорный компьютер на момент покупки был Intel I7-980x Extream Edition на 6 ядрах по 3.3 ГГц каждое + HyperThreading. Хороший вариант корпуса предложил Shuttle на чипсете X58:
Легкий корпус, блок питания на 500Вт, серверный чипсет X58, USB 3.0, два слота PCI-Express по 16 линий в каждом, хитрая система охлаждения процессора (на картинке смотрелась как малошумная). Из недостатков корпуса - сильно греется северный мост. Добил компьютер 8 ГБ ОЗУ, видеокартой nvidia GT520 (дело в том, что Intel I7 980x Extream Edition на самом деле перемаркированный Xeon, а в Xeon не бывает интегрированных видеокарт, так что пришлось взять внешнюю видеокарту), SSD диском на 60ГБ (обычный диск можно растрясти пока таскаешь туда-сюда и у SSD-диска не будет проблем если пара сотен человек начнет одновременно качать видеозапись). В качестве приятной опции заказал беспроводную клавиатуру с тач-скрином. Для подключения к университетской сети Wi-Fi куплена сетевая карта с USB-интерфейсом.
Осталось выбрать только плату захвата HDMI-сигнала.

PCI-Express плата HDMI-захвата для записи и прямого вещания



Плат на рынке мало. Даже удивительно что мало, вроде задача очень распространенная и чипы с аппаратным сжатием видео есть в камерах видеонаблюдения и на планшетных компьютерах с вебкамерами за 200$. На отечественном рынке удалось найти только PCI-Express платы захвата AverTV DarkCrystal HD Capture и Blackmagic Intensity Pro, не умеющих аппаратно кодировать поток. Первая, как оказалась, умеет принимать HDMI-сигнал только через свою фирменную программу, которая может его только записать, но мы не сможем его вещать. Так что AverTV из рассмотрения выпал. Зато Blackmagic обещает поддержку Windows, Mac, Linux, включая возможность работать в Windows как со стандартной камерой через DirectShow. И еще обещают бесплатно программу Media Express для записи и тоже под все платформы, включая Linux, а также совместимость с Adobe Flash Media Live Encoder (FMLE) - это программа как раз используется для кодирования видео и отправки его на flash-сервер. Единственный, в дальнейшем обнаружившийся недостаток у blackmagic, о котором опять молчит инструкция, но который оказался очень досадным в дальнейшем: плата захвата под Linux не поддерживает стандартный интерфейс видеоустройств Video4Linux2, а надпись в документации к плате захвата Supported OS: Linux означает только то, что с платой захвата в Linux будет работать та самая программа Media Express, которая только и умеет что писать поток на диск.
Но про недостатки Blackmagic Intensity Pro мы узнали уже после того как он был куплен.

Итого: стоимость железа без видеокамеры получилась в районе 70 т.р., что более чем на нолик дешевле Havision Mako.
Update: таки платы с поддержкой Video4Linux в природе существуют.

Выбираем сервер для прямой трансляции

Железо есть, теперь надо решить при помощи какого софта будем вещать в интернет. Напоминаю, что вещать хотим на сайте и не хотим заставлять пользователя ставить всякие разные плагины. Зритель должен зайти на страницу с вещанием и просто начать смотреть. Единственной технологией работающей сразу на Windows, Linux, Mac, Android является вещание во флеше (по протоколу RTMP). Ущемленными при таком выборе останутся только владельцы Iphone и Ipad (да и с ними можно разобраться). Технологию вещания во flash по протоколу RTMP подробно расписывать не буду, скажу только какие медиа-сервера для этих целей подходят. Из платных это Adobe Flash Media Server (FMS) и Wowza, из бесплатных Erlyvideo и Moment. FMS и Wowza стоят по 1000$ и написаны на java, т.е. работают и на Windows и на Linux. Erlyvideo написан на экзотическом erlang и работает только под Linux. Moment написан на Cи и тоже только под Linux. Начальство в покупке FMS или Wowza отказало, так что остались на выбор Erlyvideo и Moment и этим же выбором диктуется установка на компьютер ОС Linux.

Делаем сайт для трансляции

Можно написать простенький сайт с нуля, но я предпочитаю использовать готовые CMS по такой причине:
  • под CMS легко найти программиста, который допишет к ней необходимый функционал
  • под CMS можно поискать готовые модули для типовых задач
  • под CMS можно легко купить готовый шаблон или установить бесплатный. А если CMS на компьютере совпадает с CMS сайта организации, то вообще можно просто перенсти шаблон на компьюетр и сразу получить сайт трансляции с тем же видом что и сайт организации.
Из CMS я выбрал drupal7, поскольку шаблон ПГУ для него уже был и имелся опыт написания модулей.

Чат

На сайт надо вставить чат. Вменяемых готовых чатов под drupal нет, но можно воспользоваться каким-либо внешним чатом или написать свой. Я решил написать свой для того, чтобы имелась возможность администратору использовать чат для отправки команд пользователю. Например, чтобы по окончании вещания отправить javascript команду и перенаправить пользователей на другую страницу или чтобы была возможность отправить во время трансляции какой-либо alert. Чат написал на nodejs с использованием вебсокетов. Правда, до реализации отправки команд руки так и не дошли, но а так больше рассказывать нечего.

Включаем возможность трансляции с USB-камеры

В хотелках я писал возможность захвата с USB-камеры и вещания в интернет. У нас была камера Tandberg USB PrecisionHD с разрешением HD 1280х720 и 30 кадрами в секунду при любой освещенности и светосилой объектива F1.7. В камере хороший встроенный микрофон. В Linux камера опознается как стандартное устройство UVC и, потому, поддерживается почти любой программой захвата видео. Захватывать видео и кодировать я решил при помощи VLC, а вещать Erlyvideo, установленным на этом же сервере. Управлять всем процессом хотелось без использования монитора только через сайт на drupal. Ну так в итоге и получилось, единственный всплывший момент: как останавливать захват видео? Если просто убить VLC, то файл видео оказывается недописанный и его потом никакая программа воспроизвести не может. Надо как-то из командной строки сказать VLC чтобы она прекратила записывать файл. Это можно сделать таким образом:


  • Запустить VLC с поддержкой telnet-сервера.
  • Подключиться к этому telnet-серверу и отдать команду на начала захвата видео с USB-камеры
  • Телнетом отправить команду закодировать поток и вещать его в mpeg-ts по протоколу http сжатому кодеком mp4.
  • Телнетом отправить команду продублировать этот поток в файл на диске (т.е. записать на диск уже сжатое видео).
Команды эти должны последовательно отправляться с сайта по нажатию кнопок.
Для остановки записи тогда надо просто телнетом отправить команду остановки записи в файл. Пример (не мой) телнет-скрипта можно посмотреть здесь.
Конфигурация erlyvideo очень простая, надо в файле конфигурации указать в качестве источника видео http-ссылку на поток в контейнере mpeg-ts. Тут важно что erlyvideo нужно чтобы VLC будет отдавало видео по http в контейнере mpeg-ts и сжатое кодеком mp4 и аудиокодеком AAC.
Все это было проделано в виде соответствующего модуля для drupal. Местами для запуска VLC-сервера использовался perl.
После я добавил еще небольшую плюшку. Дело в том, что часто на конференциях докладчики выступают по 15-20 минут, а доклады потом требуется разделять по отдельным файлам. Так как немного лениво после записи разделять доклады в видеоредакторе, то я добавил возможность кнопками останавливать запись, тут же менять название следующей записи и, по нажатию кнопки, продолжать запись в другой файл. После остановки видео для администратора генерируется прямая ссылка на скачивание через http-сервер. Эту ссылку можно тут-же опубликовать в чате.
Ну и до кучи, предусмотрена возможность одновременного вещания с нескольких USB-вебкамер и вообще с любых Video4Linux2 видеоустройств, распознанных как /dev/video0, /dev/video1 и т.д.

Вещание потока с HDMI-входа карты захвата



Как я уже писал, заказывая плату захвата я полагал что в Linux она будет поддерживаться как стандартное устройство Video4Linux2, выглядить как /dev/video0 и написав ПО для вещания USB-вебкамеры я проблему уже решил. Но оказалось что я заблуждался и процесс вещания с HDMI-входа придется строить с самого начала.
Сервер вещания может быть только под Linux и очень хотелось не переносить его в ЦОД. Получается два варианта:
1) Основным сервером сделать Windows, на Windows провести захват видео средствами Adobe Flash Media Live Encoder (FMLE) и опубликовать поток на медиасервере Erlyvideo. А раз Erlyvideo работает только под Linux, то запустить Linux в виртуальной машине. В качестве виртуальной машины выбор из VirtualBox или VMware Player. Выбор пал на VMware Player, поскольку с VirtualBox возникли непонятные проблемы. Так в итоге и сделал, но выяснились проблемы: если оставить FMLE кодировать сигнал на ночь, то постепенно падает число кадров в потоке с 60 до 8 к/c.
Кстати, попробовал я сделать и наоборот: установить Linux на компьютер, на нем запустить Xen, в Xen запустить виртуализованную Windows и пробросить карту захвата как PCI-устройство. Но по каким-то причинам так пробросить именно blackmagic не удалось, хотя контроллер с USB-камерой легко пробросился.
2) Второй вариант тоже простой: использовать только Linux без всякой виртуаллизации, но найти способ захватить поток с blackmagic. Такая возможность в принципе действительно оказалась и тоже в виде двух программ. Первая программа - бесплатный модуль decklinksrc к фреймворку gstreamer. Вторая программа bmdcapture - некоторый бинарный файл, написанный на основе blackmagic SDK и умеющий хватать видеопоток и отправлять его в ffmpeg, а уже ffmpeg отправлять видео на любой из медиа-серверов, хоть Erlyvideo, хоть Moment, хоть Wowza.
Пример реализации прямой трансляции с камеры Tandberg PrecisionHD Camera с чатом на nodejs и медиа-сервером Moment:

flash plus chat live translation
Дальше пойдут технические подробности как реализовать работу с decklinksrc или с bmdcapture, интересные только тем кто захочет это повторить на своих системах. Скажу только что вещание с bmdcapture получилось нестабильным, а с плагином к gstreamer моих знаний оказалось недостаточно чтобы реализовать совсем так как хотелось. Те, кто не собирается создавать подобную систему, могут сразу перейти к заключению.

Захват HDMI-видео с blackmagic intensity pro в Linux при помощи модуля decklink к gstreamer

Опишу как именно можно получить поток с карт blackmagic intensity pro. Все действия производились на Ubuntu 12.04 LTS, но должны получиться и на других дистрибутивах при наличии свежего модуля gstreamer.
1) Установить модуль к карте захвата blackmagic c сайта производителя Blackmagic_Desktop_Video_Linux_9.5.tar.gz
Установка написана в инструкции, после установки убеждаемся что модуль загружен
# lsmod |grep blackmagic
и, если ничего не видем, загружаем модуль
# modprobe blackmagic

2) Устанавливаем gstreamer вместе с плагинами bad: apt-get install gstreamer0.10-plugins-bad. Плагины bad содержат необходимый нам плагин захвата видео с карт decklinksrc
3) Проверяем что версия плагина decklinksrc в gstreamer свежая:
# gst-inspect decklinksrc |grep Version.
У меня получилась версия 0.10.22.3. В более ранних версиях параметры вызова плагина в gstreamer могут немного отличаться
4) Просматриваем режимы работы интерфейса HDMI карты захвата intensity pro той же самой командой # gst-inspect decklinksrc и смотрим режимы под mode.
Нам надо выбрать режим, в котором видео поступает в плату захвата от источника HDMI-сингала (видеокамера, компьютер). mode 9 соответствует режиму HD1080 30p, mode 15 режиму HD1080 60p, mode 18 режиму HD720 60p. Также надо обратить внимание на параметр connection, из которого надо выбрать вход, к которому подключен источник HDMI сигнала. Для intensity pro HDMI идет как connection 1, компонентый вход как component 3.
Аналогично со звуком audio-input: Автоматическое определение входа audio-input 0, звук через кабель HDMI: audio-input 1, аналоговых вход: audio-input 3
5) Теперь можно запускать gstreamer для захвата изображения. Пример записи изображения в файл при котором камера подает изображение 1080p 30fps на вход HDMI, затем изображение кодируется в mpeg4 и в контейнере avi сохраняется в файл /tmp/video.avi:
$ gst-launch -v decklinksrc mode=9 connection=1 ! queue ! ffmpegcolorspace ! queue ! ffenc_mpeg4 ! avimux ! queue ! filesink location=/tmp/video.avi
Другие варианты использования gstreamer можно посмотреть здесь, важно только что в качестве источника видео используется decklinksrc.
Что, собственно, у меня сходу не получилось: не получилось отправить это видео на флешовый сервер прямо из ffmpeg, а только лишь сохранение в файл не интересно - это и так умеет делать программа Media Express. Более опытные в деле работы с gstreamer найдут вариант как это сделать или просто используют тотже ffmpeg для получения видео и отправки его на медиа-сервер. Кстати, с gstreamer есть еще один интересный вариант. Дело в том, что медиа-сервер Moment может в качестве источника видео использовать gstreamer. Но сам сервер собран со старой версией плагина decklink, которая не работает, а собрать gstreamer из исходников со свежей версией плагина decklink или каким-то путем просто заменить плагин у меня не получилось.
Кстати, вот вариант чтобы захватывать gstreamer на компьютере, на нем же кодировать в mp4 и результат писать в сокет:
# gst-launch decklinksrc mode=9 connection=1 ! queue ! ffmpegcolorspace ! x264enc  speed-preset=fast bitrate=300 key-int-max=25 threads=8 ! flvmux ! tcpserversink port=12999 protocol=none
а на другом компьютере читать данные из сокета и что-то потом с ними делать уже в ЦОД-е:
gst-launch tcpclientsrc protocol=none port=12999 ! ......

Захват HDMI-видео с blackmagic intensity pro в Linux при помощи decklink-ffmpeg

Ну и еще один способ получить изображение с камеры, как в начале и говорилось, использовать decklink-ffmpeg. Начинаем опять с установки
1) Скачайте DeckLink SDK с сайта разработчика и распакуйте во временную папку, например /tmp/decklinksdk. У меня SDK было версии 9.5.
2) Установите библиотеки libav
3) Скачайте с сайта разработчика decklink-ffmpeg, распакуйте содержимое в папку с SDK в подпапку Linux/Samples (при компиляции decklink-ffmpeg потребуются файлы из DeckLink SDK). У меня получилась папка /tmp/decklinksdk/Linux/Samples/lu-zero-decklink-ffmpeg-a8b01. Перейдем в папку с decklink-ffmpeg:
# cd /tmp/decklinksdk/Linux/Samples/lu-zero-decklink-ffmpeg-a8b01
и скомпилируем программу
# make
4) После успешной компиляции в папке появятся исполняемые файлы bmdcapture, bmdgenlock, bmdplay, которые надо просто скопировать в /usr/bin.
5) Запускаем захват видео с платы HDMI в режиме mode 9 и перенаправляем захваченое сырое видео на ffmpeg для последующего кодирования с битрейтом 2000Кбит/c на медиа-сервер (Wowza, Adobe Flash Media Server, Erlyvideo, Moment или др.) на адрес rtmp://example.com/stream/name1
 # bmdcapture -m 9 -F nut -f pipe:1 | ffmpeg -y -i - -qmax 63 -qcomp 0 -vb 2000k -an -f flv rtmp://example.com/stream/name1
Для использования h.264 надо установить x264 и запустить
 # bmdcapture -m 9 -F nut -f pipe:1 | avconv -y -i - -vcodec libx264 -threads 10 -preset:v fast -vb 2000k -ar 44100 -f flv rtmp://example.com/stream/name1
В моем случае флешевым сервером выступил Moment на кодирующем компьютере. С этим вариантом все заработало кроме одного но: bmdcapture самопроизвольно падает раз в 10-40 минут. Чтобы программа сразу после падения сама поднималась я просто засунул запуск bmdcapture в бесконечный цикл. Т.е. как только bmdcapture падает, она сразу запускается вновь. При этом происходит выпадание примерно 8 секунд видео как из вещания, так и из записи, если ее вести в отдельные файлы.

Заключение

Итоги половинчатые: хотелось на выходе получить маленький компьютер, который можно отдать любому сотруднику, сотрудник воткнет в компьютер видеокамеру или систему ВКС и дальше сможет сам через веб-интерфейс запустить трансляцию, записать и скачать видео, поучаствовать в чате. Получилось все это только для USB-вебкамеры, а для HDMI такую автоматизацию провести не удалось из-за отсутствия поддержки Video4Linux2 со стороны карты захвата. Значит, пока, для вещания и записи HDMI-видео по прежнему нужен квалифицированный специалист.
С июля этого года такой специалист принят в УЦИ и головная боль по записи видеоконферений с организации прямой трансляции теперь не моя, а пытаться как-то автоматизировать этот процесс с помощью автономного переносного компьютера теперь уже не нужно.
P.S. Спасибо тем, кто дочитал до конца :). В качестве бонуса публикую исходники чата для сервера Moment https://github.com/borovinskiy/momentvideo-chat

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

Как оживить корпоративный сайт?

Тестирование производительности Drupal: MySQL vs PostgreSQL часть 2