magnify
Home arrow Posts tagged "flash"
formats

Организация видеотрансляции на сайте

Опубликовано: 09.02.2009 Автор: в

В одном из моих прошлых постов для передачи потокового видео я использовал связку Motion+ffmpeg+ffserver. В принципе, это рабочий вариант, но по какой-то причине ffserver довольно «криво» работал в качестве HTTP-сервера для отдачи видео.

В этот раз мы попробуем пойти другим путем и организовать трансляцию IP-камеры на сайте с помощью VLC Media Player — кроссплатформенного видеоплеера, а также, что наиболее важно в нашем случае, сервера потокового вещания. Сразу оговорюсь, что в качестве формата трансляции был выбран Flash Video (flv). Причин несколько, но самая главная — наличие Flash-плеера в браузере у 99% процентов пользователей Интернет. Конечно, можно выбрать и другой контейнер, например ASF.

Поскольку IP-камера (AXIS), с которой предполагалось вещание выдавала видео в формате MPEG ES, то предварительно его надо было преобразовать в MPEG TS, чтобы потом его можно было транскодировать в FLV.

Общая схема трансляции показана на рисунке ниже.

Общая схема

В качестве TS Muxer, FLV Encoder и FLV Streamer и будет выступать VLC.

Технически же это будет реализовано таким образом, что TS Muxer будет посылать MPEG TS поток по HTTP на порт 8080, откуда его можно будет «забирать», транскодировать в FLV и слать по HTTP на порт 8081. Чтобы было более понятно, проиллюстрирую это примером. Предположим, что все будет происходить на одном сервере (хотя это абсолютно не обязательно). Тогда техническая реализация работы будет следующей:

Реализация

Приступим к реализации. Как обычно, детали установки приведу для Debian Etch 4.0. VLC будем собирать из исходников.

1. Подготовка:

# Устанавливаем необходимые для сборки пакеты
# !!! НЕ ЗАБУДЬТЕ ДОБАВИТЬ РЕПОЗИТОРИЙ DEBIAN-MULTIMEDIA В APT !!!
apt-get install ffmpeg libavformatcvs51 libavcodeccvs51 libavcodeccvs51-dev libavformatcvs51-dev \
libavutilcvs49-dev libavutilcvs49 libavahi-client3 libavahi-common-dev libpostproccvs51-dev  \
libswscalecvs0-dev libswscalecvs0 libxvidcore4-dev libxvidcore4 libx264-dev libx264-54 automake1.9 \
autoconf g++ gcc liba52-0.7.4-dev libdvbpsi3-dev libdvbpsi3 libfaad-dev libfaac-dev libfribidi-dev \
libgcrypt11-dev liblame-dev liblua5.1-0-dev libmad0-dev libmpeg2-4-dev libogg-dev libvorbis-dev \
zlib1g-dev libvcdinfo-dev libiso9660-dev libcddb2-dev libflac-dev

# Скачиваем и собираем LIVE555 Streaming Media
# !!! ВНИМАНИЕ !!! На 4.11.2009 vlc с последней версией live от 28.10.2009 не работает. Проверено.
# http://forum.videolan.org/viewtopic.php?f=13&t=66303
# У меня сохранилась более старая версия, поэтому загружаем отсюда:
wget http://flance.onego.ru/files/live/live.tar.gz
tar xvfz live.tar.gz
cd live
./genMakefiles linux
make

2. VLC:

# На время написания статьи самая свежая стабильная версия - 0.9.8a
wget http://download.videolan.org/pub/videolan/vlc/0.9.8a/vlc-0.9.8a.tar.bz2
bzip2 -d vlc-0.9.8a.tar.bz2
tar xvf vlc-0.9.8a.tar

3. Добавляем live555 в дерево исходных текстов VLC:

cd vlc-0.9.8a
cp -r $YOUR_LIVE555_BUILD_DIR extras

4. Собираем VLC:

