C другого WCS сервера по WebRTC¶
Описание¶
WCS может по требованию захватывать WebRTC-видеопоток, раздаваемый с другого WCS-сервера. Захваченный поток может раздаваться на любые из поддерживаемых платформ, по любой из поддерживаемых технологий. Для управления захватом WebRTC-потока используется REST API.
Схема работы¶
- Браузер соединяется с сервером WCS1 по протоколу Websocket и отправляет команду
publishStream
. - Браузер захватывает микрофон и камеру и отправляет WebRTC поток на сервер.
- REST-клиент отправляет на сервер WCS2 запрос
/pull/pull
. - WCS2 запрашивает поток с WCS1.
- WCS2 получает WebRTC поток с WCS1.
- Второй браузер устанавливает соединение c сервером WCS2 по Websocket и отправляет команду
playStream
. - Второй браузер получает WebRTC поток и воспроизводит этот поток на странице.
REST API¶
REST-запрос должен быть HTTP/HTTPS POST запросом в таком виде:
- HTTP:
http://test.flashphoner.com:8081/rest-api/pull/pull
- HTTPS:
https://test.flashphoner.com:8444/rest-api/pull/pull
Здесь:
test.flashphoner.com
- адрес WCS-сервера8081
- стандартный REST / HTTP порт WCS-сервера8444
- стандартный HTTPS портrest-api
- обязательная часть URL/pull/pull
- используемый REST-метод
REST-методы и статусы ответа¶
/pull/pull¶
Извлечь WebRTC-поток по указанному URL
Request example¶
POST /rest-api/pull/pull HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"uri":"wss://demo.flashphoner.com:8443",
"localStreamName": "testStream",
"remoteStreamName": "testStream"
}
Response example¶
Return codes¶
Code | Reason |
---|---|
200 | OK |
404 | Not found |
409 | Conflict |
500 | Internal error |
/pull/find_all¶
Найти все извлеченные WebRTC-потоки
Request example¶
Response example¶
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
[
{
"localMediaSessionId": "5a072377-73c1-4caf-abd3",
"remoteMediaSessionId": null,
"localStreamName": "testStream",
"remoteStreamName": "testStream",
"uri": "wss://demo.flashphoner.com:8443",
"status": "NEW"
}
]
Return codes¶
Code | Reason |
---|---|
200 | OK |
404 | Not found |
500 | Internal error |
/pull/terminate¶
Завершить извлеченный WebRTC-поток
Request example¶
POST /rest-api/pull/find_all HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"uri":"wss://demo.flashphoner.com:8443",
"localStreamName": "testStream",
"remoteStreamName": "testStream"
}
Response example¶
Return codes¶
Code | Reason |
---|---|
200 | OK |
404 | Not found |
500 | Internal error |
Параметры¶
Параметр | Описание | Пример |
---|---|---|
uri | Websocket URL WCS-сервера |
wss://demo.flashphoner.com:8443
|
localMediaSessionId | Идентификатор медиасессии |
5a072377-73c1-4caf-abd3
|
remoteMediaSessionId | Идентификатор медиасессии на другом сервере |
12345678-abcd-dead-beaf
|
localStreamName | Локальное имя, присвоенное захваченному потоку. По данному имени поток может быть запрошен с WCS сервера |
testStream
|
remoteStreamName | Имя захватываемого потока на другом сервере |
testStream
|
status | Текущий статус потока |
NEW
|
Настройка¶
По умолчанию, захват потока производится по незащищенному соединению, т.е. URL WCS-сервера должен задаваться в виде ws://demo.flashphoner.com:8080
. Чтобы использовать Secure Websocket, необходимо в файле настроек flashphoner.properties указать параметр
Изменения в настройку должны быть внесены на обоих WCS-серверах: том, который публикует поток, и том, который этот поток захватывает.
Краткое руководство по тестированию¶
- Для теста используем:
- два WCS-сервера;
- браузер Chrome и REST-клиент для отправки запросов на сервер;
- веб-приложение Two Way Streaming для публикации потока;
-
веб-приложение Player для воспроизведения захваченного потока в браузере.
-
Откройте веб-приложение Two Way Streaming, опубликуйте поток на первом сервере
-
Откройте REST-клиент. Отправьте на второй сервер запрос
/pull/pull
, указав в параметрах: - URL WCS-сервера, с которого будет захватываться поток;
- имя потока, опубликованного на сервере;
-
локальное имя потока
-
Убедитесь, что поток захвачен сервером. Для этого отправьте запрос
/pull/find_all
:
-
Откройте веб-приложение Player на втором сервере, укажите в поле
Stream
локальное имя потока, нажмитеStart
Последовательность выполнения операций¶
Ниже описана последовательность вызовов при использовании примера Two Way Streaming для публикации потока на одном WCS сервере и Player для воспроизведения потока на другом WCS сервере
-
Установка соединения с сервером
Flashphoner.createSession()
code
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) { setStatus("#connectStatus", session.status()); onConnected(session); }).on(SESSION_STATUS.DISCONNECTED, function () { setStatus("#connectStatus", SESSION_STATUS.DISCONNECTED); onDisconnected(); }).on(SESSION_STATUS.FAILED, function () { setStatus("#connectStatus", SESSION_STATUS.FAILED); onDisconnected(); });
-
Получение от сервера события, подтверждающего успешное соединение
SESSION_STATUS.ESTABLISHED
code
-
Публикация потока
Stream.publish()
code
-
Получение от сервера события, подтверждающего успешную публикацию потока
STREAM_STATUS.PUBLISHING
code
session.createStream({ name: streamName, display: localVideo, cacheLocalResources: true, receiveVideo: false, receiveAudio: false }).on(STREAM_STATUS.PUBLISHING, function (stream) { setStatus("#publishStatus", STREAM_STATUS.PUBLISHING); onPublishing(stream); }).on(STREAM_STATUS.UNPUBLISHED, function () { ... }).on(STREAM_STATUS.FAILED, function () { ... }).publish();
-
Отправка потока по WebRTC на первый сервер
-
Отправка REST-запроса
/pull/pull
на второй сервер -
Запрос потока с первого сервера
-
Отправка потока по WebRTC на второй сервер
-
Установка соединения со вторым сервером
Flashphoner.createSession()
code
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(); });
-
Получение от сервера события, подтверждающего успешное соединение
SESSION_STATUS.ESTABLISHED
code
-
Запрос на воспроизведение потока
Stream.play()
code
stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) { var video = document.getElementById(stream.id()); if (!video.hasListeners) { video.hasListeners = true; video.addEventListener('playing', function () { $("#preloader").hide(); }); video.addEventListener('resize', function (event) { var streamResolution = stream.videoResolution(); if (Object.keys(streamResolution).length === 0) { resizeVideo(event.target); } else { // Change aspect ratio to prevent video stretching var ratio = streamResolution.width / streamResolution.height; var newHeight = Math.floor(options.playWidth / ratio); resizeVideo(event.target, options.playWidth, newHeight); } }); } ... }); stream.play();
-
Получение от сервера события, подтверждающего успешный захват и проигрывание потока
STREAM_STATUS.PLAYING
code
stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) { ... }).on(STREAM_STATUS.PLAYING, function(stream) { $("#preloader").show(); setStatus(stream.status()); onStarted(stream); }).on(STREAM_STATUS.STOPPED, function() { ... }).on(STREAM_STATUS.FAILED, function(stream) { ... }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){ ... }); stream.play();
-
Отправка потока по WebRTC зрителю
-
Остановка воспроизведения потока.
Stream.stop()
code
-
Получение от сервера события, подтверждающего остановку воспроизведения потока
STREAM_STATUS.STOPPED
code
stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) { ... }).on(STREAM_STATUS.PLAYING, function(stream) { ... }).on(STREAM_STATUS.STOPPED, function() { setStatus(STREAM_STATUS.STOPPED); onStopped(); }).on(STREAM_STATUS.FAILED, function(stream) { ... }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){ ... }); stream.play();
-
Остановка публикации потока
Stream.stop()
code
-
Получение от сервера события, подтверждающего остановку публикации потока
STREAM_STATUS.UNPUBLISHED
code
session.createStream({ name: streamName, display: localVideo, cacheLocalResources: true, receiveVideo: false, receiveAudio: false }).on(STREAM_STATUS.PUBLISHING, function (stream) { ... }).on(STREAM_STATUS.UNPUBLISHED, function () { setStatus("#publishStatus", STREAM_STATUS.UNPUBLISHED); onUnpublished(); }).on(STREAM_STATUS.FAILED, function () { ... }).publish();