From another WCS server via WebRTC¶
Overview¶
WCS can capture on demand a WebRTC video stream published by another WCS server. The captured stream can be than played on any of supported platforms using any of supported technologies. WebRTC stream capturing is managed using REST API.
Operation flowchart¶
- The browser connects to the WCS1 server via Websocket and sends the
publishStream
command. - The browser captures the microphone and the camera and sends the WebRTC stream to the server.
- The REST client sends to the WCS2 server the
/pull/pull
query. - WCS2 requests the stream from WCS1.
- WCS2 receives the WebRTC stream from WCS1.
- The second browser establishes a connection to the WCS2 server via Websocket and sends the
playStream
command. - The second browser receives the WebRTC stream and plays this stream on the page.
REST API¶
REST query must be an HTTP/HTTPS POST request as follows:
- HTTP:
http://test.flashphoner.com:8081/rest-api/pull/pull
- HTTPS:
https://test.flashphoner.com:8444/rest-api/pull/pull
Where:
test.flashphoner.com
is the address of the WCS server8081
is the standard REST / HTTP port of the WCS server8444
is the standard HTTPS portrest-api
is the required part of the URL/pull/pull
is the REST method used
REST queries and responses¶
/pull/pull¶
Pull the WebRTC stream at the specified 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¶
Find all pulled WebRTC streams
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¶
Terminate the pulled WebRTC stream
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 |
Parameters¶
Parameter | Description | Example |
---|---|---|
uri | Websocket URL of WCS server |
wss://demo.flashphoner.com:8443
|
localMediaSessionId | Session identifier |
5a072377-73c1-4caf-abd3
|
remoteMediaSessionId | Session identifier on the remote server |
12345678-abcd-dead-beaf
|
localStreamName | Local name assigned to the captured stream. By this name the stream can be requested from the WCS server |
testStream
|
remoteStreamName | Captured stream name on the remote server |
testStream
|
status | Current stream status |
NEW
|
Configuration¶
By default, WebRTC stream is pulled over unsecure Websocket connection, i.e. WCS server URL has to be set as ws://demo.flashphoner.com:8080
. To use Secure Websocket, the parameter must be set in flashphoner.properties file
This change has to be made on both WCS servers: the server that publishes the stream and the server the stream is pulled to.
Quick manual on testing¶
- For this test we use:
- two WCS servers;
- the Chrome browser and a REST-client to send queries to the server;
- the Two Way Streaming web application to publish the stream;
-
the Player web application to play the captured stream in the browser.
-
Open the Two Way Streaming web application and publish the stream on the first server
-
Open the REST client. Send the
/pull/pull
query to the second WCS server and specify the following parameters: - URL of the WCS server the stream is captured from;
- stream name published on the server;
-
local stream name
-
Make sure the second server captured the stream. To do this, send the
/pull/find_all
query:
-
Open the Player web application and put in the local stream name into the
Stream
field, then clickStart
:
Call flow¶
Below is the call flow when using the Two Way Streaming example to publish a stream on one WCS server and playing that stream on another WCS server
-
Establishing connection to the server
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(); });
-
Receiving from the server an event confirming successful connection
SESSION_STATUS.ESTABLISHED
code
-
Publishing the stream
Stream.publish()
code
-
Receiving an event confirming successful publishing of the stream
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();
-
Sending the stream via WebRTC to the server
-
Sending the
/pull/pull
REST query to the second server -
Requesting the stream from the first server
-
Sending the stream via WebRTC to the second server
-
Establishing connection to the second server
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(); });
-
Receiving from the server and event confirming successful connection
SESSION_STATUS.ESTABLISHED
code
-
Requesting to play the stream
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();
-
Receiving an event confirming successful capturing and playing of the stream
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();
-
Sending the stream via WebRTC to the playing client
-
Stopping playback of the stream
Stream.stop()
code
-
Receiving an event confirming successful unpublishing of the stream
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();
-
Stopping publishing the stream
Stream.stop()
code
-
Receiving an event confirming successful unpublishing of the stream
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();