Versions Compared

Key

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

Example of video conference

This example can be used to organize video conference for three participants on Web Call Server.
Each participant can publish a stream of one of the following types

...

Link to the "room" is displayed in the Invite field.

Code of the example

The path to the source code of the example on WCS server is:

...

Here host is the address of the WCS server.

Work with code of video conference

To analyze the code, let's take the version of file conference.js with hash cf0daabc6b86e21d5a2f9e4605366c8b7f0d27eb, which is available here and can be downloaded with corresponding build 0.3.18.1894.

...


1. Initialization of the API. line 10API is initialized after loading the page. For Flash support, the path to SWF file is passed to the

Flashphoner.init() method. code

Code Block
languagejs
themeRDark
Flashphoner.init({flashMediaProviderSwfLocation: '../../../../media-provider.swf'});

2. Connection to server. line 69Connection to server is established when Join button is clicked.

Flashphoner.roomApi.connect() code

Code Block
languagejs
themeRDark
connection = Flashphoner.roomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){
    setStatus('#status', session.status());
    onLeft();
}).on(SESSION_STATUS.DISCONNECTED, function(session) {
    setStatus('#status', session.status());
    onLeft();
}).on(SESSION_STATUS.ESTABLISHED, function(session) {
    setStatus('#status', session.status());
    joinRoom();
});

Session is created with method roomApi.connect(). Callback function, which will be called in case of successfully established connection (status SESSION_STATUS.ESTABLISHED), is added.

3. Joining a conference. line 82

After establishing connection to the server, method connection.join() is used to join the conference.
To join3. Receiving the event confirming successful connection

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
connection = Flashphoner.roomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){
    setStatus('#status', session.status());
    onLeft();
}).on(SESSION_STATUS.DISCONNECTED, function(session) {
    ...
}).on(SESSION_STATUS.ESTABLISHED, function(session) {
    ...
});

4. Joining a conference.

connection.join() code
To join, name of the conference room is passed to the method. (The name can be specified as parameter in the URL of the client page; otherwise, random name will be generated.)

Code Block
languagejs
themeRDark
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
    var participants = room.getParticipants();
    console.log("Current number of participants in the room: " + participants.length);
    if (participants.length >= _participants) ...
});

5. Receiving the event describing chat room state

RoomStatusEvent STATE код

On this event:

  • the length of the array of Participant objects returned by method Room.getParticipants() is determined to get the number of already connected participants
  • if the maximum allowed number of participants had already been reached, the user leaves the "room" (line 85)
  • otherwise, the user starts publishing video stream
Code Block
languagejs
themeRDark
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
    var participants =  consoleroom.warn("Current room is full"getParticipants();
        $("#failedInfo").textconsole.log("Current roomnumber is full.");
        room.leave().then(onLeft, onLeftof participants in the room: " + participants.length);
        return false;
    }
    setInviteAddress(room.name());
    if (participants.length >= 0_participants) {
        var chatState = "participants: "console.warn("Current room is full");
        for (var i = 0; i < participants.length; i++) {
   $("#failedInfo").text("Current room is full.");
        room.leave().then(onLeft, onLeft);
         installParticipant(participants[i])return false;
    }
        chatState += participants[i]setInviteAddress(room.name());
         if (i != participants.length -> 10) {
           var chatState += ",participants: ";
        for }
(var i = 0; i }
    < participants.length; i++) {
     addMessage("chat", chatState);
     } else {
 installParticipant(participants[i]);
          addMessage("chat", " roomchatState is empty"+= participants[i].name();
     }
    if publishLocalMedia(room);
     onJoined(room);
}).on(ROOM_EVENT.JOINED, function(participant){
i != participants.length - 1) {
       installParticipant(participant);
     addMessage(participant.name(),chatState += "joined,");
}).on(ROOM_EVENT.LEFT, function(participant){;
         }
     //remove participant}
     removeParticipant(participant);
     addMessage(participant.name()"chat", "left"chatState);
}).on(ROOM_EVENT.PUBLISHED, function(participant){
     } else {
      playParticipantsStream(participant);
}).on(ROOM_EVENT.FAILED, function(room, info){   addMessage("chat", " room is empty");
     }
     connection.disconnectpublishLocalMedia(room);
     $('#failedInfo').text(info)onJoined(room);
}).on(ROOM_EVENT.MESSAGEJOINED, function(messageparticipant){
     addMessage(message.from.name(), message.text);
});

