Пользователь
0,0
рейтинг
19 декабря 2009 в 07:56

Администрирование → Потоковое видео средствами 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 0
  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>.
Павел @TheRipper
карма
31,7
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (34)

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

              Как будто вы за ffmpeg заплатили, а вас киданули.
            • 0
              Можно задать смещение и размер.
              Если не ошибаюсь нечто вроде этого:
              -s 800x600 -i :0.0+75,30
              А вообще-то гугль на предмет x11grab показывает, что очень многие задаются этим же и похожими вопросами.
              • 0
                Спасибо! Сейчас еще покопаю в эту сторону!
            • 0
              Если Вам ещё интересно, то скажу, что задавать разрешение экрана надо перед -i :0.0, а разрешение, в которое надо преобразовать — после.
      • 0
        И сразу еще один вопрос. Можем ли мы подцепить звук? То есть так же, как и здесь, захватить и видео и звук? И с какой примерной задержкой все будет обрабатываться?
        • +1
          Звук подцепить можно, и синхронизация должна быть, тут как раз ничего сложного. Цепляйте (мультиплексируйте) звук к исходящему потоку на самом последнем этапе кодирования, (если этапов несколько), это должно снизить нагрузку на проц (если это имеет для вас значение) и пользуйтесь UDP, так будет быстрее (ИМХО).
          Задержка обычно бывает от 3 секунд до 3 минут, и сильно зависит от мощностей передающей и принимающей стороны, также зависит от выбранного способа передачи и кодирования. Кроме того в пределах одной сессии она обычно колеблется на +- 10-15%, это уже от канала зависит.
  • 0
    Однако использовать ffserver в промышленных масштабах следует крайне осторожно. Например, установленный битрейт далеко не всегда выдерживается. А если нужно ограничивать по ip-адресам, то там вообще страшный баг — диапазоны неверно сравниваются (а мой патч вроде с августа так и не приняли).
    • 0
      А какую нагрузку может выдержать ffserver на машине с 4гб ОЗУ и 2 ядерным C2D 2,44ггц? И если не ffmpeg, то что вы посоветуете из опен сорс (хотя можно и не опен сорс, но чтобы было бесплатно) использовать для вещания видео с камер в интернет?
      P.S. Сечас передо мной стоит такая задача, а вот оптимального решения найти не могу…
      • 0
        Насчет нагрузки ответить не смогу. Он вообще, насколько я понимаю, сделан в качестве примера того, что можно делать с ffmpeg. Но если стабильное постоянное соединение, то можно и его попробовать — несколько десятков пользователей он выдержать должен.
        А в качестве альтернативы можно предложить VLC, хотя у нас его не получилось использовать, видимо надо «уметь готовить» — в интернете вроде довольно много успешных примеров, и на хабре как-то проскакивало.
        • 0
          Он выдерживает до 5000 соединений на одну машину (потолок). Да и вообще, вполне себе production уровня продукт.
          Все наши стрельбы по нему упирались только в сеть. Да он садится только на одно ядро, но тем не менее этого достаточно. Остальные ядра можно занять под другие процессы.
      • 0
        Это не более чем потешный демонстрационный пример. Если нужо серьёзное промышленное и качественное решение, то варианта два. Допиливать имеющиеся Open source проекты, интегрировать совместно и получать качественное решение. Либо заплатить тем, кто это уже сделал.
  • 0
    Фид-файл можно запихнуть в ОЗУ средствами ffserver?
    • 0
      фид файл лучше в tmpfs класть
  • +1
    Насколько реально в такой схеме обрабатывать на лету поток в 2,5Мбайт(!)/сек, 720*572? Поток в MPEG2, на выходе нужен поток в FLV.
    Я пробовал схему vlc+live+ffmpeg. Постоянные переполнения vbv-буфера(Video Rate Buffer Verifier), а флеш-видео на выходе с артефактами, пропусками кадров и торможениями. Как только ни крутил параметры, ничего не помогло.
    • +1
      У меня реально получилось только 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
        а что мешает написать свой, под свои же требования стример, можно использовать Livemedia библиотеку, у нее лицензия LGPL, там все предельно просто.
        • 0
          тем более что на ffmpeg потратили аж 4 дня, за это время можно было свое сделать
          • 0
            Ну, мне чтобы написать прогу надо сначала вспомнить базовые знания программирования на С под линух, потом изучить интерфейсы нужных либ, а потом сесть писать и отлаживать :).
            То есть явно больше 4-х дней. Кроме того, у меня было ещё чем заниматься при подготовке этой трансляции, кроме как только тестировать ffmpeg.
    • 0
      может 2,5 мегабита? ато если 2.5 мегабайта то это походит на несжатое видео.
      • 0
        было арендовано 5 мегабит в каждую сторону, то есть 5 мегабит полнодуплекс.
  • 0
    а как с windwos обстоят дела? допустим я хочу транслировать видео с вебки, какой мне путь к устройству указывать? где его узнать?
  • 0
    Необязательно запускать ручками два отдельных процесса — ffserver и ffmpeg. Можно в ffserver.conf указать что запускать и оно само это делать будет:
    Launch ffmpeg -s 800x640 -r 30 -f video4linux2 -i /dev/video0

    И относительно проигрывания потокового видео: попробуйте запустить обычный avi — получите ругань, что флеш поддерживает тоько два кодека. А вот если указать каким кодеком выводить — будет работать, но будет жрать процессор.
    <Feed stream0.ffm>
     File /tmp/stream0.ffm
     FileMaxSize 3M
     Launch ffmpeg -s 800x640 -r 30 -f video4linux2 -i /dev/video0
    </Feed>
  • 0
    Покажет список камер которые можно использовать
    sudo v4l2-ctl --list-devices

    Список аудио карт для осуществления записи звука
    sudo arecord -l

    Пример для записи звука без указания канала и с ним
    Launch ffmpeg -s 640x480 -f video4linux2 -i /dev/video0 -r 30 -f alsa -i hw:0,0
    Launch ffmpeg -s 640x480 -f video4linux2 -i /dev/video1 -r 30 -f alsa -ac 1 -i hw:0,0

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