Versions Compared

Key

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

...

This example may be used to embed player to the web page for live streams from web and IP cameras playback. These technologies are supported^

  • WebRTC
  • MSE
  • WSPlayer (Websocket + HTML5 Canvas)

Embedding page interface:

Image RemovedImage Added

Code of the example

Source code of the example is on server by this path:

/usr/local/FlashphonerWebCallServer/client2/examples/demo/streaming/embed_player 

player.css  - CSS style file
player.html  - player page
player.js  - script for player to work
sample.css  - CSS style file for embedding  interface page
sample.html  -  embedding  embedding  interface page
sample.js  - script to form embedding code

The example can be tested on this URL:

https://host:8888/client2/examples/demo/streaming/embed_player/sample.html 

where host is your WCS server address

Analyzing the code

To analyze code get player.js file version with hash ecbadc3 24a69e1 that can be found here and is avalable to download in build 2.0.212225.

1. API initializing.

Flashphoner.init()  code

Code Block
languagejs
themeRDark
        Flashphoner.init({
 preferredMediaProviders: mediaProviders && mediaProviders !== "" ?     receiverLocation: '../../dependencies/websocket-player/WSReceiver2.js',
            decoderLocation: '../../dependencies/websocket-player/video-worker2.js',
            preferredMediaProviders: mediaProviders && mediaProviders !== "" ? mediaProviders.split(','): []
        });

2. Connection to the server

Flashphoner.createSession() code

These parameters are passed to createSession() method:

...

mediaProviders.split(','): [] });

2. Connection to the server

Flashphoner.createSession()  code

The following parameters are passed to createSession()  method:

  • urlServer  - WCS server URL
  • mediaOptions  - parameters to connect through the TURN server
Code Block
languagejs
themeRDark
let mediaOptions = {"iceServers": [{'url': 'turn:turn.flashphoner.com:443?transport=tcp', 'username': 'flashphoner', 'credential': 'coM77EMrV7Cwhyan'}]};
Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions}).on(SESSION_STATUS.ESTABLISHED, function (session) {
    ...
});

3. Receiving the event confirming successful connection

SESSION_STATUS.ESTABLISHED  code

Code Block
languagejs
themeRDark
    var mediaOptions = {"iceServers": [{'url': 'turn:turn.flashphoner.com:443?transport=tcp', 'username': 'flashphoner', 'credential': 'coM77EMrV7Cwhyan'}]};Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions}).on(SESSION_STATUS.ESTABLISHED, function (session) {
    FlashphonersetStatus(session.createSession({urlServer: urlServer, mediaOptions: mediaOptionsstatus());
    //session connected, start playback
    playStream(session);
}).on(SESSION_STATUS.ESTABLISHEDDISCONNECTED, function (session) {
        ...
}).on(SESSION_STATUS.FAILED, function () {
    ...
});

3. Receiving the event confirming successful connection

ConnectionStatusEvent ESTABLISHED code

...

languagejs
themeRDark

...

4. Video stream playback.

Session.createStream() , Stream.play()  code

The following parameters are passed to createStream()  method:

  • streamName  - name of the stream
  • remoteVideo  - div  element to display stream on page
  • resolution to play the stream (transcoding will be enabled on server)
  • useControls - enables a standard HTML5 video controls
  • unmutePlayOnStart: false  - disables automatic audio unmuting for autoplay to conform browsers requirements
Code Block
languagejs
themeRDark
let useVideoControls = true;
...
let options = {
    name: streamName,
   setStatus(session.status());
   display: remoteVideo,
    useControls:  //session connected, start playbackuseVideoControls
};
if (resolution) {
    playWidth    playStream(session);
= resolution.split("x")[0];
    playHeight }).on(SESSION_STATUS.DISCONNECTED, function () {= resolution.split("x")[1];
    options.constraints = {
  ...
    }).on(SESSION_STATUS.FAILED, function ()video: {
        ...
    });

...

session.createStream(), play() code

These parameters are passed to createStream() method:

  • streamName - name of the stream
  • remoteVideo - <div>-element to display stream on page
  • switch to show/|hide full screen button
  • player window resolution
  • unmutePlayOnStart: false - disables automatic audio unmuting for autoplay to conform browsers requirements
Code Block
languagejs
themeRDark
    var options = {
        name: streamNamewidth: playWidth,
            height: playHeight
        },
        display: remoteVideo,
        flashShowFullScreenButtonaudio: true
    };
}
    if (resolution_for_wsplayerautoplay) {
        options.playWidthunmutePlayOnStart = resolution_for_wsplayer.playWidth;
        options.playHeight = resolution_for_wsplayer.playHeight;
    } else if (resolutionfalse;
}
playingStream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
        options.playWidth = resolution.split("x")[0];
        options.playHeight = resolution.split("x")[1];
    }
    if (autoplay) {
        options.unmutePlayOnStart = false;
    }
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    });
    stream.play();

