Есть 10 пользователей, которые стримят видео с веб-камеры по WebRTC. Нужно вывести снапшоты (thumbnails) их стримов на одной веб-странице, чтобы выглядело примерно так:


Можно просто воспроизвести видео вместо картинок, но давайте посчитаем каким будет битрейт, если каждый из потоков занимает 1 Mbps полосы. Если воспроизводить все десять, получится 10 Mbps. Не многовато для превьюшек?

Гораздо лучше было бы запросить у сервера кадр из видеопотока, получить его в виде PNG и показать картинку в браузере.


Сначала мы реализовали загрузку PNG-картинки по запросу:

  1. Делаем асинхронный запрос:

    stream.snapshot();

  2. Сервер сохраняет картинку в файловой системе.
  3. Пользователь, который запрашивал снапшот получает URL картинки и может его вставить картинку HTML тэгом:

    <img src="{url}"/>

Такой вариант работал, но чем-то нам не понравился. Возможно тем, что пришлось бы хранить картинки у себя на сервере или придумывать их выгрузку на Nginx или Apache для последующей статической раздачи.

В результате, решили заворачивать PNG в Base64 и отправлять клиенту снапшот в таком виде. При таком подходе файлы не раздаются с сервера по http. PNG контент файла формируется и передается на клиента по Websockets в момент запроса.

Пошаговое описание процесса с кусками JavaScript кода:

1. Alice отправляет видеопоток с веб-камеры на сервер по WebRTC и называет поток stream1.

session.createStream({name:"stream1"}).publish()

2. Bob, зная название потока может запросить снапшот следующим способом:

var stream = session.createStream({name:"stream1"});
stream.snapshot();

Для того, чтобы получить снапшот, Bob вешает листенер STREAM_STATUS.SNAPSHOT_COMPLETE, который вставляет Base64 картинку в элемент , расположенный на странице:

stream.on(STREAM_STATUS.SNAPSHOT_COMPLETE, function(stream){
	snapshotImg.src = "data:image/png;base64,"+stream.getInfo();
}

Полный код примера со снапшотами доступен здесь.

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


На стороне сервера, для получения снапшота, требуется декодирование видеопотока. Входящий WebRTC поток депакетизируется, декодируется и в этой точке становится возможным делать его снимки. Схема с декодированием и с нормальным воспроизведением выглядит так:


Для нормального воспроизведения потоки не декодируются и попадают к зрителю как есть. Если требуется снапшот, он берется с той ветки видеопотока, которая зашла на декодинг.

При работе со снапшотами используется WebRTC-сервер Web Call Server 5 и Web SDK, которое дает JavaScript API для работы со снапшотами онлайн трансляции.
Поделиться с друзьями
-->

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


  1. caway
    25.05.2017 11:47

    PNG, как бы, не лучший вариант для кадров.
    Почему не JPG!?


    1. Enverest
      25.05.2017 12:50

      PNG можно легко заменить на APNG — Firefox поддерживает и Chrome на подходе.


  1. flashphoner
    25.05.2017 11:58

    Почему не JPG!?

    Как обычно, потому что снапшоты надо было еще вчера. А под рукой уже были инструменты для сжатия в PNG.

    А по хорошему, да. Придется и JPEG превью сделать.

    image


  1. T-362
    25.05.2017 12:46

    Мне что больше интересно — картинки с кроликом, постоянно в примерах всяких плееров, это вообще какой-то реальный мультик или визуальный lorem ipsum?


    1. flashphoner
      25.05.2017 12:53

      Это реальный мультик и визуальный lorem ipsum для видео.
      Big Buck Bunny


      1. T-362
        25.05.2017 13:08

        А, теперь понятно — мультик под CC 3.0, надо бы глянуть.


        1. JIghtuse
          25.05.2017 18:09

          Один из числа мультфильмов, созданных открытыми инструментами — Blender, GIMP, Inkscape, etc (Open Movies). Исходные материалы тоже доступны, насколько помню (3D-модели и прочее).
          https://www.youtube.com/watch?v=mN0zPOpADL4&list=PL6B3937A5D230E335


  1. Optimus_990
    30.05.2017 09:14

    Хорошее описание, а мульт помню, крутой!