...
7. Графики chrome://webrtc-internals для второго потока:
Воспроизведение потока по WebRTC в стороннем плеере
Поток, опубликованный на WCS сервере, можно воспроизвести по WebRTC в стороннем плеере, например, в VR-плеере. Для этого видеоэлемент страницы, в котором будет воспроизводиться поток, передается параметром remoteVideo
в функцию WebSDK session.createStream()
session.ceateStream() код
Code Block | ||||
---|---|---|---|---|
| ||||
session.createStream({
name: document.getElementById('playStream').value,
display: display,
remoteVideo: video
})
... |
Тестирование
1. Для теста возьмем:
- WCS сервер
- веб-приложение Two Way Streaming для публикации потока
- VR-плеер Delight для воспроизведения потока
2. Публикуем поток на WCS сервере
3. Воспроизводим поток в VR-плеере
Пример кода страницы с плеером
1. Объявление видеоэлемента для воспроизведения потока, поля ввода имени потока и кнопок запуска и остановки воспроизведения
Автозапуск воспроизведения
Примеры Player и Embed Player поддерживают автозапуск воспроизведения при помощи параметра
Code Block | ||
---|---|---|
| ||
autoplay=true |
например
Code Block | ||
---|---|---|
| ||
https://hostname:8888/embed_player?urlServer=wss://hostname:8443&streamName=stream1&autoplay=true&mediaProviders=WebRTC |
Здесь
- hostname - имя WCS-сервера
- stream1 - имя потока на сервере
Особенности автозапуска воспроизведения в браузерах
Chrome
В последних версиях браузера Chrome (71 и выше) была изменена политика автозапуска воспроизведения контента на веб-страницах. Теперь для запуска воспроизведения видео необходимо, чтобы пользователь совершил какое-либо действие, например, нажатие на кнопку.
Это изменение влияет на создание аудиоконтекста, который необходим, чтобы работала регулировка громкости. Согласно новой политике, создание аудиоконтекста также требует действия от пользователя.
В связи с этим, в Chrome 71, а также в других браузерах на базе Chromium, поддерживающих изменение политики автозапуска, видео при автозапуске может проигрываться без звука. Для того, чтобы включить звук, пользователь должен переместить регулятор громкости в окне Embed Player.
Существует способ обойти данное ограничение, не требующий действий от пользователя. Для этого необходимо на веб-страницу плеера добавить код
Code Block | ||||
---|---|---|---|---|
| ||||
<iframe <div style="width: 50%;src="silence.mp3" allow="autoplay" id="displayaudio"> <dl8-live-video id="remoteVideo" format="STEREO_TERPON"> <source> </dl8-live-video> </div> <input class="form-control" type="text" id="playStream" placeholder="Stream Name"> <button id="playBtn" type="button" class="btn btn-default" disabled>Play</button> <button id="stopBtn" type="button" class="btn btn-default" disabled>Stop</button> |
2. Обработка события готовности плеера к воспроизведению
Code Block | ||||
---|---|---|---|---|
| ||||
document.addEventListener('x-dl8-evt-ready', function () {
dl8video = document.getElementById('remoteVideo');
$('#playBtn').prop('disabled', false).click(function() {
playStream();
});
}); |
3. Установка соединения с сервером и создание потока
Code Block | ||||
---|---|---|---|---|
| ||||
var video = dl8video.contentElement;
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) {
var session = Flashphoner.getSessions()[0];
session.createStream({
name: document.getElementById('playStream').value,
display: display,
remoteVideo: video
}).on(STREAM_STATUS.PLAYING, function (stream) {
...
}).play();
}) |
4. Запуск воспроизведения в VR-плеере и обработка нажатия кнопки остановки воспроизведения
Code Block | ||||
---|---|---|---|---|
| ||||
...
}).on(STREAM_STATUS.PLAYING, function (stream) {
dl8video.start();
$('#stopBtn').prop('disabled', false).click(function() {
$('#playBtn').prop('disabled', false);
$('#stopBtn').prop('disabled', true);
stream.stop();
dl8video.exit();
});
}).play();
}) |
Полный код примера страницы с VR-плеером
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<!DOCTYPE html> <html> <head> <title>WebRTC Delight</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script type="text/javascript" src="../../../../flashphoner.js"></script> <script type="text/javascript" src="../../dependencies/jquery/jquery-1.12.0.js"></script> <script type="text/javascript" src="../../dependencies/js/utils.js"></script> <script src="dl8-66b250447635476d123a44a391c80b09887e831e.js" async></script> style="display:none"></iframe> |
и разместить в одном каталоге со страницей файл silence.mp3, содержащий 0.25 секунды тишины.
В этом случае при загрузке страницы будет воспроизведена тишина, после чего можно будет создавать аудиоконтекст и играть видео со звуком.
iOS Safari
Автозапуск воспроизведения работает, начиная с iOS 12.2. При этом политика автозапуска, как и в Chrome, требует, чтобы пользователь переместил регулятор громкости для воспроизведения звука.
В версиях iOS 12.2-12.3 звук может не начать воспроизводиться и при движении регулятора громкости. В таких случаях необходимо повторно запустить воспроизведение видео, не обновляя страницу.
При включенном Low Power Mode автозапуск воспроизведения в iOS Safari не работает.
Тонкая настройка воспроизведения звука в iOS Safari
В случае воспроизведения и последующей публикации видео на одной странице (например, видеочат) в iOS Safari уровень звука для проигрываемого потока может меняться. Избежать этого можно двумя способами:
1. Запрашивать доступ к медиаустройствам при создании сессии перед проигрыванием
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) { ... if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") { Flashphoner.playFirstVideo(localVideo, true, PRELOADER_URL).then(function () { Flashphoner.getMediaAccess(null, localVideo).then(function (disp) { <meta name="dl8-custom-format" content='{"name": "STEREO_TERPON","base":"STEREO_MESH","params":{"uri": "03198702.json"}}'> }); </head> <body>}); } <div style="width: 50%;" id="display"> ... }); |
2. Через 1-1.5 секунды после получения статуса потока PLAYING, отключить и снова включить звук и/или видео
Code Block | ||||
---|---|---|---|---|
| ||||
session.createStream({ <dl8-live-video id="remoteVideo" format="STEREO_TERPON">name: streamName, display: remoteVideo <source> }).on(STREAM_STATUS.PENDING, function (stream) { </dl8-live-video>... }).on(STREAM_STATUS.PLAYING, function (stream) </div> <input class="form-control" type="text" id="playStream" placeholder="Stream Name"> <button id="playBtn" type="button" class="btn btn-default" disabled>Play</button> <button id="stopBtn" type="button" class="btn btn-default" disabled>Stop</button> { setStatus("#playStatus", stream.status()); onPlaying(stream); <script> Flashphoner.init({flashMediaProviderSwfLocation: '../../../../media-provider.swf'}); var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS; var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS; var STREAM_STATUS_INFO = Flashphoner.constants.STREAM_STATUS_INFO; var playBtn = document.getElementById('playBtn'); var display = document.getElementById('display'); var dl8video = null; var url = setURL(); if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") { setTimeout(function () { muteVideo(); document.addEventListener('x-dl8-evt-ready', function () { dl8video = document.getElementById('remoteVideo'); $('#playBtn').prop('disabled', false).click(function() { playStream(); }); unmuteVideo(); }, 1500); } }); function playStream() { $('#playBtn').prop('disabled', true); $('#stopBtn').prop('disabled', false); var video = dl8video.contentElement; Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) { var session = Flashphoner.getSessions()[0]; session.createStream({ name: document.getElementById('playStream').value, display: display, remoteVideo: video }).on(STREAM_STATUS.PLAYING, function (stream) { dl8video.start(); $('#stopBtn').prop('disabled', false).click(function() { $('#playBtn').prop('disabled', false); $('#stopBtn').prop('disabled', true); stream.stop(); dl8video.exit(); }); }).play(); }) } </script> </body> </html> |
Известные проблемы
1. Возможный баг в браузере Safari на iOS приводит к фризам при воспроизведении WebRTC
Симптомы: останавливается воспроизведение видео, звуковая дорожка при этом может продолжать играть, для восстановления требуется перезагрузка страницы либо перезапуск браузера.
...
...
}).play(); |
Известные проблемы
1. Возможный баг в браузере Safari на iOS приводит к фризам при воспроизведении WebRTC
Симптомы: останавливается воспроизведение видео, звуковая дорожка при этом может продолжать играть, для восстановления требуется перезагрузка страницы либо перезапуск браузера.
Решение:
а) включить транскодер на сервере, указав в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
disable_streaming_proxy=true |
б) при воспроизведении потока с iOS Safari явно указать ширину и высоту, например:
Code Block | ||||
---|---|---|---|---|
| ||||
session.createStream({constraints:{audio:true,video:{width:320,height:240}}}).play(); |
2. При публикации потока по RTMP и воспроизведении в браузере по WebRTC вместо аудиокодека Opus используется PCMU
Симптомы: в chrome://webrtc-internals отображается кодек PCMU
Решение: отключить алгоритм избегания транскодинга (Avoid Transcoding Alhorithm) при помощи опции в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
disable_rtc_avoid_transcoding_alg=true |
3. При публикации потока при помощи Flash Streaming, воспроизведении этого потока в iOS Safari по WebRTC и одновременной публикации потока по WebRTC из Safari перестает воспроизводиться звук.
Симптомы:
а) Публикация потока stream1 из приложения Flash Streaming в браузере Chrome под Windows
б) Воспроизведение потока stream1 на iOS Safari в приложении Two Way Streaming. Звук и видео воспроизводятся нормально.
в) Публикация потока из iOS Safari в приложении Two Way Streaming. Воспроизведение звука пропадает.
г) Остановка публикации в iOS Safari. Воспроизведение звука восстанавливается.
Решение: отключить алгоритм избегания транскодинга (Avoid Transcoding Alhorithm) на сервере при помощи опции в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
disable_rtc_avoid_transcoding_alg=true |
4. При публикации потока по RTMP и отключении Keep Alive для всех протоколов воспроизведение в браузере по WebRTC останавливается по истечению WebSocket-таймаута
Симптомы: при публикации потока по RTMP воспроизведение в браузере по WebRTC останавливается без явного указания ошибки
Решение: если Keep Alive отключен для всех протоколов при помощи настройки в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
keep_alive.algorithm=NONE |
необходимо также отключить таймаут на чтение WebSocket настройкой
Code Block | ||||
---|---|---|---|---|
| ||||
disable_streaming_proxy=true |
б) при воспроизведении потока с iOS Safari явно указать ширину и высоту, например:
Code Block | ||||
---|---|---|---|---|
| ||||
session.createStream({constraints:{audio:true,video:{width:320,height:240}}}).play(); |
2. При публикации потока по RTMP и воспроизведении в браузере по WebRTC вместо аудиокодека Opus используется PCMU
Симптомы: в chrome://webrtc-internals отображается кодек PCMU
Решение: отключить алгоритм избегания транскодинга (Avoid Transcoding Alhorithm) при помощи опции в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
disable_rtc_avoid_transcoding_alg=true |
3. При публикации потока при помощи Flash Streaming, воспроизведении этого потока в iOS Safari по WebRTC и одновременной публикации потока по WebRTC из Safari перестает воспроизводиться звук.
Симптомы:
а) Публикация потока stream1 из приложения Flash Streaming в браузере Chrome под Windows
б) Воспроизведение потока stream1 на iOS Safari в приложении Two Way Streaming. Звук и видео воспроизводятся нормально.
в) Публикация потока из iOS Safari в приложении Two Way Streaming. Воспроизведение звука пропадает.
г) Остановка публикации в iOS Safari. Воспроизведение звука восстанавливается.
Решение: отключить алгоритм избегания транскодинга (Avoid Transcoding Alhorithm) на сервере при помощи опции в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
disable_rtc_avoid_transcoding_alg=true |
4. При публикации потока по RTMP и отключении Keep Alive для всех протоколов воспроизведение в браузере по WebRTC останавливается по истечению WebSocket-таймаута
Симптомы: при публикации потока по RTMP воспроизведение в браузере по WebRTC останавливается без явного указания ошибки
Решение: если Keep Alive отключен для всех протоколов при помощи настройки в файле flashphoner.properties
Code Block | ||||
---|---|---|---|---|
| ||||
keep_alive.algorithm=NONE |
необходимо также отключить таймаут на чтение WebSocket настройкой
Code Block | ||||
---|---|---|---|---|
| ||||
ws_read_socket_timeout=falsews_read_socket_timeout=false |
5. Кодек G722 не работает в браузере Edge
Симптомы: поток со звуком G722 не воспроизводится в браузере Edge или воспроизводится без звука, с фризами
Решение: использовать другой кодек или другой браузер. В случае, если использование другого браузера невозможно, исключить кодек G722 при помощи настройки
Code Block | ||
---|---|---|
| ||
codecs_exclude_streaming=g722,telephone-event |
6. Некоторые браузеры, основанные на Chromium, например Opera, Yandex, в зависимости от версии и ОС не поддерживают кодек H264
Симптомы: не работает публикация, не работает воспроизведение частично (только звук) или полностью при трансляции WebRTC потока H264
Решение: разрешить поддержку vp8 на стороне сервера
Code Block | ||
---|---|---|
| ||
codecs=opus,...,h264,vp8,... |
исключить H264 для трансляции или воспроизведения на стороне клиента
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream = session.createStream({
...
stripCodecs: "h264,H264"
}).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
...
});
publishStream.publish(); |
Необходимо отметить, что при трансляции H264 потока и воспроизведении его как VP8 на сервере включается транскодинг.
7. Если в настройках браузера Chrome 71 и выше для сайта разрешен Flash, при воспроизведении по WebRTC в консоль браузера может выводиться ошибка "Cross-origin content must have visible size large than 400 x 300 pixels, or it will be blocked"
Симптомы: при воспроизведении по WebRTC в консоль браузера Chrome выводится сообщение "Cross-origin content must have visible size large than 400 x 300 pixels, or it will be blocked", при этом воспроизведение работает
Решение: использовать WebSDK без поддержки Flash
Code Block | ||
---|---|---|
| ||
flashphoner-no-flash.js |