5. Receiving the event confirming stream is ready to playback

StreamStatusEvent PENDING code

...

...
});
playingStream.play();

5. Receiving the event confirming stream is ready to playback

STREAM_STATUS.PENDING  code

On this event:

  • hide the custom preloader in Chrome browser because there is a standard one when standard controls are enabled
  • set up resize video event handler
  • set up video event handlers separately for Safari and other browsers
Code Block
languagejs
themeRDark
   playingStream stream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
        var video = document.getElementById(stream.idif (Browser.isChrome()); {
        if (!video.hasListeners) {
            video.hasListeners = true;// Hide a custom preloader in Chrome because there is a standard one with standard controls
            video.addEventListener('playing', function () {hideItem('preloader');
    }
    let video = document.getElementById(stream.id());
    if $("#preloader").hide();(!video.hasListeners) {
        video.hasListeners =   })true;
            video.addEventListener('resize', function (event) {
setResizeHandler(video, stream, playWidth);
        if (Browser.isSafariWebRTC()) {
         var streamResolution = stream.videoResolutionsetWebkitEventHandlers(video);
        } else {
           if setEventHandlers(Object.keys(streamResolution).length === 0) {
video);
        }
    }
}).on(STREAM_STATUS.PLAYING, function (stream) {
    ...
}).on(STREAM_STATUS.STOPPED, function ()  resizeVideo(event.target);
{
    ...
}).on(STREAM_STATUS.FAILED, function(stream) {
           } else ...
}).on(STREAM_EVENT, function(streamEvent){
                    // Change aspect ratio to prevent video stretching
                    var ratio = streamResolution.width / streamResolution.height;
                    var newHeight = Math.floor(options.playWidth / ratio);
            ...
});
playingStream.play();

6. Receiving the event confirming successful stream playback

STREAM_STATUS.PLAYING  code

On this event, MSE stream playback is unpaused in Android Firefox browser

Code Block
languagejs
themeRDark
playingStream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
    ...
}).on(STREAM_STATUS.PLAYING, function (stream) {
    // Android Firefox may pause stream playback via MSE even if video element is muted
    if (Flashphoner.getMediaProviders()[0] == "MSE" && autoplay && Browser.isAndroidFirefox()) {
        resizeVideo(event.target, options.playWidth, newHeightlet video = document.getElementById(stream.id());
        if (video &&      }video.paused) {
            }video.play();
        }
     }).on
    setStatus(STREAM_STATUS.PLAYING, function (stream) {);
        ...
    onStarted();
}).on(STREAM_STATUS.STOPPED, function () {
        ...
    }).on(STREAM_STATUS.FAILED, function (stream) {
        ...
    }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTHEVENT, function (streamstreamEvent) {
        ...
    });
    stream.playingStream.play();

6. Receiving the event confirming successful stream playback

StreamStatusEvent PLAYING 7. Stream playback stop

Stream.stop()  code

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    }).on(STREAM_STATUS.PLAYING, function (stream) {
        setStatus(stream.status());
        onStarted(stream);
    }).on(STREAM_STATUS.STOPPED, function () {
        ...
    }).on(STREAM_STATUS.FAILED, function () {
        ...
    }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function (stream) {
        ...
    });
    stream.play();

7. Stream playback stop

stream.stop() code

