Потоковое видео средствами 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>.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 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?
                        • +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

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