Есть 10 пользователей, которые стримят видео с веб-камеры по WebRTC. Нужно вывести снапшоты (thumbnails) их стримов на одной веб-странице.
Можно просто воспроизвести видео вместо картинок, но давайте посчитаем каким будет битрейт, если каждый из потоков занимает 1 Mbps полосы. Если воспроизводить все десять, получится 10 Mbps. Не многовато для превьюшек?
Гораздо лучше было бы запросить у сервера кадр из видеопотока, получить его в виде PNG и показать картинку в браузере.
Сначала мы реализовали загрузку PNG-картинки по запросу.
- Делаем асинхронный запрос stream.snapshot()
- Сервер сохраняет картинку в файловой системе.
- Пользователь, который запрашивал снапшот получает ссылку на картинку по http и может его вставить HTML тэгом
Такой вариант работал, но чем-то нам не нравился. Возможно тем, что пришлось бы хранить картинки у себя на сервере или придумывать их выгрузку на Nginx или Apache для последующей статической раздачи.
В результате, решили заворачивать PNG в Base64 и отправлять клиенту снапшот в таком виде. При таком подходе файлы не раздаются с сервера по http. Контент файла передается на клиента по Websockets.
Пошаговое описание процесса с кусками JavaScript кода
1. Alice отправляет видеопоток с веб-камеры на сервер по WebRTC и называет поток stream1.
session.createStream({name:"stream1"}).publish()
2. Bob, зная название потока может запросить снапшот следующим способом:
var stream = session.createStream({name:"stream1"}); stream.snapshot();
Для того, чтобы получить снапшот, Bob вешает листенер, который вставляет Base64 картинку в элемент , расположенный на странице:
stream.on(STREAM_STATUS.SNAPSHOT_COMPLETE, function(stream){ snapshotImg.src = "data:image/png;base64,"+stream.getInfo(); }
Полный код примера со снапшотами доступен здесь.
В этом примере можно отправить видеопоток на сервер, а потом забрать с этого видеопотока снапшоты, периодически нажимая на кнопку Take. Разумеется, при желании, можно это автоматизировать, написав соответствующий скрипт, который будет снимать снапшоты с потоков, к примеру, раз в минуту.
На стороне сервера, для получения снапшота, требуется декодирование видеопотока. Входящий WebRTC поток депакетизируется, декодируется и в этой точке становится возможным делать его снимки. Схема с декодированием и с нормальным воспроизведением выглядит так:
Для нормального воспроизведения потоки не декодируются и попадают к зрителю как есть. Если требуется снапшот, он берется с той ветки видеопотока, которая зашла на декодирование.
При работе со снапшотами используется WebRTC-сервер Web Call Server 5.