# Поскольку мне не нужен был VLC с графическим интерфейсом на сервере, то использовались ключи, которые его не собирали
./configure --enable-release --enable-faad --disable-remoteosd --disable-qt4 --disable-skins2 \
--disable-activex --disable-v4l2 --disable-libv4l2 --disable-x11 --disable-xvideo --disable-glx \
--disable-opengl --disable-visual --enable-realrtsp --enable-flac --with-live555-tree=extras/live \
--disable-dbus --disable-hal > /tmp/1 2> /tmp/2
# В файле /tmp/2 можно будет смотреть ошибки и предупреждения процесса конфигурирования
# Если будет какая-нибудь ошибка, то необходимо установить соответствующий пакет Debian и
# запустить configure еще раз
make

5. Запускаем VLC TS Muxer:

./vlc -vv --no-rtsp-tcp rtsp://<URL потока> --rtsp-caching=10000 --no-sout-audio --sout \
'#std{access=http,dst=127.0.0.1:8080,mux=ts}'

6. Запускаем FLV encoder+streamer:

./vlc -vv http://127.0.0.1:8080 --loop --http-caching=10000 --sout \
'#transcode{vcodec=FLV1,vb=1024}:std{access=http{mime=video/x-flv},dst=:8081/stream.flv,mux=ffmpeg{mux=flv}}'

6. Интеграция в HTML:

# Скачиваем flash-плеер, я рекомендую JW FLV Media Player, но можно попробовать и другой
wget http://www.longtailvideo.com/jw/upload/mediaplayer.zip
# Распаковываем и кладем файлы  player.swf и swfobject.js в один каталог с предполагаемой
# HTML-страницей, где будем показывать видео

Добавляем следующий HTML-код в страницу:

<script type="text/javascript" src="swfobject.js"></script>
<div id="mplayer">this will be replaced by the SWF.</div>
<script type="text/javascript">
var so = new SWFObject('player.swf','player','459','375','9');
so.addParam('allowfullscreen','true');
so.addParam('flashvars','start=1&amp;repeat=always&amp;file=http://<адрес потока>&amp;bufferlength=0&amp;autostart=true&amp;displayclick=none&amp;mute=true');
so.write('mplayer');
</script>

Внимание! Параметры start (спасибо Кириллу) и repeat важны.
Все, можно проверять. Хочу еще отметить, что на данный момент VLC с текущей версией FFMPEG для в плане FLV кодирования не работает, поэтому я использовал пакеты Debian. Если кодек FLV1 не нужен, то можно собрать VLC и со свежими FFMPEG и X264.

04.11.2009 ОБНОВЛЕНИЕ:
Важная информация:
1. Для сборки на Debian Lenny 5.0 необходимо добавить в опции конфигурирования VLC на 4 шаге опции --disable-nls и --disable-mozilla, иначе вылезет ошибка о Buggy glibc version.
2. VLC с последней версией liveMedia не стартует. Смотрите комментарии в шаге 1.

Ссылки:

  1. http://www.videolan.org
  2. http://www.ffmpeg.org
  3. http://www.live555.com/liveMedia
  4. http://www.longtailvideo.com/players/jw-flv-player
 
Просмотров: 40 606 | 99 комментариев  comments 
formats

Передача видео с IP-камер D-Link

Опубликовано: 22.05.2008 Автор: в

Недавно столкнулся с проблемой получения и передачи потокового видео с IP-камеры D-Link 6620G. Обнаружилось, что эта камера (как и все камеры D-Link, как мне ответил сотрудник на официальном форуме) не отдает видеопоток напрямую ни по UDP, ни по HTTP в чистом виде, что меня очень неприятно удивило. С камерой можно работать только через ActiveX-компонент, т.е. только в IE. Единственное, что можно получить — это текущий кадр через cgi-bin/video.jpg. Но задача как раз была организовать раздачу через Web. Что ж, после некоторых размышлений мне удалось это сделать, организовав следующую схему:

Общая схема

Работать это должно было следующим способом:

  1. С камеры формируется MJPEG-поток, забирая текущий кадр /cgi-bin/video.jpg. Для этого используется детектор Motion. Этот программное решение подкупило меня своей легковесностью, быстротой, а также довольно гибкой функциональностью.
  2. Далее ffmpeg конвертирует MJPEG-поток в flv и отдает flv-поток с помощью ffserver.
  3. В нужную HTML-страничку встраивается FLV-плеер, который и показывает картинку.