...

.on(ROOM_EVENT.

...

LEFT, function(participant){
     ...
}).on(ROOM_EVENT.

...

PUBLISHED, function(participant){
     ...
}).on(ROOM_EVENT.

...

In this callback function,

  • the length of the array of Participant objects returned by method Room.getParticipants() is determined to get the number of already connected participants
  • if the maximum allowed number of participants had already been reached, the user leaves the "room" (line 85)
  • otherwise, the user starts publishing video stream

ROOM_EVENT.JOINED event is sent by server when a new participants joins the "room"; when this status is received, the interface is changed to display the new participant and playback of video stream published by that participant is started.
ROOM_EVENT.LEFT event is sent by server when one of the participants leaves the conference; when this status is received, appropriate changes in the interface are done.
ROOM_EVENT.PUBLISHED event is sent by server when one of the participants starts publishing; when this status is received, playback of video stream published by that participant is started.
ROOM_EVENT.FAILED - when this status is received, method connection.disconnect() is used to close connection to server.
ROOM_EVENT.MESSAGE event is sent by server when one of the participants sends text message; when this status is received, the message is added to the messages log.

When callback function for event ROOM_EVENT.JOINED, ROOM_EVENT.LEFT or ROOM_EVENT.PUBLISHED is called, object 'participant' describing corresponding participant (which joined / left / started publishing) is passed to the function.

4. Video streaming. line 217

Code Block
languagejs
themeRDark
room.publish(document.getElementById("localDisplay")).on(STREAM_STATUS.FAILED, function (stream) {
    console.warn("Local stream failed!");
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
    setStatus("#localStatus", stream.status());
    onMediaPublished(stream);
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
});

After joining a conference, method room.publish() is called to publish video stream.
<div> element 'localDisplay', in which video from camera will be displayed, is passed to the method.

5. Playback of video stream. line 159

...

FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
     ...
});

6. Video streaming.

room.publish() code

<div> element 'localDisplay', in which video from camera will be displayed, is passed to the room.publish() method

Code Block
languagejs
themeRDark
room.publish(document.getElementById("localDisplay")).on(STREAM_STATUS.FAILED, function (stream) {
    console.warn("Local stream failed!");
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
    setStatus("#localStatus", stream.status());
    onMediaPublished(stream);
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
});

7. Receiving the event notifying that other participant joined to the room

RoomStatusEvent JOINED code

Code Block
languagejs
themeRDark
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
     ...
}).on(ROOM_EVENT.JOINED, function(participant){
     installParticipant(participant);
     addMessage(participant.name(), "joined");
}).on(ROOM_EVENT.LEFT, function(participant){
     ...
}).on(ROOM_EVENT.PUBLISHED, function(participant){
     ...
}).on(ROOM_EVENT.FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
     ...
});

8. Receiving the event notifying that other participant published video stream

RoomStatusEvent PUBLISHED code

