Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


Chrome

Firefox

Safari 11

Internet Explorer

Edge

Windows

+

+


+

+

Mac OS

+

+

+



Android

+

+




iOS

-

-

+

To manage capturing of an RTMP stream, REST API is used.



Operation flowchart


1. The browser establishes a connection to the server via the Websocket protocol and sends the play command.

...

4. The server transforms the stream to WebRTC and gives the stream to the browser.

REST-queries

A REST-query should be HTTP/HTTPS POST request as follows:

  • HTTP: http://test.flashphoner.com:9091/rest-api/rtsp/startup
  • HTTPS: https://test.flashphoner.com:8888/rest-api/rtsp/startup

Where:

  • test.flashphoner.com - is the address of the WCS server
  • 9091 - is the standard REST / HTTP port of the WCS server
  • 8888 - is the standard HTTPS port
  • rest-api - is the required part of the URL
  • /rtsp/startup - REST-method to use

REST-methods and response statuses

...

REST-method

...

Example of REST-query

...

Example of response

...

Response statuses

...

Description

...

/rtsp/startup

...

Code Block
languagejs
themeRDark
{
 "uri":"rtsp://myserver.com/live/myStream"
}

409 - Conflict

500 - Internal error

Pull the RTMP stream by the specified URL

...

/rtsp/find_all

...

Code Block
languagejs
themeRDark
{
"uri": "rtsp://myserver.com/live/myStream",
"status": "PLAYING"
}

200 – streams found
404 – streams not found

...

Find all pulled RTMP-streams

...

/rtsp/terminate

...

Code Block
languagejs
themeRDark
{
"uri":"rtsp://myserver.com/live/myStream"
}

200 - stream terminated
404 - stream not found

...

Terminate the pulled RTMP stream

Parameters

...

Parameter name

...

Description

...

Example

...

uri

...

URL of the RTSP stream

...

rtsp://myserver.com/live/myStream

...

status

...

Current status of the stream

...

PLAYING

Configuration

Sometimes, when IP camera should be connected through VPN, RTSP client should be bound to certain IP address. The option rtsp_client_address in settings file flashphoner.properties defines this address, for example:

Code Block
languagebash
themeRDark
rtsp_client_address=172.16.0.3

Quick manual on testing

Capturing a video stream from the IP camera and broadcasting it to a browser using the REST query /rtsp/startup

1. For this test we use:

  • the demo server at demo.flashphoner.com;
  • the Chrome browser and the REST-client to send queries to the server;
  • the Player web application to play the captured stream in the browser.

2. Open the REST client. Send the /rtsp/startup query specifying the URL of the web camera in parameters:

Image Removed

3. Make sure the stream is captured by the server. To do this, send the /rtsp/find_all query:

Image Removed

Image Removed

4. Open the Player web app and in the "Stream" field specify the URL of the web camera and click Start. Browser starts to play the stream:

Image Removed

5. Send the /rtsp/terminate query specifying the URL of the web camera in parameters:

Image Removed

6. Stream playback will terminate displaying an error:

Image Removed

Capturing of a video stream from the IP camera and broadcasting it to a browser without REST queries

1. For this test we use:

  • the demo server at demo.flashphoner.com;
  • the Player web application to play the captured stream in the browser.

2. Open the Player web app and specify the URL of the camera in the "Stream" field:

Image Removed

3. Click the "Start" button. Broadcasting of the captured stream begins.

Image Removed

4. WebRTC internals diagrams:

Image Removed

Configuration

Sometimes, when IP camera should be connected through VPN, RTSP client should be bound to certain IP address. The option rtsp_client_address in settings file flashphoner.properties defines this address, for example:

Code Block
languagebash
themeRDark
rtsp_client_address=172.16.0.3

Quick manual on testing

Capturing of a video stream from the IP camera and playing it in a browser

1. For this test we use:

  • the demo server at demo.flashphoner.com;
  • the Player web application to play the captured stream in the browser.

2. Open the Player web app and specify the URL of the camera in the "Stream" field:

Image Added


3. Click the "Start" button. Broadcasting of the captured stream begins.

Image Added


4. WebRTC internals diagrams:

Image Added

Stream capture from the IP camera management by REST API