Опишу подробнее процесс установки и конфигурирования этого добра на Debian 4.0:

1. Подготовка:
Добавляем в /etc/apt/sources.list репозиторий debian-multimedia

deb http://www.debian-multimedia.org stable main
deb-src http://www.debian-multimedia.org etch main

Устанавливаем пакеты

apt-get update
apt-get install motion ffmpeg

2. Конфигурация motion (/etc/motion/motion.conf):
Сам Motion, вообще говоря, это программный детектор движения. У него довольно много интересных настроек и опций. Конфигурирование происходит через файл /etc/motion/motion.conf.

# Включаем демон
daemon on
quiet on

# Указываем URL кадра камеры
# и, если необходимо, логин и пароль
netcam_url http://IP-АДРЕС/cgi-bin/video.jpg
netcam_userpass admin:adminpass
# Надпись слева
text_left Test

# Размер получаемого кадра c камеры
width 704
height 576

# Частота кадров. Иными словами, максимально количество кадров забираемое
# с камеры в секунду
framerate 5
# Качество забираемой картинки
quality 100
# Отключаем автояркость
auto_brightness off

#Различные настройки видео
threshold 4500
noise_level 64

brightness 0
contrast 0
saturation 0
hue 0

# Отключаем использование ffmpeg в реальном времени
ffmpeg_cap_new off

# Директория, где храним снимки и фильмы
target_dir /var/lib/motion/snapshots

# Включаем сервер, транслирующий MJPEG-поток на порту 8081
webcam_port 8081

# Разрешение соединения с MJPEG-потоком
# Если ffmpeg на другом IP, то ставим off. Иначе - on
webcam_localhost off

# Качество выдаваемого MJPEG-потока
webcam_quality 100
# Частота кадров выдаваемого потока
webcam_maxrate 5

# Отключаем запись снимков и видео.
# Можно и включить, кому хочется
output_all off
output_motion off
output_normal off

Проверить наличие MJPEG-потока можно, например, при помощи VLC media player.

3. Конфигурирование ffserver:
Настройка ffserver происходит через файл /etc/ffserver.conf:

# Порт, ка котором будет слушать ffserver и отдавать flv-поток
Port 8080

# Интерфейс привязки ffserver'а (в данном случае - все)
BindAddress 0.0.0.0

# Максимально дозволенное количество клиентов
MaxClients 1000

# Пропускная способность в kbit/sec
MaxBandwidth 100000

# Файл журнала
CustomLog /var/log/ffservser.log
...
# Описываем feed
<Feed feed1.ffm>
File /tmp/feed1.ffm
FileMaxSize 10M
</Feed>
...
# Поток Flash Video
# Описываем его параметры (bitrate, framerate, buffersize и т.д.)
<Stream test.flv>
Feed feed1.ffm
Format flv
VideoCodec flv
#VideoFrameRate 4
VideoSize 4cif
VideoBitRate 2000
#Qscale 2
#VideoBufferSize 256
#VideoQMin 10
#VideoQMax 10
#VideoIntraOnly
PreRoll 0
NoAudio
</Stream>
...
# Можно включить статистику
<Stream stat.html>
Format status
# Only allow local people to get the status
#ACL allow localhost
ACL allow <IP-адрес>
</Stream>
...

4. Скрипты запуска и остановки ffmpeg и ffserver:
Для запуска и остановки ffmpeg и ffserver создаем простые shell-скрипты.
start_ffmpeg.sh:

#!/bin/sh

# Запускаем ffserver
/usr/bin/ffserver;
# Запускаем ffmpeg
/usr/bin/ffmpeg -s 4cif -y -an -r 4 -f mjpeg -i http://127.0.0.1:8081/stream.mjpg http://IP-АДРЕС:8080/feed1.ffm &

stop_ffmpeg.sh:

#!/bin/sh

# Для простоты...8)
killall ffserver;
killall ffmpeg;

5. HTML-код для просмотра:
Смотреть видео мы будем через FLV-плеер, например, Flowplayer.
index.html

