Linux для всех

индекс
247,20

Потоковое видео средствами ffserver & ffmpeg

Для организации трансляции нам потребуется:


  • Linux
  • FFmpeg (включает в себя ffserver)

Теория


FFmpeg — это набор свободных библиотек с открытым исходным кодом, которые позволяют записывать, конвертировать и передавать цифровое аудио и видео в различных форматах. Он включает libavcodec, библиотеку кодирования и декодирования аудио и видео и libavformat, библиотеку мультиплексирования и демультиплексирования в медиаконтейнер. Название происходит от названия экспертной группы MPEG и «FF», означающего «fast forward».

© Wikipedia

ffserver идёт в комплекте с ffmpeg и выполняет роль медиа-сервера — получает видеопоток от ffmpeg, который может быть запущен на другой машине, и раздаёт его счастливым пользователям.
Каждый получаемый поток называется Feed’ом (далее будет просто фид). Таких потоков может быть несколько, так же как и отдаваемых (выходных).
FFmpeg у нас будет захватывать видео с веб-камеры или читать из файла.

Практика


Сначала настроим ffserver, чей конфиг лежит в /etc/ffserver.conf:
  1. Port 8090
  2. BindAddress 0.0.0.0
  3. MaxClients 100
  4. MaxBandwidth 20000
  5. NoDaemon
  6. # Фид, надо запомнить feed.ffm, он нам потребуется при запуске ffmpeg
  7. <Feed feed.ffm>
  8. File /tmp/feed.ffm
  9. FileMaxSize 3M
  10. </Feed>
  11. <Stream test.flv>
  12. # Ранее объявленный фид
  13. Feed feed.ffm
  14. Format flv
  15. VideoCodec flv
  16. VideoFrameRate 30
  17. VideoBufferSize 80000
  18. VideoBitRate 200
  19. # Качество видео от 1 до 31, 1 == отлично 31 == фи!
  20. VideoQMin 1
  21. VideoQMax 5
  22. # Разрешение, везде должно быть одинаково!
  23. VideoSize 352x288
  24. PreRoll 1
  25. # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
  26. Noaudio
  27. </Stream>
  28. # Флешка test.swf для просмотра трансляции
  29. <Stream test.swf>
  30. Feed feed.ffm
  31. # Будет запускаться в Adobe Flash Player
  32. Format swf
  33. VideoCodec flv
  34. VideoFrameRate 30
  35. VideoBufferSize 50000
  36. VideoBitRate 100
  37. VideoQMin 1
  38. VideoQMax 5
  39. # Разрешение, везде должно быть одинаково!
  40. VideoSize 352x288
  41. PreRoll
  42. # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
  43. Noaudio
  44. </Stream>


Пускаем ffserver:
$ ffserver

Пускаем ffmpeg:
$ ffmpeg -s 352x288 -r 30 -f video4linux2 -i /dev/video0 http://localhost:8090/feed.ffm
-s разрешение, указанное в конфиге ffserver, -r количество кадров/секунду, -f формат, -i путь к камере (или к видео-файлу), http://localhost:PORT/FEED это адрес, где ffserver будет ждать наш поток

PS: если выдаст ошибку, то можно попробовать формат v4l (-f video4linux)

Открываем в браузере http://localhost:8090/test.swf и широко улыбаемся:)

Для отправки видео поменяем параметр -i на путь к файлу, уберём -f (ffmpeg сам определит формат файла):
$ ffmpeg -s 352x288 -r 30 -i ~/big_buck_bunny.ogg http://localhost:8090/feed.ffm

Ну а что бы вставить нашу флешку в html-страницу используем следующий код:
<embed src="http://localhost:8090/test.swf" width="550" height="400"></embed>.
+33
19 декабря 2009, 07:56
172

комментарии (32)