Code Block
languagejs
themeRDark
participantconnection.play(document.getElementById(pDisplay)join({name: getRoomName()}).on(STREAMROOM_STATUSEVENT.PLAYINGSTATE, function (playingStreamroom) {
     document..getElementById(playingStream.id().
}).addEventListener('resize'on(ROOM_EVENT.JOINED, function (eventparticipant) {
        resizeVideo(event.target);...
}).on(ROOM_EVENT.LEFT, function(participant){
    } ...
}).on(ROOM_EVENT.PUBLISHED, function(participant){
     playParticipantsStream(participant);
});

Callback function for event STREAM_STATUS.PLAYING is added to call function resizeVideo(), which is used in the examples to adapt resolution to the element, in which the video will be displayed.

6. Stop of streaming. line 184

The following method is called to stop video streaming

Code Block
languagejs
themeRDark
stream.stop();

After calling the method, status STREAM_STATUS.UNPUBLISHED should arrive to confirm stop of streaming from the server side.

7. Leaving conference room. line 22

To leave conference room, method room.leave() is used.

...

languagejs
themeRDark

After leaving, function onLeft() of the example is called to make appropriate changes in controls of the interface.

8. Mute/unmute audio and video of the published stream. line 187, line 196

The following functions are used to check if audio or video is muted.

  • stream.isAudioMuted()
  • stream.isVideoMuted()

The following functions are used to mute/unmute audio and video

  • stream.unmuteAudio();
  • stream.muteAudio();
  • stream.unmuteVideo();
  • stream.muteVideo();

9. Sending text message. line 29

Method participant.sendMessage() is used for sending text message to other participants. Message text is passed to the method.

When Send button is clicked,

  • method room.getParticipants() is used to get the array of connected participants
  • the message is sent to each participant
Code Block
languagejs
themeRDark
.on(ROOM_EVENT.FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
     ...
});

9. Playback of video stream.

participant.play() code
<div> element, in which the video will be displayed, is passed to the participant.play() method.

Code Block
languagejs
themeRDark
function playParticipantsStream(participant) {
    if (participant.play) {
        $("[id$=Name]").each(function (index, value) {
            if ($(value).text() == participant.name()) {
                var p = value.id.replace('Name', '');
                var pDisplay = p + 'Display';
                participant.play(document.getElementById(pDisplay)).on(STREAM_STATUS.PLAYING, function (playingStream) {
                    document.getElementById(playingStream.id()).addEventListener('resize', function (event) {
                        resizeVideo(event.target);
                    });
                });
            }
        });
    }
}

10. Stop of streaming.

stream.stop() code

Code Block
languagejs
themeRDark
function onMediaPublished(stream) {
    $("#localStopBtn").text("Stop").off('click').click(function(){
        $(this).prop('disabled', true);
        stream.stop();
    }).prop('disabled', false);
    ...
}

11. Receiving the event confirming successful streaming stop

StreamStatusEvent UNPUBLISHED code

Code Block
languagejs
themeRDark
room.publish(document.getElementById("localDisplay")).on(STREAM_STATUS.FAILED, function (stream) {
    ...
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
    ...
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
});

12. Leaving conference room

room.leave() code

Code Block
languagejs
themeRDark
function onJoined(room) {
    $("#joinBtn").text("Leave").off('click').click(function(){
        $(this).prop('disabled', true);
        room.leave().then(onLeft, onLeft);
    }).prop('disabled', false);
    ...
}

13. Mute/unmute audio and video of the published stream

stream.isAudioMuted(), stream.isVideoMuted(), stream.muteAudio(), stream.unmuteAudio(), stream.muteVideo(), stream.unmuteVideo() code

Code Block
languagejs
themeRDark
function onMediaPublished(stream) {
    ...
    $("#localAudioToggle").text("Mute A").off('click').click(function(){
        if (stream.isAudioMuted()) {
            $(this).text("Mute A");
            stream.unmuteAudio();
        } else {
            $(this).text("Unmute A");
            stream.muteAudio();
        }
    }).prop('disabled', false);
    $("#localVideoToggle").text("Mute V").off('click').click(function() {
        if (stream.isVideoMuted()) {
            $(this).text("Mute V");
            stream.unmuteVideo();
        } else {
            $(this).text("Unmute V");
            stream.muteVideo();
        }
    }).prop('disabled',false);
}

14. Sending text message.

participant.sendMessage() code

When Send button is clicked,

  • method room.getParticipants() is used to get the array of connected participants
  • the message is sent to each participant
Code Block
languagejs
themeRDark
function onJoined(room) {
    ...
    $('#sendMessageBtn').off('click').click(function(){
        var message = field('message');
        addMessage(connection.username(), message);
        $('#message').val("");
        //broadcast message
        var participants = room.getParticipants();
);
        for (var i = 0; i < participants.length; i++) {
            participants[i].sendMessage(message);
        }
    }).prop('disabled',false);
    $('#failedInfo').text("");
}