...
Supported platforms and browsers
Chrome | Firefox | Safari 11 | Chromium Edge | ||
---|---|---|---|---|---|
Windows | + | + | + | ||
Mac OS | + | + | + | ||
Android | + | + | + | ||
iOS | - | -+ (iOS 14.6+) | + (iOS 14.6+) | + |
Supported codecs
- Video: H.264, VP8
- Audio: Opus, G.711
...
Below is the call flow when using the Conference example.
1. Participant 1 establishes a connection to the server.
FlashphonerRoomApi.roomApi.connect(); code
Code Block | ||||
---|---|---|---|---|
| ||||
connection = Flashphoner.roomApiRoomApi.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(); }); |
...
2. Participant 1 receives from the server an event confirming successful connection.
ConnectionStatusEvent ESTABLISHED ESTABLISHED code
Code Block | ||||
---|---|---|---|---|
| ||||
connection = Flashphoner.roomApiRoomApi.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()); joinRoom(); }); |
...
3. Participant 1 enters the chat room.
connection.join(); code
Code Block | ||||
---|---|---|---|---|
| ||||
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){ ... }); |
...
4. Participant 1 receives from the server an event describing the state of the room.
RoomStatusEvent STATE STATE code
Code Block | ||||
---|---|---|---|---|
| ||||
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) { 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 - 1) { chatState += ","; } } addMessage("chat", chatState); } else { addMessage("chat", " room is empty"); } publishLocalMedia(room); onJoined(room); ... }); |
...
5. Participant 1 publishes the media stream.
room.publish(); code
Code Block | ||||
---|---|---|---|---|
| ||||
room.publish({ display: display, constraints: constraints, record: false, receiveVideo: false, receiveAudio: false ... }); |
...
6. Participant 1 receives from the server an event confirming successful publishing of the stream.
StreamStatusEvent PUBLISHING PUBLISHING code
Code Block | ||||
---|---|---|---|---|
| ||||
room.publish({ display: display, constraints: constraints, record: false, receiveVideo: false, receiveAudio: false }).on(STREAM_STATUS.FAILED, function (stream) { ... }).on(STREAM_STATUS.PUBLISHING, function (stream) { setStatus("#localStatus", stream.status()); onMediaPublished(stream); }).on(STREAM_STATUS.UNPUBLISHED, function(stream) { ... }); |
...
12. Participant 1 receives from the server an event informing that participant 2 has joined.
RoomStatusEvent JOINED JOINED code
Code Block | ||||
---|---|---|---|---|
| ||||
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){ ... }); |
...
17. Participant 1 leaves the chat room.
room.leave(); code
Code Block | ||||
---|---|---|---|---|
| ||||
function onJoined(room) { $("#joinBtn").text("Leave").off('click').click(function(){ $(this).prop('disabled', true); room.leave().then(onLeft, onLeft); }).prop('disabled', false); ... } |
...
18. Participants of the room receive from the server an event informing that participant 1 has left the room.
RoomStatusEvent LEFT LEFT code
Code Block | ||||
---|---|---|---|---|
| ||||
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){ ... }).on(ROOM_EVENT.JOINED, function(participant){ ... }).on(ROOM_EVENT.LEFT, function(participant){ //remove participant removeParticipant(participant); addMessage(participant.name(), "left"); }).on(ROOM_EVENT.PUBLISHED, function(participant){ ... }).on(ROOM_EVENT.FAILED, function(room, info){ ... }).on(ROOM_EVENT.MESSAGE, function(message){ ... }); |
...
Then play output.mp4.file:
Room multiple streams recording to one file with subsequent mixing
...
Since WCS build 5.2.1012 and WebSDK build 2.0.190 it is possible to record all the room streams to one file, with automatic mixing after finishing a conference. To do this, a first participant should set room record option while creating a room:
...
In thei case, all the room streams will be reocrded to one file. When the last participant leaves the room is finalized, the recording will also be stopped, and the script set in the following parameter will be automatically launched
...
8. Recording file mixing may take a long time depending on recording length, CPU and dick I/O performance. When miximg is done, download the file from /usr/local/FlashphonerWebCallServer/records folder or open in browser by /client/records link
...
Room finalizing
Room exists until at leats one participant is connected. When the last participant calls room.leave() function, the room is finalized.
If the last participant refreshes web page or loses server connection without calling room.leave(), the room will be active during the time interval set by the following parameter in milliseconds
Code Block | ||
---|---|---|
| ||
room_idle_timeout=60000 |
By default, the interval is 60 seconds. When time is expired, the room is finalized.
Known issues
1. Non-latin characters should be encoded while messaging
...
Solution: use JavaScript functions encodeURIComponent() while sending a message
Code Block | ||||
---|---|---|---|---|
| ||||
| ||||
var participants = room.getParticipants(); for (var i = 0; i < participants.length; i++) { participants[i].sendMessage(encodeURIComponent(message)); } |
and decodeURIComponent() while receiving message
Code Block | ||||
---|---|---|---|---|
| ||||
... }).on(ROOM_EVENT.MESSAGE, function(message){ }).on(ROOM_EVENT.MESSAGE, function(message){ addMessage(message.from.name(), decodeURIComponent(message.text)); addMessage(message.from.name(), decodeURIComponent(message.text)); }); ...}); ... |
2. When connection.join() and then room.leave() are called too fast. it is possible to send join command to the server while it still handles previous leave command for this user
Symptoms: when connection.join() is called right after room.leave(), client may receive a message
Code Block | ||
---|---|---|
| ||
Room already has user with such login |
Solution: use at least 1 second interval between room.leave() and connection.join() subsequent calls