+1
alon #
как все просто то оказывается, только вот вопрос: ffmpeg умеет брать видео с IP камеры в mjpeg или mpeg2?
0
TheRipper #
насчёт IP камер не знаю, но форматы mjpeg и mpeg2 он поддерживает
0
arti_kz #
Теоретически может — ведь у камеры обычно есть адрес нужного потока, достаточно скормить его ffmpeg'у. Мы пробовали — даже работало, но все постоянно падало — было подозрение на соединение (поток через wifi брался). Другой вопрос — с каким качеством это все будет конвертироваться…
0
angry_elf #
Вопрос странный. ffmpeg умеет практически все распространённые форматы и большинство малораспространённых. Разумеется, все варианты mpeg (mjpeg тоже) там есть. man ffmpeg, в общем.
0
FFunk #
В 16 строчке, случаем, не «Format swf»?
В комментах конфига ffserver'а нет flv
0
TheRipper #
Нет, именно flv. Это относится к /test.flv, который можно использовать в других плеерах, например, в JWPlayer
0
MYPABEU #
Еще такой вопрос: а можно ли экран потоково отдавать??? Ну Х11 должен же иметь какой-то девайс в /dev/.
Просто тут появляется идея =))
+1
TheRipper #
Да, можно.
ffmpeg -f x11grab -r 30 -s 352x288 -i :0.0 localhost:8090/feed.ffm
PS: если будете менять разрешение, то и в конфиге ffserver не забудьте
0
MYPABEU #
А разрешение рабочего стола в иксах не имеет значения? Ffmpeg сам все сожмет до нужного размера, так?
0
Antigluk #
поэкспериментируйте ;)
0
MYPABEU #
Был несколько разочарован.
Сделал разрешение 320х240 — расчитывал получить нормальный потоковый выход, а получил картинку 320х240 от верхнего левого угла (0,0).
Честно говоря — я был несколько обижен =)
Просто сразу созрела идея как сделать достаточно интересный сервис.
VDS у меня полно. Видимо, придется копать в сторону VNC, но и тут нас ждут некоторые сложности…
+1
Frosty #
>Был несколько разочарован… Честно говоря — я был несколько обижен =)