Code Block
languagejs
themeRDark
            $that.find('.play-pause').bind('click', function () {
                // If playing, etc, change classes to show pause or play button
                if (!$(this).prop('disabled')) {
                    if (stopped) {
                        ...
                    } elseplayingStream.stop();

8. Receiving the event confirming successful playback stop

STREAM_STATUS.STOPPED  code

Code Block
languagejs
themeRDark
playingStream = 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_EVENT, function(streamEvent){
    ...
});
playingStream.play(); 

9. Automatic playback starting if required

code

Code Block
languagejs
themeRDark
if (autoplay) {
    centralButton.click();
}

10. Setting up resize event handler

code

On this event, the container size for video element is changed

Code Block
languagejs
themeRDark
function setResizeHandler(video, stream, playWidth) {
    video.addEventListener('resize', function (event) {
        let streamResolution               if (stream) {= stream.videoResolution();
        if (Object.keys(streamResolution).length === 0) {
                stream.stop(resizeVideo(event.target);
        } else {
            // Change }
aspect ratio to prevent video stretching
            let ratio = streamResolution.width /   ...streamResolution.height;
            let newHeight = Math.floor(playWidth     }/ ratio);
            resizeVideo(event.target,    }playWidth, newHeight);
        }
    });

8. Receiving the event confirming successful playback stop

...

;
}

11. Setting up event handlers for Safari browser

code

The following events are handled:

  • playing - hide the custom preloader when stream is playing
  • webkitbeginfullscreen , webkitendfullscreen - detect full screen mode to unpause stream playback when exiting this mode in iOS Safari
  • pause - unpause stream playback when exiting full screen mode; stop playback by clicking the standard pause control in windowed mode
Code Block
languagejs
themeRDark
function setWebkitEventHandlers(video) {
    let streamneedRestart = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) { false;
    let isFullscreen = false;
    // Hide  custom ...preloader
    })video.on(STREAM_STATUS.PLAYINGaddEventListener('playing', function (stream) {
        ...hideItem('preloader');
    }).on(STREAM_STATUS.STOPPED, function () {;
    //    setStatus(STREAM_STATUS.STOPPED);
        onStopped();Use webkitbeginfullscreen event to detect full screen mode in iOS Safari
    })video.on(STREAM_STATUS.FAILEDaddEventListener("webkitbeginfullscreen", function () {
        ...
isFullscreen =   }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function (stream) {
true;
    });            ...
    });
    streamvideo.play();

9. Playback volume setting

stream.unmuteRemoteAudio(), stream.setVolume(currentVolumeValue) code

Code Block
languagejs
themeRDark
addEventListener("pause", function () {
        if (streamneedRestart) {
          if  (volume > 0) {console.log("Video paused after fullscreen, continue...");
            video.play();
            ifneedRestart (!firstUnmuted && slider && Browser.isAndroid()) {
= false;
        } else if (!(isFullscreen || document.webkitFullscreenElement)) {
      console.error("User should click volume unmute button to// enable audio");
    Stop stream by standard play/pause control
            returnplayingStream.stop(false);
        }
    });
  else if (stream.isRemoteAudioMutedvideo.addEventListener("webkitendfullscreen", function ()) {
        video.play();
        needRestart = stream.unmuteRemoteAudio()true;
        isFullscreen = false;
    });  firstUnmuted = true;
            }
        }
}

12. Setting up event handlers in other browsers

code

The following events are handled:

  • playing - hide the custom preloader when stream is playing
  • pause - stop playback by clicking the standard pause control in windowed mode
Code Block
languagejs
themeRDark
function setEventHandlers(video) {
    // Hide   stream.setVolume(volume);
    }
    // Save current volume in page element to restore it when mute/unmute
custom preloader
    video.addEventListener('playing', function () {
        $hideItem('#volume-range').val(volumepreloader');
    ...

10. Automatic playback start on page load

code

Code Block
languagejs
themeRDark
    if (autoplay ) {});
    // Use standard pause control to stop playback
    video.addEventListener("pause", function () {
 // Autoplay will start for muted video tag only, adjust mute button and slider view
if (!(document.fullscreenElement || document.mozFullscreenElement)) {
           firstUnmuted = false;
        $('.volume').addClass('volume-none');
        $('.volume').html(HTML_VOLUME_MUTE);
// Stop stream by standard play/pause control if we're not in fullscreen
            $('#slider').slider( "value", 1 playingStream.stop();
        $(".play-pause").click();}
    });
}