<html>
<head>
<title>
Тестовое видео
</title>
<script type="text/javascript" src="swfobject.js"></script>
</head>
</html>
<body>
<div id="mplayer">Movie</div>
<script type="text/javascript">
    var so = new SWFObject('FlowPlayerLight.swf','player','698','600','7');
    so.addVariable("config", "{videoFile: http://IP-АДРЕС:8080/test.flv'', showMenu: false, showFullScreenButton: false, showVolumeSlider: false,
    so.write('mplayer');
</script>
</div>
<body>

FlowPlayerLight.swf можно взять здесь. Библиотеку swfobject.jsздесь.

Можно, конечно, и просто встроить FLV-плеер в HTML-код через Embed и Object.

Очень важное замечание: скорее всего придется поиграться c framerate, bitrate и другими параметрами в ffserver.conf и в скрипте запуска. Мне пришлось долго повозиться, подбирая более менее нормальные значения, поскольку возникали проблемы с проигрыванием потока в FLV-плеере.

6. Теперь все готово к пробному запуску:
Запускаем motion

/etc/init.d/motion start

Запускаем ffserver и ffmpeg

./start_ffmpeg.sh

Открываем в браузере index.html и смотрим, показывается ли изображение с камеры.

В заключение, хочется отметить, что, все-таки, такая схема не является широковещательной. Т.е. каждый подключенный клиент будет «кушать» кусок полосы канала равный битрейту видео. Я пока не разбирался, можно ли организовать таким образом broadcasting или multicasting, поскольку это немного вне моей компетенции…8) Но думаю, что при определенном усилии это можно сделать. Также к недостаткам можно отнести довольно высокий битрейт (сколько я ни пытался, получить видео хотя бы в районе 500 kbit/sec, в нормальном качестве, и приемлемой частотой обновления не получилось).

Ссылки:

  1. http://forum.dlink.ru
  2. http://www.lavrsen.dk/twiki/bin/view/Motion/WebHome
  3. http://ffmpeg.mplayerhq.hu/
  4. http://en.wikipedia.org/wiki/Webcast
  5. http://en.wikipedia.org/wiki/Motion_JPEG
  6. http://www.videolan.org/vlc
  7. http://flowplayer.org
  8. http://blog.deconcept.com/swfobject
 
Просмотров: 29 356 | 8 комментариев  comments 
formats

Потоковое Flash-Video + ClipShare

Опубликовано: 16.05.2008 Автор: в

Один из моих недавних проектов был посвящен проблеме передачи потокового flash-видео.На сайте был установлен ClipShare (кто не знает — это клон популярного видеосервиса YouTube). Необходимо было исправить проблему загрузки файлов и настроить потоковую раздачу через HTTP загруженных видеороликов.

Объясню вкратце, что такое такое «потоковая» раздача flash-видео (HTTP flv streaming). Вообще говоря, передача видеороликов возможна несколькими способами:

  • Как обычный flv-файл, через flash-плеер браузера. При такой передаче файл кэшируется.
  • Как вложение в swf-файле. В этом случае, файл должен быть полностью загружен до начала проигрывания.
  • Прогрессивная загрузка по HTTP (Progressive download via HTTP). К преимуществам этого метода можно отнести буферизацию, использование обычных веб-серверов, возможность использовать один SWF-плеер для проигрывания различных роликов.Передача потока flash-video возможно только при наличии специальных метаданных в файле, описывающих стартовые позиции каждого ключевого кадра видео. Благодаря этому, Flash-плеер может запрашивать и получать любую часть видео до того как буферизация закончится. Другими словами, «перемотка» видеролика возможна без томительного ожидания закачки файла, что согласитесь, очень удобно. Вы наверняка замечали это при просмотре роликов на YouTube.
  • Поток RMTP. Реальная потоковая раздача, используя специализированные серверы, например Flash Media Server, Red5.

Так вот задача была как раз была реализовать 3-ий способ.

К тому же, непонятно почему файлы не загружались на сервер.

Проблема загрузки фалов решилась следующим способом:

Запустив ‘/usr/bin/php /path/to/public_html/convert.php test.mpeg test /path/to/public_html/video/test.mpeg‘, я обнаружил, что mencoder, как раз использующийся для конвертации видеофайла не знает ничего про параметр -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames, что и указало на причину проблемы. Новые версии mencoder больше не поддерживают эту опцию. После того, как я убрал всякие вхождения этого параметра в php-файлах ClipShare (convert.php и upload.php) и заменил еще одну опцию -vop на -vf (чтобы сильно не ругался), аплоад заработал на ура.

