Versions Compared

Key

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

...

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

Script for video conference uses roomApi designed for video chats, video conferences, webinars and other applications that involve presence of users in one virtual "room". To use RoomApi, the script flashphoner-room-api.js should be included

...


1. Initialization of the API.

Flashphoner.init() code

Code Block
languagejs
themeRDark
Flashphoner.init();

2. Connection to server.RoomApi.connectCamera and microphone access request

Flashphoner.getMediaAccess() code

Code Block
languagejs
themeRDark
connection = RoomApi.connect({urlServer:     Flashphoner.getMediaAccess(null, localDisplay).then(function() {
        createConnection(url, username: username);
    }).on(SESSION_STATUS.FAILED, catch(function(sessionerror) {
    ...
});

3. Receiving the event confirming successful connection

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
connection = RoomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){
    ...
}).on(SESSION_STATUS.DISCONNECTED, function(session) {
    ...
}).on(SESSION_STATUS.ESTABLISHED, function(session) {
    setStatus('#status', session.status())    console.error("User not allowed media access: "+error);
        $("#failedInfo").text("User not allowed media access. Refresh the page");
        onLeft();
    joinRoom();
});

4. Joining a conference3. Connection to server.

connectionRoomApi.joinconnect() 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
function createConnection(url, username) {
    connection = RoomApi.joinconnect({nameurlServer: getRoomName()url, recordusername: isRecord()username}).on(ROOMSESSION_EVENTSTATUS.STATEFAILED, function(roomsession){
        ...
    });
}

54.  Receiving Receiving the event describing chat room state

RoomStatusEvent STATE code

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

...

languagejs
themeRDark

...

confirming successful connection

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
connection = RoomApi.connect({urlServer: url, username: username}).on(ROOMSESSION_EVENTSTATUS.STATEFAILED, function(roomsession){
    var participants = room.getParticipants();...
}).on(SESSION_STATUS.DISCONNECTED, function(session) {
    console.log("Current number of participants in the room: " + participants.length...
}).on(SESSION_STATUS.ESTABLISHED, function(session) {
    setStatus('#status', session.status());
    if (participants.length >= _participants) {
        console.warn("Current room is full");
        $("#failedInfo").text("Current room is full.");
        room.leave().then(onLeft, onLeft);
        return false;
    }
    setInviteAddress(room.name());
    if (participants.length > 0) {
        var chatState = "participants: ";
        for (var i = 0; i < participants.length; i++) {
            installParticipant(participants[i]);
            chatState += participants[i].name();
         if (i != participants.length - 1joinRoom();
});

5. 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(), record: isRecord()}).on(ROOM_EVENT.STATE, function(room){
    ...
});

6. Receiving the event describing chat room state

RoomStatusEvent STATE code

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(), record: isRecord()}).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) {
        console.warn("Current room   chatState += ","is full");
         }
     }$("#failedInfo").text("Current room is full.");
         addMessage("chat", chatStateroom.leave().then(onLeft, onLeft);
     } else {
         addMessage("chat", " room is empty")return false;
     }
     publishLocalMediasetInviteAddress(room.name());
    if onJoined(room);
}).on(ROOM_EVENT.JOINED, function(participant)(participants.length > 0) {
     ...
}).on(ROOM_EVENT.LEFT, function(participant){
     ...
}).on(ROOM_EVENT.PUBLISHED, function(participant){
   var chatState = "participants: ";
        ...
}).on(ROOM_EVENT.FAILED, function(room, info){
for (var i = 0; i < participants.length; i++) {
          ...
}).on(ROOM_EVENT.MESSAGE, function(message){  installParticipant(participants[i]);
     ...
});

6. Low Power Mode checking before publishing on mobile device

Flashphoner.playFirstVideo() code

Code Block
languagejs
themeRDark
       chatState if (Browser.isSafariWebRTC()) {
+= participants[i].name();
         varif display(i != document.getElementById("localDisplay");
participants.length - 1) {
         Flashphoner.playFirstVideo(display, true, PRELOADER_URL).then(function() {
   chatState += ",";
         }
     publishLocalMedia(room);}
        }).catch(function (error) { addMessage("chat", chatState);
     } else {
     console.log("Can't atomatically publish local streamaddMessage("chat", use" room Publishis buttonempty");
     }
       for (var i = 0; i < display.children.length; i++) publishLocalMedia(room);
     onJoined(room);
}).on(ROOM_EVENT.JOINED, function(participant){
     ...
}).on(ROOM_EVENT.LEFT, function(participant){
          if (display.children[i]) ...
}).on(ROOM_EVENT.PUBLISHED, function(participant){
     ...
}).on(ROOM_EVENT.FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
       console.log("remove cached instance id " + display.children[i].id);...
});

