Overview
Conference React application shows how to use Web SDK and RoomApi in React application to publish and play WebRTC streams in chat room
The project is available on GitHub, in Web SDK build archives since build 2.0.201 by the following path examples/react/conference-react.
Building the project
1. Download WebSDK source code
git clone https://github.com/flashphoner/flashphoner_client.git
2. Go to the example folder
cd flashphoner_client/examples/react/conference-react
3. Install dependencies
npm install
4. Build for local testing
npm start
or to deploy to your web server
npm run build
Analyzing example code
To analyze the code take version with hash 456b1c7 which is available here and in Web SDK build 2.0.201
Application code is in ConferenceApp.js file, additional functions are in fp-utils.js file
1. API import
import * as Flashphoner from '@flashphoner/websdk/src/flashphoner-core.js'; import * as RoomApi from '@flashphoner/websdk/src/room-module.js'; import * as FPUtils from './fp-utils.js';
2. API initialization
Flashphoner.init() code
componentDidMount() { try { Flashphoner.init({}); ... } catch(e) { console.log(e); ... } }
3. Connecting to the server and receving the event confirming connection is established successfully
RoomApi.connect(), SESSION_STATUS.ESTABLISHED code
createConnection = (url, username) => { let app = this; let session = this.state.session; if (session && session.status() === SESSION_STATUS.ESTABLISHED) { ... } else { console.log("Create new RoomApi session with url " + url + ", login " + username); app.setState({joinButtonDisabled: true, serverUrlDisabled: true}); RoomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.ESTABLISHED, (session) => { app.setState({session: session, sessionStatus: SESSION_STATUS.ESTABLISHED, sessionStatusClass: 'text-success'}); app.joinRoom(session); }).on(SESSION_STATUS.DISCONNECTED, () => { ... }).on(SESSION_STATUS.FAILED, () => { ... }); } }
4. Enter participant to the room, receiving room state
connection.join(), ROOM_EVENT.STATE code
The following parameters are passed to connection.join() function:
- room name
- should room streams be written to multiple recorder file
joinRoom = (session) => { let app = this; let roomName = this.getRoomName(); let record = this.state.record; console.log("Join the room " + roomName + ", record " + record); session.join({name: roomName, record: record}).on(ROOM_EVENT.STATE, (room) => { let roomParticipants = room.getParticipants(); let participantsNumber = roomParticipants.length; console.log("Current number of participants in the room: " + participantsNumber); if (roomParticipants.length >= maxParticipants) { console.warn("Current room is full"); app.setState({sessionFailedInfo: "Current room is full"}); room.leave().then(() => {app.onLeft();}, () => {app.onLeft();}); return false; } app.setInviteUrl(roomName); if (participantsNumber > 0) { let chatState = "participants: "; for (let i = 0; i < participantsNumber; i++) { app.installParticipant(roomParticipants[i]); chatState += roomParticipants[i].name(); if (i < participantsNumber - 1) { chatState += ","; } } app.addMessage("chat", chatState); } else { app.addMessage("chat", " room is empty"); } ... app.publishLocalMedia(room); app.onJoined(room); ... }); }
5. Publishing stream to the room
Room.publish() code
publishLocalMedia = (room) => { let app = this; let constraints = { audio: true, video: true }; let display = document.getElementById("localDisplay"); app.setState({publishButtonDisabled: true}); room.publish({ display: display, constraints: constraints, record: false, receiveVideo: false, receiveAudio: false ... }); }
6, Receiving the event confirming the stream is successfully published
STREAM_STATUS.PUBLISHING code
publishLocalMedia = (room) => { ... room.publish({ display: display, constraints: constraints, record: false, receiveVideo: false, receiveAudio: false }).on(STREAM_STATUS.FAILED, (stream) => { ... }).on(STREAM_STATUS.PUBLISHING, (stream) => { app.setState({publishStatus: STREAM_STATUS.PUBLISHING, publishStatusClass: 'text-success'}); app.onMediaPublished(stream); }).on(STREAM_STATUS.UNPUBLISHED, (stream) => { ... }); }
7. Receiving the event about a participant joining the room
ROOM_EVENT.JOINED code
joinRoom = (session) => { let app = this; let roomName = this.getRoomName(); let record = this.state.record; console.log("Join the room " + roomName + ", record " + record); session.join({name: roomName, record: record}).on(ROOM_EVENT.STATE, (room) => { ... }).on(ROOM_EVENT.JOINED, (participant) => { app.installParticipant(participant); app.addMessage(participant.name(), "joined"); }).on(ROOM_EVENT.LEFT, function(participant) { ... }).on(ROOM_EVENT.PUBLISHED, (participant) => { ... }).on(ROOM_EVENT.FAILED, (room, info) => { ... }).on(ROOM_EVENT.MESSAGE, (message) => { ... }); }
8. Receiving the event about a participant publishing a stream
ROOM_EVENT.PUBLISHED code
joinRoom = (session) => { let app = this; let roomName = this.getRoomName(); let record = this.state.record; console.log("Join the room " + roomName + ", record " + record); session.join({name: roomName, record: record}).on(ROOM_EVENT.STATE, (room) => { ... }).on(ROOM_EVENT.JOINED, (participant) => { ... }).on(ROOM_EVENT.LEFT, function(participant) { ... }).on(ROOM_EVENT.PUBLISHED, (participant) => { app.playParticipantsStream(participant); }).on(ROOM_EVENT.FAILED, (room, info) => { ... }).on(ROOM_EVENT.MESSAGE, (message) => { ... }); }
9. Playing participant stream with resizing the stream picture to div
Stream.play(), STREAM_STATUS_PLAYING, FPUtils.resizeVideo() code
playStream = (stream, remoteVideo, name) => { let app = this; let participantStream = null; participantStream = stream.play(remoteVideo).on(STREAM_STATUS.PLAYING, (playingStream) => { let video = document.getElementById(playingStream.id()); if (video) { video.addEventListener('resize', (event) => { FPUtils.resizeVideo(event.target); }); } }); app.setParticipantStream(name, participantStream); }
10. Sending a text message to all the participants
Participant.sendMessage() code
onSendClick = () => { let session = this.state.session; let room = this.state.room; let message = this.state.message; if (session && room) { let participants = room.getParticipants(); this.addMessage(session.username(), message); for (let i = 0; i < participants.length; i++) { participants[i].sendMessage(encodeURIComponent(message)); } this.setState({message: ''}); } }
11. Receiving text message from other participant
ROOM_EVENT.MESSAGE code
joinRoom = (session) => { let app = this; let roomName = this.getRoomName(); let record = this.state.record; console.log("Join the room " + roomName + ", record " + record); session.join({name: roomName, record: record}).on(ROOM_EVENT.STATE, (room) => { ... }).on(ROOM_EVENT.JOINED, (participant) => { ... }).on(ROOM_EVENT.LEFT, function(participant) { ... }).on(ROOM_EVENT.PUBLISHED, (participant) => { ... }).on(ROOM_EVENT.FAILED, (room, info) => { ... }).on(ROOM_EVENT.MESSAGE, (message) => { if (message.from && message.text) { app.addMessage(message.from.name(), decodeURIComponent(message.text)); } }); }
12. Receiving the event about participant is left the room
ROOM_EVENT.LEFT code
joinRoom = (session) => { let app = this; let roomName = this.getRoomName(); let record = this.state.record; console.log("Join the room " + roomName + ", record " + record); session.join({name: roomName, record: record}).on(ROOM_EVENT.STATE, (room) => { ... }).on(ROOM_EVENT.JOINED, (participant) => { ... }).on(ROOM_EVENT.LEFT, function(participant) { app.removeParticipant(participant); app.addMessage(participant.name(), "left"); }).on(ROOM_EVENT.PUBLISHED, (participant) => { ... }).on(ROOM_EVENT.FAILED, (room, info) => { ... }).on(ROOM_EVENT.MESSAGE, (message) => { ... }); }
13. Stopping stream publishing
Stream.stop() code
onPublishClick = () => { let stream = this.state.publishStream; let room = this.state.room; if (!room) return; this.setState({publishButtonDisabled: true}); if (!stream) { this.publishLocalMedia(room); } else { stream.stop(); } };
14. Leaving the room
Room.leave() code
onJoinClick = () => { let app = this; ... let room = this.state.room; let participants = this.state.participants; if (!room) { ... } else { this.setState({joinButtonDisabled: true}, () => { participants.forEach((participant) => { // Stop all the playing participants streams app.stopParticipantStream(participant.stream); }); room.leave().then(() => {app.onLeft();}, () => {app.onLeft();}); }); } };