Table of Contents |
---|
Описание
WCS может по требованию захватывать WebRTC-видеопоток, раздаваемый с другого WCS-сервера. Захваченный поток может раздаваться на любые из поддерживаемых платформ, по любой из поддерживаемых технологий. Для управления захватом WebRTC-потока используется REST API.
Схема работы
- Браузер соединяется с сервером WCS1 по протоколу Websocket и отправляет команду publish.
- Браузер захватывает микрофон и камеру и отправляет WebRTC поток на сервер.
- REST-клиент отправляет на сервер WCS2 запрос /pull/pull.
- WCS2 запрашивает поток с WCS1.
- WCS2 получает WebRTC поток с WCS1.
- Второй браузер устанавливает соединение c сервером WCS2 по Websocket и отправляет команду play.
- Второй браузер получает WebRTC поток и воспроизводит этот поток на странице.
REST-вызовы
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-методы и статусы ответа
...
REST-метод
...
Пример тела REST-запроса
...
Пример тела REST-ответа
...
Статусы ответа
...
Описание
...
/pull/pull
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"uri":"wss://demo.flashphoner.com:8443",
"localStreamName": "testStream",
"remoteStreamName": "testStream"
} |
409 - Conflict
500 - Internal error
Извлечь WebRTC-поток по указанному URL
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"localMediaSessionId": "5a072377-73c1-4caf-abd3",
"remoteMediaSessionId": null,
"localStreamName": "testStream",
"remoteStreamName": "testStream",
"uri": "wss://demo.flashphoner.com:8443",
"status": "NEW"
} |
...
200 – потоки найдены
500 - Internal error
...
/pull/terminate
...
Code Block | ||||
---|---|---|---|---|
| ||||
{
"uri":"wss://demo.flashphoner.com:8443",
"localStreamName": "testStream",
"remoteStreamName": "testStream"
} |
...
200 - поток завершен
500 - Internal error
...
Завершить извлеченный WebRTC-поток
Параметры
...
Имя параметра
...
Описание
...
Пример
...
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 указать параметр
Code Block | ||||
---|---|---|---|---|
| ||||
wcs_agent_ssl=true |
Изменения в настройку должны быть внесены на обоих WCS-серверах: том, который публикует поток, и том, который этот поток захватывает.
Краткое руководство по тестированию
1. Для теста используем:
- два WCS-сервера;
- браузер Chrome и REST-клиент для отправки запросов на сервер;
- веб-приложение Two Way Streaming для публикации потока;
- веб-приложение Player для воспроизведения захваченного потока в браузере.
2. Откройте веб-приложение Two Way Streaming, опубликуйте поток на сервере
3. Откройте REST-клиент. Отправьте запрос /pull/pull, указав в параметрах:
- URL WCS-сервера, с которого будет захватываться поток;
- имя потока, опубликованного на сервере
- локальное имя потока
4. Убедитесь, что поток захвачен сервером. Для этого отправьте запрос /pull/find_all:
5. Откройте веб-приложение Player, укажите в поле Stream локальное имя потока, нажмите Start
Последовательность выполнения операций (Call flow)
Ниже описана последовательность вызовов при использовании примера Two Way Streaming для публикации потока на одном WCS сервере и Player для воспроизведения потока на другом WCS сервере
1. Установка соединения с сервером.
Flashphoner.createSession(); code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
}); |
...
ConnectionStatusEvent ESTABLISHED code
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) {
setStatus("#connectStatus", session.status());
onConnected(session);
}).on(SESSION_STATUS.DISCONNECTED, function () {
...
}).on(SESSION_STATUS.FAILED, function () {
...
}); |
...
stream.publish(); code
Code Block | ||||
---|---|---|---|---|
| ||||
session.createStream({
name: streamName,
display: localVideo,
cacheLocalResources: true,
receiveVideo: false,
receiveAudio: false
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
...
}).on(STREAM_STATUS.UNPUBLISHED, function () {
...
}).on(STREAM_STATUS.FAILED, function () {
...
}).publish(); |
...
StreamStatusEvent, статус PUBLISHING code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
|
...
6. Отправка REST-запроса /pull/pull на второй сервер
7. Запрос потока с первого сервера
8. Отправка аудио-видео потока по WebRTC на второй сервер
9. Установка соединения со вторым сервером.
Flashphoner.createSession(); code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
}); |
10. Получение от сервера события, подтверждающего успешное соединение.
ConnectionStatusEvent ESTABLISHED code
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
setStatus(session.status());
//session connected, start playback
playStream(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
...
}).on(SESSION_STATUS.FAILED, function(){
...
}); |
...
stream.play(); code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
|
12. Получение от сервера события, подтверждающего успешный захват и проигрывание потока.
StreamStatusEvent, статус PLAYING code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
|
13. Отправка аудио-видео потока по WebRTC
14. Остановка воспроизведения потока.
stream.stop(); code
Code Block | ||||
---|---|---|---|---|
| ||||
function onStarted(stream) {
$("#playBtn").text("Stop").off('click').click(function(){
$(this).prop('disabled', true);
stream.stop();
}).prop('disabled', false);
...
} |
15. Получение от сервера события, подтверждающего остановку воспроизведения потока.
StreamStatusEvent, статус STOPPED code
Code Block | ||||
---|---|---|---|---|
| ||||
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();
|
16. Остановка публикации потока.
stream.stop(); code
Code Block | ||||
---|---|---|---|---|
| ||||
function onPublishing(stream) {
$("#publishBtn").text("Stop").off('click').click(function () {
$(this).prop('disabled', true);
stream.stop();
}).prop('disabled', false);
$("#publishInfo").text("");
} |
17. Получение от сервера события, подтверждающего остановку публикации потока.
StreamStatusEvent, статус UNPUBLISHED code
...
language | js |
---|---|
theme | RDark |
...
Include Page | ||||
---|---|---|---|---|
|