- PVSM.RU - https://www.pvsm.ru -
В апреле прошлого года по сети прокатился пресс-релиз о том, что Apple выкатывает поддержку WebRTC в браузерах Safari для Mac OS и iOS. С момента выхода пресс-релиза скоро пройдет ровно год, как Apple продолжает выкатывать WebRTC для Safari. Ждем.
Однако ждут не все. Кому-то требуется реал-тайм видео в Safari прямо сейчас и в этой статье мы расскажем как обходиться без WebRTC в браузере iOS Safari и Mac OS Safari и чем можно его заменить.
На сегодняшний день нам известны следующие варианты:
Так как мы ищем альтернативу RTC (Real Time Communication), то сравним эти варианты не только по платформам iOS / Mac OS, но и по средней задержке (Latency) в секундах.
iOS | Mac OS | Latency | |
HLS, DASH | Да | Да | 15 |
Flash RTMP | Нет | Да | 3 |
Flash RTMFP | Нет | Да | 1 |
Websockets | Да | Да | 3 |
WebRTC Plugin | Нет | Да | 0.5 |
Как видно из этой таблицы, HLS совсем выпадает из реалтайма со своими 15 и более секундами задержки, хотя и прекрасно работает на обоих платформах.
Несмотря на то, что «Flash умер», он продолжает работать на Mac OS и даёт годную для реалтайма задержку. Но дела у флэша на Safari действительно обстоят не очень. Бывает так, что Flash оказывается попросту отключен.
Тоже самое что и Flash RTMP, с той лишь разницей, что работает по UDP и умеет сбрасывать пакеты, что несомненно лучше для реалтайма. Хорошая задержка. Не работает на iOS.
Некоторая альтернатива для HLS, если нужна сравнительно низкая задержка. Работает в iOS и Mac OS.
В этом случае видеопоток приходит через Websockets (RFC6455), декодируется на уровне JavaScript и отрисовывается на HTML5 canvas с помощью WebGL. Этот способ работает гораздо быстрее HLS, но имеет свои недостатки:
В Mac OS можно установить WebRTC плагин, который реализует WebRTC. Это несомненно дает самую лучшую задержку, но требует скачивания и установки пользователем стороннего программного обеспечения. Можно справедливо заметить, что Adobe Flash Player тоже плагин и тоже может требовать ручной установки, но «мертвый флэш» плагин от Adobe, очевидно, обгоняет Noname WebRTC плагины по распространенности. Кроме этого, WebRTC плагины не работают в iOS Safari.
Если не ограничиваться браузером Safari, можно рассмотреть следующие варианты:
Имплементим iOS приложение с поддержкой WebRTC и получаем низкую задержку и всю мощь WebRTC-технологии. Не браузер. Требует установки из App Store.
Браузер с поддержкой WebRTC под iOS. Говорят, что поддерживает WebRTC, но мы не тестировали. Не очень популярный браузер. Но если есть возможность заставить пользователей им пользоваться, можно попробовать это сделать.
Тоже что и Bowser. Непонятно, насколько хорошо работает с WebRTC. Не популярен на iOS.
Можно подождать внедрение WebRTC от Apple. Прошел уже год. Возможно осталось ждать не так уж и долго. Может у кого-то есть инсайд?
Из таблицы выше видно, что на iOS Safari остается только два варианта: HLS и Websockets. Первый имеет задержку более 15 секунд. Второй имеет свои ограничения и задержку около 3 секунд. Есть еще MPEG DASH, но это тот же HLS / HTTP в плане реалтайма.
В силу перечисленных выше ограничений:
Вебсокеты, конечно же, не могут претендовать на полноценную замену WebRTC в браузере iOS Safari, но позволяют играть реалтайм-потоки прямо сейчас.
В этом случае, схема реалтаймовой трансляции выглядит так:
В качестве сервера используется Web Call Server 5, который поддерживает такую конвертацию и отдает поток на iOS Safari по Websockets. Источником реалтаймового видеопотока может быть вебкамера, которая отправляет видео на сервер или же IP камера, работающая по RTSP.
Так выглядит отправка реалтаймового WebRTC видеопотока на сервер в браузере Google Chrome с десктопа:
А так выглядит воспроизведение этого же видеопотока в реалтайме, в браузере iOS Safari:
Здесь мы в качестве имени видеопотока указали d3c6, т.е. Тот видеопоток, который был отправлен с браузера Chrome по WebRTC.
В случае, если видеопоток забирается с IP-камеры, в iOS Safari это будет выглядеть так:
Как видно из скриншота, в качестве имени видеопотока мы использовали RTSP адрес. Сервер забрал RTSP поток и сконвертировал его в Websockets для iOS Safari.
Исходный код плеера доступен здесь [1]. Однако плеер по ссылке работает не только для iOS Safari. Он может переключаться между тремя технологиями: WebRTC, Flash, Websockets в порядке приоритета и содержит немного больше кода, чем требуется для воспроизведения в iOS Safari.
Попробуем минимизировать код плеера чтобы продемонстрировать минимальную конфигурацию, которая будет играть в iOS Safari
Минимальный код HTML-страницы будет выглядеть так: player-ios-safari.html
<html>
<head>
<script language="javascript" src="flashphoner.js"></script>
<script language="javascript" src="player-ios-safari.js"></script>
</head>
<body onLoad="init_page()">
<h1>The player</h1>
<div id="remoteVideo" style="width:320px;height:240px;border: 1px solid"></div>
<input type="button" value="start" onClick="start()"/>
<p id="status"></p>
</body>
</html>
Из этого кода видно, что главный элемент на странице — это div-блок
<div id="remoteVideo" style="width:320px;height:240px;border: 1px solid"></div>
Именно этот блок будет отвечать за воспроизведении видео, после того как скрипты API вставят туда HTML5 Canvas.
Далее идет скрипт плеера. Объем скрипта: 80 строк: player-ios-safari.js
var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
var remoteVideo;
var stream;
function init_page() {
//init api
try {
Flashphoner.init({
receiverLocation: '../../dependencies/websocket-player/WSReceiver2.js',
decoderLocation: '../../dependencies/websocket-player/video-worker2.js'
});
} catch(e) {
return;
}
//video display
remoteVideo = document.getElementById("remoteVideo");
onStopped();
}
function onStarted(stream) {
//on playback start
}
function onStopped() {
//on playback stop
}
function start() {
Flashphoner.playFirstSound();
var url = "wss://wcs5-eu.flashphoner.com:8443";
//create session
console.log("Create new session with url " + url);
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
playStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});
}
function playStream(session) {
var streamName = "12345";
var options = {
name: streamName,
display: remoteVideo
};
options.playWidth = 640;
options.playHeight = 480;
stream = session.createStream(options).on(STREAM_STATUS.PLAYING, function(stream) {
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.STOPPED, function() {
setStatus(STREAM_STATUS.STOPPED);
onStopped();
}).on(STREAM_STATUS.FAILED, function() {
setStatus(STREAM_STATUS.FAILED);
onStopped();
});
stream.play();
}
//show connection or remote stream status
function setStatus(status) {
//display stream status
}
К наиболее важным частям этого скрипта можно отнести инициализацию API
Flashphoner.init({
receiverLocation: '../../dependencies/websocket-player/WSReceiver2.js',
decoderLocation: '../../dependencies/websocket-player/video-worker2.js'
});
При инициализации подгружается еще два скрипта:
Эти скрипты являются ядром вебсокет плеера. Первый отвечает за доставку видеопотока, а второй за его обработку. Скрипты flashphoner.js, WSReceiver2.js и video-worker2.js доступны для скачивания в сборке Web SDK [2] для Web Call Server и обязательно должны быть подключены для воспроизведения потока в iOS Safari.
Таким образом имеем следующие обязательные скрипты:
Установка соединения с сервером происходит с помощью следующего кода:
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
playStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
onStopped();
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
onStopped();
});
}
Непосредственно воспроизведение видеопотока осуществляется с помощью метода API createStream().play(). При воспроизведении видеопотока в div-элемент remoteVideo будет встроен HTML-элемент Canvas, в котором будет происходить рендеринг видеопотока.
function playStream(session) {
var streamName = "12345";
var options = {
name: streamName,
display: remoteVideo
};
options.playWidth = 640;
options.playHeight = 480;
stream = session.createStream(options).on(STREAM_STATUS.PLAYING, function(stream) {
setStatus(stream.status());
onStarted(stream);
}).on(STREAM_STATUS.STOPPED, function() {
setStatus(STREAM_STATUS.STOPPED);
onStopped();
}).on(STREAM_STATUS.FAILED, function() {
setStatus(STREAM_STATUS.FAILED);
onStopped();
});
stream.play();
}
Мы захардкодили в коде две вещи:
1) Урл сервера
var url = "wss://wcs5-eu.flashphoner.com:8443";
Это публичный демо-сервер Web Call Server 5. Если с ним что-то не так, вам нужно установить свой [3] для тестирования.
2) Название потока для воспроизведения
var streamName = "12345";
Это название видеопотока, который мы воспроизводим. В случае, если это поток с RTSP IP-камеры, его можно прописать так
var streamName = "rtsp://host:554/stream.sdp";
Самая неприметная, но очень важная функция:
Flashphoner.playFirstSound();
На мобильных платформах, в частности на iOS Safari есть ограничение Web Audio API, которое не дает проигрывать звук из динамиков до тех пор, пока пользователь не щелкнет пальцем по какому-либо элементу web-страницы. Поэтому при нажатии кнопки Start мы вызываем метод playFirstSound(), который играет короткий кусок сгенерированного аудио, чтобы видео в итоге могло играть с аудио.
В конечном итоге наш кастомный минимальный плеер, состоящий из четырех скриптов и одного HTML файла player-ios-safari.html выглядит так:
Скачать исходный код плеера можно здесь [4].
Таким образом, мы рассказали о текущих альтернативах WebRTC для iOS Safari и разобрали пример с реалтайм-плеером с передачей видео по технологии Websockets. Возможно он поможет кому-то дождаться прихода WebRTC на Safari.
Пресс-релиз [5] — Apple выкатывает WebRTC для Safari
Websockets [6] — RFC6455
WebGL [7] — спецификация
Web Call Server [8] — WebRTC-сервер, который может конвертировать поток в Websockets для воспроизведения на iOS Safari
Установка WCS [3] — скачать и установить
Запуск на Amazon EC2 [9] — запуск готового образа сервера на Amazon AWS
Исходный код [4] — пример плеера: player-ios-safari.js и player-ios-safari.html
Web SDK [2] — web API для сервера WCS, содержащее скрипты flashphoner.js, WSReceiver2.js, video-worker2.js
Автор: Flashphoner
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/252147
Ссылки в тексте:
[1] здесь: https://github.com/flashphoner/flashphoner_client/tree/wcs_api-2.0/examples/demo/streaming/player
[2] Web SDK: https://flashphoner.com/wcs-web-sdk
[3] установить свой: https://flashphoner.com/download
[4] здесь: http://flashphoner.com/downloads/examples/player-ios-safari-0.5.18.1977-5.0.2156.zip
[5] Пресс-релиз: https://www.theregister.co.uk/2016/04/13/apple_rolling_webrtc_into_webkit/
[6] Websockets: https://tools.ietf.org/html/rfc6455
[7] WebGL: https://www.khronos.org/registry/webgl/specs/1.0/
[8] Web Call Server: https://flashphoner.com
[9] Запуск на Amazon EC2: https://aws.amazon.com/marketplace/pp/B01D1L5EAK
[10] Источник: https://habrahabr.ru/post/325978/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.