7. Low Power Mode checking before publishing on mobile device

Flashphoner.playFirstVideo() code

Code Block
languagejs
themeRDark
    if (Browser.isSafariWebRTC()) {
        var display = document.getElementById("localDisplay");
         displayFlashphoner.removeChildplayFirstVideo(display.children[i]);, true, PRELOADER_URL).then(function() {
            publishLocalMedia(room);
    }
    }).catch(function (error) {
      }
      console.log("Can't atomatically publish local stream,  onMediaStopped(roomuse Publish button");
        });
    }

7. 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({
for (var i = 0; i < display.children.length; i++) {
         display: display,
      if  constraints: constraints,(display.children[i]) {
        record: false,
        receiveVideo: false,
  console.log("remove cached instance id "  receiveAudio: false
+ display.children[i].id);
       }).on(STREAM_STATUS.FAILED, function (stream) {
        console.warn("Local stream failed!" display.removeChild(display.children[i]);
               setStatus("#localStatus", stream.status()); }
        onMediaStopped(room);
    }).on(STREAM_STATUS.PUBLISHING, function (stream) {

           setStatus("#localStatus", stream.status() onMediaStopped(room);
        onMediaPublished(stream});
    }).on(STREAM_STATUS.UNPUBLISHED, function(stream) {

8. 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({
         setStatus("#localStatus", stream.status());
display: display,
         onMediaStopped(room);
    });

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

RoomStatusEvent JOINED code

Code Block
languagejs
themeRDark
connection.join({name: getRoomName(), record: isRecord()}).on(ROOM_EVENT.STATE, function(room){
     ...
constraints: constraints,
        record: false,
        receiveVideo: false,
        receiveAudio: false
    }).on(ROOMSTREAM_EVENTSTATUS.JOINEDFAILED, function (participantstream) {
      installParticipant(participant  console.warn("Local stream failed!");
     addMessage(participant.name(), "joined");
   setStatus("#localStatus", stream.status());
        onMediaStopped(room);
    }).on(ROOMSTREAM_EVENTSTATUS.LEFTPUBLISHING, function (participantstream) {
     ...
   setStatus("#localStatus", stream.status());
        onMediaPublished(stream);
    }).on(ROOMSTREAM_EVENTSTATUS.PUBLISHEDUNPUBLISHED, function(participantstream) {
     ...
}).on(ROOM_EVENT.FAILED, function(room, info){   setStatus("#localStatus", stream.status());
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){   onMediaStopped(room);
     ...
});

9. Receiving the event notifying that other participant published video streamjoined to the room

RoomStatusEvent PUBLISHED JOINED code

Code Block
languagejs
themeRDark
connection.join({name: getRoomName(), record: isRecord()}).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){
     playParticipantsStream(participant);...
}).on(ROOM_EVENT.FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
     ...
});

10. Low Power Mode checking before playback on mobile deviceFlashphoner.playFirstVideo() Receiving the event notifying that other participant published video stream

RoomStatusEvent PUBLISHED code

Code Block
languagejs
themeRDark
connection.join({name: getRoomName(),               if (Browser.isSafariWebRTC()) record: isRecord()}).on(ROOM_EVENT.STATE, function(room){
                    Flashphoner.playFirstVideo(pDisplay, false, PRELOADER_URL).then(function() ...
}).on(ROOM_EVENT.JOINED, function(participant){
                        playStream(participant, pDisplay);...
}).on(ROOM_EVENT.LEFT, function(participant){
                    ...
}).catch(function (error) on(ROOM_EVENT.PUBLISHED, function(participant){
     playParticipantsStream(participant);
}).on(ROOM_EVENT.FAILED, function(room, info){
     ...
}).on(ROOM_EVENT.MESSAGE, function(message){
     ...
});

11. Low Power Mode checking before playback on mobile device

Flashphoner.playFirstVideo() code

Code Block
languagejs
themeRDark
      // Low Power Mode detected, user action is needed to start playback in this mode #WCS-2639
if (Browser.isSafariWebRTC()) {
                    Flashphoner.playFirstVideo(pDisplay, false, PRELOADER_URL).then(function() {
    console.log("Can't atomatically play participant" + participant.name() + " stream, use Play button");
                    playStream(participant, pDisplay);
               for (var i = 0; i < pDisplay.children.length; i++}).catch(function (error) {
                        // Low Power Mode detected, if (pDisplay.children[i]) {
        user action is needed to start playback in this mode #WCS-2639
                        console.log("removeCan't cachedatomatically instanceplay id participant" + pDisplay.children[i].idparticipant.name() + " stream, use Play button");
                        for (var i = 0; i <  pDisplay.removeChild(pDisplay.children[i]);children.length; i++) {
                            }
  if (pDisplay.children[i]) {
                      }
           console.log("remove cached instance id " + pDisplay.children[i].id);
             onParticipantStopped(participant                   pDisplay.removeChild(pDisplay.children[i]);
                    });
        }
                        }

...


                        onParticipantStopped(participant);
                    });
                }

12. Playback of video stream.

participant.play() code

The following parameters are passed to the method:

  • display - div element to display remote video;
  • options.unmutePlayOnStart - enables (by default) or disables (for example, in Android Edge) automatic audio unmuting while starting playback;
  • options.constraints.audio.deviceId - audio output device Id (the example uses default audio device)

A user must click a button if automatic audio playback is disabled

...

languagejs
themeRDark

...

button if automatic audio playback is disabled

Code Block
languagejs
themeRDark
        var options = {
            unmutePlayOnStart: true,
            constraints: {
                audio: {
                    deviceId: 'default'
                }
            }
        };
        // Leave participant stream muted in Android Edge browser #WCS-3445
        if (Browser.isChromiumEdge() && Browser.isAndroid()) {
            options.unmutePlayOnStart = false;
        }
        participant.getStreams()[0].play(display, options).on(STREAM_STATUS.PLAYING, function (playingStream) {
            var video = document.getElementById(playingStream.id())
            video.addEventListener('resize', function (event) {
                resizeVideo(event.target);
            });
            // Set up participant Stop/Play button
            if (playBtn) {
                $(playBtn).text("Stop").off('click').click(function() {
                    $(this).prop('disabled', true);
                    playingStream.stop();
                }).prop('disabled', false);
            }
            // Set up participant audio toggle button #WCS-3445
            if (audioBtn) {
                $(audioBtn).text("Audio").off('click').click(function() {
                    if (playingStream.isRemoteAudioMuted()) {
            document.getElementById(playingStream.id()).addEventListener('resize', function (event) {
            playingStream.unmuteRemoteAudio();
                    } else {
               resizeVideo(event.target);
         }playingStream.muteRemoteAudio();
        if (button) {
            $(button).text("Stop").off('click').click(function(){}
                $(this}).prop('disabled', true);'disabled', false);
            }
            // Start participant audio state checking  playingStream.stop();timer #WCS-3445
            })participantState.prop('disabled', falsestartMutedCheck(playingStream);
        }
    }).on(STREAM_STATUS.STOPPED, function () {
            onParticipantStopped(participant);
        }).on(STREAM_STATUS.FAILED, function () {
            onParticipantStopped(participant);
        });

1213. 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);
    ...
}

1314. Receiving the event confirming successful streaming stop

StreamStatusEvent UNPUBLISHED code

Code Block
languagejs
themeRDark
room.publish({
    display: display,
    constraints: constraints,
    record: false,
    receiveVideo: false,
    receiveAudio: false
}).on(STREAM_STATUS.FAILED, function (stream) {
    ...
}).on(STREAM_STATUS.PUBLISHING, function (stream) {
    ...
}).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
    setStatus("#localStatus", stream.status());
    onMediaStopped(room);
});

1415. 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);
    ...
}

1516. 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);
}

1617. Sending text message.

participant.sendMessage() code

When Send button is clicked,

...