Skip to content

Streaming with zooming

Overview

This example can be used to test WebRTC stream publishing with zooming video on the fly in browser

A stream is being published with zoom from the client

The URL specified in the input field parameters:

  • test1.flashphoner.com:8443 is the address and Websocket port of the WCS server
  • 2a12b361 is the stream name

Two videos are played on the page

  • Local - video from the camera
  • Preview - the video as received from the server

The code of the example

The code of the example is on WCS server by the following path:

/usr/local/FlashphonerWebCallServer/client/examples/demo/stream-zoom/stream-zoom.html

  • stream-zoom.css - file with styles
  • stream-zoom.html - page of the streamer
  • stream-zoom.js - main script providing functionality of the example

This example can be tested using the following address:

https://host:8444/client/examples/demo/streaming/stream-zoom/stream-zoom.html

where host is the address of the WCS server.

Analyzing the code

To analyze the code, let's take the version of file stream-zoom.js with hash 7626dbf, which is available here and may be downloaded in build 2.0.260.

1. API initialization

Flashphoner.init() code

const init_page = function() {
    //init api
    try {
        Flashphoner.init();
    } catch(e) {
        setText("notifyFlash", "Your browser doesn't support WebRTC technology needed for this example");
        return;
    }
    ...
}

2. Connecting to the server

Flashphoner.createSession() code

const start = function() {
    //check if we already have session
    if (currentSession) {
        startStreaming(currentSession);
    } else {
        //create session
        let url = getValue("url");
        console.log("Create new session with url " + url);
        Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
            ...
        }).on(SESSION_STATUS.DISCONNECTED, function(){
            ...
        }).on(SESSION_STATUS.FAILED, function(){
            ...
        });
    }
}

3. Receiving the event confirming successful connection

SESSION_STATUS.ESTABLISHED code

const start = function() {
    //check if we already have session
    if (currentSession) {
        startStreaming(currentSession);
    } else {
        //create session
        let url = getValue("url");
        console.log("Create new session with url " + url);
        Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
            //session connected, start streaming
            currentSession = session;
            startStreaming(session);
        }).on(SESSION_STATUS.DISCONNECTED, function(){
            ...
        }).on(SESSION_STATUS.FAILED, function(){
            ...
        });
    }
}

4. Video streaming with zooming enabled

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

Parameters passed to createStream() method:

  • streamName - name of stream;
  • localVideo - div element to display video from camera
  • constraints.video.zoom: true - enables video zooming if supported
  • constraints.audio: true - enables audio capturing
const startStreaming = function(session) {
    let streamName = getValue("url").split('/')[3];
    disableItem("url");

    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: {
            video: {
                zoom: true
            },
            audio: true
        }
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        ...
    }).on(STREAM_STATUS.UNPUBLISHED, function(){
        ...
    }).on(STREAM_STATUS.FAILED, function(stream){
        ...
    }).publish();
}

5. Receiving the event confirming successful publishing

STREAM_STATUS.PUBLISHING code

On receiving the event, preview stream is created with Session.createStream(), and Stream.play() is called to play it.

const startStreaming = function(session) {
    let streamName = getValue("url").split('/')[3];
    disableItem("url");

    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: {
            video: {
                zoom: true
            },
            audio: true
        }
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        setStatus(STREAM_STATUS.PUBLISHING);
        //play preview
        session.createStream({
            name: streamName,
            display: remoteVideo
        }).on(STREAM_STATUS.PLAYING, function(previewStream){
            //enable stop button
            onStarted(publishStream, previewStream);
        }).on(STREAM_STATUS.STOPPED, function(){
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function(stream){
            //preview failed, stop publishStream
            if (publishStream.status() === STREAM_STATUS.PUBLISHING) {
                setStatus(STREAM_STATUS.FAILED, stream);
                publishStream.stop();
            }
        }).play();
    }).on(STREAM_STATUS.UNPUBLISHED, function(){
        ...
    }).on(STREAM_STATUS.FAILED, function(stream){
        ...
    }).publish();
}

6. Set up zoom slider after successful preview playback starting

Stream.getZoomCapabilities, Stream.setZoom code

const setUpZoom = function(publishStream) {
    // Check if zoom capabilities available
    if (publishStream) {
        let zoom = document.getElementById("zoom");
        let zoomCapabilities = publishStream.getZoomCapabilities();

        if (zoomCapabilities) {
            // Set up zoom control
            setText("info", "Zoom can be used with the camera");
            setAttribute("info", "class", "text-muted");
            zoom.min = zoomCapabilities.min;
            zoom.max = zoomCapabilities.max;
            zoom.step = zoomCapabilities.step;
            zoom.value = zoomCapabilities.value;
            zoom.oninput = async function(event) {
                await publishStream.setZoom(event.target.value);
                console.log("Zoom value: " + publishStream.getZoom());
            };
            enableItem("zoom");
        } else {
            setText("info", "Zoom can't be used with the camera");
            setAttribute("info", "class", "text-danger");
        }
    }
}