Как будто вы за ffmpeg заплатили, а вас киданули.
0
deemytch #
Можно задать смещение и размер.
Если не ошибаюсь нечто вроде этого:
-s 800x600 -i :0.0+75,30
А вообще-то гугль на предмет x11grab показывает, что очень многие задаются этим же и похожими вопросами.
0
MYPABEU #
Спасибо! Сейчас еще покопаю в эту сторону!
0
TheRipper #
Если Вам ещё интересно, то скажу, что задавать разрешение экрана надо перед -i :0.0, а разрешение, в которое надо преобразовать — после.
0
MYPABEU #
И сразу еще один вопрос. Можем ли мы подцепить звук? То есть так же, как и здесь, захватить и видео и звук? И с какой примерной задержкой все будет обрабатываться?
+1
deemytch #
Звук подцепить можно, и синхронизация должна быть, тут как раз ничего сложного. Цепляйте (мультиплексируйте) звук к исходящему потоку на самом последнем этапе кодирования, (если этапов несколько), это должно снизить нагрузку на проц (если это имеет для вас значение) и пользуйтесь UDP, так будет быстрее (ИМХО).
Задержка обычно бывает от 3 секунд до 3 минут, и сильно зависит от мощностей передающей и принимающей стороны, также зависит от выбранного способа передачи и кодирования. Кроме того в пределах одной сессии она обычно колеблется на +- 10-15%, это уже от канала зависит.
0
arti_kz #
Однако использовать ffserver в промышленных масштабах следует крайне осторожно. Например, установленный битрейт далеко не всегда выдерживается. А если нужно ограничивать по ip-адресам, то там вообще страшный баг — диапазоны неверно сравниваются (а мой патч вроде с августа так и не приняли).
0
alon #
А какую нагрузку может выдержать ffserver на машине с 4гб ОЗУ и 2 ядерным C2D 2,44ггц? И если не ffmpeg, то что вы посоветуете из опен сорс (хотя можно и не опен сорс, но чтобы было бесплатно) использовать для вещания видео с камер в интернет?
P.S. Сечас передо мной стоит такая задача, а вот оптимального решения найти не могу…
0
arti_kz #
Насчет нагрузки ответить не смогу. Он вообще, насколько я понимаю, сделан в качестве примера того, что можно делать с ffmpeg. Но если стабильное постоянное соединение, то можно и его попробовать — несколько десятков пользователей он выдержать должен.
А в качестве альтернативы можно предложить VLC, хотя у нас его не получилось использовать, видимо надо «уметь готовить» — в интернете вроде довольно много успешных примеров, и на хабре как-то проскакивало.
0
aefimov #
Он выдерживает до 5000 соединений на одну машину (потолок). Да и вообще, вполне себе production уровня продукт.
Все наши стрельбы по нему упирались только в сеть. Да он садится только на одно ядро, но тем не менее этого достаточно. Остальные ядра можно занять под другие процессы.
0
Coolver #
Это не более чем потешный демонстрационный пример. Если нужо серьёзное промышленное и качественное решение, то варианта два. Допиливать имеющиеся Open source проекты, интегрировать совместно и получать качественное решение. Либо заплатить тем, кто это уже сделал.
0
svin0 #
Фид-файл можно запихнуть в ОЗУ средствами ffserver?
0
Ilya_Smelykh #
фид файл лучше в tmpfs класть
+1
kav #
Насколько реально в такой схеме обрабатывать на лету поток в 2,5Мбайт(!)/сек, 720*572? Поток в MPEG2, на выходе нужен поток в FLV.
Я пробовал схему vlc+live+ffmpeg. Постоянные переполнения vbv-буфера(Video Rate Buffer Verifier), а флеш-видео на выходе с артефактами, пропусками кадров и торможениями. Как только ни крутил параметры, ничего не помогло.
+1
deemytch #
У меня реально получилось только ffmpeg2theora -> ice

dvgrab --format raw - | ffmpeg2theora -f dv -x 160 -y 128 -o /dev/stdout - | oggfwd icecast2server 8000 password /odessa.ogv


Всё остальное либо падало, либо не работало. На ffmpeg/ffserver, кстати, убил четыре дня, так и не смог запустить, по документации явно видно, что что-то пропущено, но непонятно где копать, а смотреть исходный код — запалу не хватило.

Также более менее нормально работает VLC, особенно если надо передать поток одному приемнику, но очень чувствителен к сбоям сети.

У меня получилось передать 5-мбитный поток 768*576 точек, 25 к/сек, в theora, при этом упаковкой видео был занят двухъядерный 8200 где-то на 60%. Видео бежало в течение часа. mpeg4 x264 жреть ресурсов меньше, то есть где-то одно ядро, или 50% от общего, но через VLC нас не устраивали регулярные обрывы и необходимость перезапускать и сервер и клиента.

0
Ilya_Smelykh #
а что мешает написать свой, под свои же требования стример, можно использовать Livemedia библиотеку, у нее лицензия LGPL, там все предельно просто.
0
Ilya_Smelykh #
тем более что на ffmpeg потратили аж 4 дня, за это время можно было свое сделать
0
deemytch #
Ну, мне чтобы написать прогу надо сначала вспомнить базовые знания программирования на С под линух, потом изучить интерфейсы нужных либ, а потом сесть писать и отлаживать :).
То есть явно больше 4-х дней. Кроме того, у меня было ещё чем заниматься при подготовке этой трансляции, кроме как только тестировать ffmpeg.
0
Ilya_Smelykh #
может 2,5 мегабита? ато если 2.5 мегабайта то это походит на несжатое видео.
0
deemytch #
было арендовано 5 мегабит в каждую сторону, то есть 5 мегабит полнодуплекс.
0
ixside #
а как с windwos обстоят дела? допустим я хочу транслировать видео с вебки, какой мне путь к устройству указывать? где его узнать?

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