Теперь про псевдо-потоковую раздачу видео. На стороне сервера, самым простым способом, является установка веб-сервера lighttpd. Все что нужно, это наличие такого куска в конфигурационном файле lighttpd:

server.modules = ( 
  ...,
  "mod_secdownload", ## optional
  "mod_flv_streaming",
  ...
)
flv-streaming.extensions = ( ".flv" )

К сожалению, в случае ClipShare,модуль загрузки файлов (Uber-Uploader, кстати) вместо отображения текущего процесса загрузки выплевывает ‘Failed To Find Flength File, но файл все-таки загружает. Поэтому я пошел другим путем и решил поставить модуль раздачи flash-видео mod_flvx. Для установки необходимо скачать сам модуль, запустить ‘apxs -i -a -c mod_flvx.c‘ и добавить директиву ‘AddHandler flv-stream .flv‘ в конфиг апача.

Принцип работы этих модулей довольно прост. Они лишь добавляют необходимый заголовок Content-Type и парсят запрос GET а наличие праметра start.Если этот параметр задан, то модуль сначала выдает FLV-заголовок, а затем начинает передавать файл с нужной позиции, заданной этим параметром.

Я уже отметил, что для использования возможности «перемотки» без полной буферизации необходимо наличие определенных метаданных в видеофайле. Для этого используется небольшая, но очень полезная утилитка flvtool2. Для обновления файла необходимо лишь запустить ‘flvtool2 -UP <файл>.flv‘ и после этого файл готов к HTTP-раздаче. В ClipShare при загрузке видеоролика эта утилита запускается, поэтому дополнительных телодвижений производить не надо.

Проделав необходимые манипуляции, и запустив Apachе, я столкнулся с еще одной неприятной проблемой, а именно «корявостью» интегрированного в ClipShare flash-плеера Agriya. «Перемотка» отказывалась работать.

Пришлось интегрировать другой плеер — JW FLV Media Player. Для ClipShare это было сделано следующим образом:

В файле templates/view_video.tpl заменить (не забыв, конечно скачать сам плеер)

<script type="text/javascript">
   var so1 = new SWFObject("/FLVplayer/flvplayer.swf", "flvplayer", "559", "444", "7",  null, true);
   so1.addParam("allowFullScreen", "true");
   so1.addParam("wmode", "transparent");
   so1.addParam("allowSciptAccess", "always");
   so1.addVariable("themes", "/FLVplayer/themes.xml");
   so1.addVariable("config", "/FLVplayer/playerXml.php?flv={$vinfo[0].flvdoname}");
   so1.write("playerDiv");
</script>

на

<script type="text/javascript">
   var so1 = new SWFObject("/FLVplayer/mediaplayer.swf", "flvplayer", "559", "444", "7",  null, true);
   so1.addParam("allowFullScreen", "true");
   so1.addParam("wmode", "transparent");
   so1.addParam("allowSciptAccess", "always");
   so1.addVariable('autostart','true');
   so1.addVariable('file','/flvideo/{$vinfo[0].flvdoname}');
   so1.addVariable('streamscript','lighttpd');
   so1.write("playerDiv");
</script>

Можно, и даже, наверное, нужно генерировать плейлист на лету через PHP, но я с этим играться не стал, поскольку надо было получить просто работающий вариант.

После этого потоковая раздача+»перемотка» заработали на ура.

Ссылки:

  1. http://en.wikipedia.org/wiki/Flash_Video
  2. http://blog.lighttpd.net/articles/2006/03/09/flv-streaming-with-lighttpd
  3. http://inlet-media.de/flvtool2
  4. http://www.jeroenwijering.com/?item=JW_FLV_Player
  5. http://journal.paul.querna.org/articles/2006/07/11/mod_flvx/
  6. http://apachedev.ru/2006/07/13/mod_flvx-peredacha-potokovogo-flash-video/
 
Просмотров: 8 123 | 6 комментариев  comments