Usually, it is enough to set the camera URL as stream name to capture stream from IP camera. However, it is possible to manage RTSP stream capture by REST API if necessary.

Testing

1. For this test we use:

2. Open the REST client. Send the /rtsp/startup query specifying the URL of the web camera in parameters:

Image Added


3. Make sure the stream is captured by the server. To do this, send the /rtsp/find_all query:

Image Added


Image Added

4. Open the Player web app and in the "Stream" field specify the URL of the web camera and click Start. Browser starts to play the stream:

Image Added


5. Send the /rtsp/terminate query specifying the URL of the web camera in parameters:

Image Added


6. Stream playback will terminate displaying an error:

Image Added

REST-queries

A REST-query should be HTTP/HTTPS POST request as follows:

Where:

  • test.flashphoner.com - is the address of the WCS server
  • 9091 - is the standard REST / HTTP port of the WCS server
  • 8888 - is the standard HTTPS port
  • rest-api - is the required part of the URL
  • /rtsp/startup - REST-method to use

REST-methods and response statuses

REST-method

Example of REST-query

Example of response

Response statuses

Description

/rtsp/startup

Code Block
languagejs
themeRDark
{
 "uri":"rtsp://myserver.com/live/myStream"
}

409 - Conflict

500 - Internal error


Pull the RTMP stream by the specified URL


/rtsp/find_all


Code Block
languagejs
themeRDark
{
"uri": "rtsp://myserver.com/live/myStream",
"status": "PLAYING"
}

200 – streams found
404 – streams not found


Find all pulled RTMP-streams

/rtsp/terminate

Code Block
languagejs
themeRDark
{
"uri":"rtsp://myserver.com/live/myStream"
}

200 - stream terminated
404 - stream not found


Terminate the pulled RTMP stream

Parameters

Parameter name

Description

Example

uri

URL of the RTSP stream

rtsp://myserver.com/live/myStream

status

Current status of the stream

PLAYING

Call flow

Below is the call flow when using the Player example

...

3. Request to play the stream.

session.createStream(), stream.play(); code

IP camera URL is passed to createStream() method as stream name

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream)function playStream(session) {
        var videostreamName = document.getElementById(stream.id()$('#streamName').val();
    var options   if (!video.hasListeners) = {
        name: streamName,
   video.hasListeners = true;
   display: remoteVideo,
        video.addEventListener('playing', function () {
  flashShowFullScreenButton: true
    };
    ...    
    stream = $("#preloader"session.createStream(options).hide();on(STREAM_STATUS.PENDING, function(stream) {
        var video   }= document.getElementById(stream.id());
        if    video.addEventListener('resize', function (event(!video.hasListeners) {
            video.hasListeners = true;
    var streamResolution = stream.videoResolution();
                if (Object.keys(streamResolution).length === 0video.addEventListener('playing', function () {
                    resizeVideo(event.target$("#preloader").hide();
            });
    } else {
      video.addEventListener('resize', function (event) {
            // Change aspect ratio tovar preventstreamResolution video stretching
= stream.videoResolution();
                if (Object.keys(streamResolution).length === 0) {
 var ratio = streamResolution.width / streamResolution.height;
                    var newHeight = Math.floor(options.playWidth / ratioresizeVideo(event.target);
                } else {
  resizeVideo(event.target, options.playWidth, newHeight);
                }
// Change aspect ratio to prevent video stretching
      });
        }
      var ratio = streamResolution...width / streamResolution.height;
    });
    stream.play();

4. Request from WCS to the RTSP source to broadcast the stream.

5. Broadcasting the RTSP stream

6. Receiving from the server an event confirming successful capturing and playing of the stream.

StreamStatusEvent, статус PLAYING code

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
                var newHeight = Math.floor(options.playWidth / ratio);
                    resizeVideo(event.target, options.playWidth, newHeight);
                ...}
    }).on(STREAM_STATUS.PLAYING, function(stream) {
        $("#preloader").show(});
        setStatus(stream.status());}
        onStarted(stream);...
        ...
    });
    stream.play();

7. Sending audio- and video stream via WebRTC

8. Stopping playing the stream.

...

}

4. Request from WCS to the RTSP source to broadcast the stream.

5. Broadcasting the RTSP stream

6. Receiving from the server an event confirming successful capturing and playing of the stream.

StreamStatusEvent, статус PLAYING code

Code Block
languagejs
themeRDark
function onStarted(stream) {
  stream  $("#playBtn").text("Stop").off('click').click(function()= session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        $(this).prop('disabled', true);...
    }).on(STREAM_STATUS.PLAYING, function(stream) {
        stream.stop$("#preloader").show();
        }).prop('disabled', falsesetStatus(stream.status());
       $("#fullScreenBtn").off('click').click(function(){ onStarted(stream);
       stream.fullScreen(); ...
    }).prop('disabled', false);
    $("#volumeControl").slider("enable"stream.play();
    stream.setVolume(currentVolumeValue);
}

9. Receiving from the server an event confirming successful stop of the stream playback.

...


7. Sending audio- and video stream via WebRTC

8. Stopping playing the stream.

stream.stop(); code

Code Block
languagejs
themeRDark
function onStarted(stream) {
  stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) $("#playBtn").text("Stop").off('click').click(function(){
        ...
    }$(this).on(STREAM_STATUS.PLAYING, function(stream) {prop('disabled', true);
        ...stream.stop();
    }).on(STREAM_STATUS.STOPPEDprop('disabled', function(false) {;
        setStatus(STREAM_STATUS.STOPPED);$("#fullScreenBtn").off('click').click(function(){
        onStoppedstream.fullScreen();
    }).on(STREAM_STATUS.FAILED, function(stream) {prop('disabled', false);
        ...$("#volumeControl").slider("enable");
    })stream.on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){
        ...
    });
    stream.play();

Known issues

1. A stream containing B-frames does not play or plays with artifacts (latencies, lags)

Symptoms:

  • a stream sent by the IP camera via RTSP does not play or plays with latencies or lags
  • warnings in the client log:
Code Block
languagebash
themeRDark
09:32:31,238 WARN 4BitstreamNormalizer - RTMP-pool-10-thread-5 It is B-frame!

Solution: request lower resolution video from the camera to avoid using B-frames or transcode that stream.

2. Connection to the IP camera is lost on error in any track (audio or video)

Symptoms: connection to the IP camera is lost if one of tracks returns error 4**.
Solution: this behavior is enabled by default. However if one-time errors are not critical and should not terminate broadcasting, in the flashphoner.properties files set

Code Block
languagebash
themeRDark
rtsp_fail_on_error_track=false
rtp_force_synchronization=true

3. AAC frames of type 0 are not supported by decoder and will be ignored while stream pulled playback

...

setVolume(currentVolumeValue);
}

9. Receiving from the server an event confirming successful stop of the stream playback.

StreamStatusEvent, статус STOPPED code

Code Block
languagejs
themeRDark
    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();

Known issues

1. A stream containing B-frames does not play or plays with artifacts (latencies, lags)

Symptoms:

  • a stream sent by the IP camera via RTSP does not play or plays with latencies or lags
  • warnings in the client log:
10:13:06,815 WARN AAC - AudioProcessor-c6c22de8-a129-43b2-bf67-1f433a814ba9 Dropping AAC frame that starts with 0, 119056e500
Code Block
languagebash
themeRDark
RDark
09:32:31,238 WARN 4BitstreamNormalizer - RTMP-pool-10-thread-5 It is B-frame!

Solution: request lower resolution video from the camera to avoid using B-frames or transcode that stream.

2. Connection to the IP camera is lost on error in any track (audio or video)

Symptoms: connection to the IP camera is lost if one of tracks returns error 4**.
Solution: this behavior is enabled by default. However if one-time errors are not critical and should not terminate broadcasting, in the flashphoner.properties files set

Code Block
languagebash
themeRDark
rtsp_fail_on_error_track=false
rtp_force_synchronization=true

3. AAC frames of type 0 are not supported by decoder and will be ignored while stream pulled playback

In this case, warnings will be displayed in the client log:

Code Block
languagebash
themeRDark
10:13:06,815 WARN AAC - AudioProcessor-c6c22de8-a129-43b2-bf67-1f433a814ba9 Dropping AAC frame that starts with 0, 119056e500


function playStream(session) {
    var streamName = $('#streamName').val();
    var options = {
        name: streamName,
        display: remoteVideo,
        flashShowFullScreenButton: true
    };
    ...    
    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();
}