Описание
Приложение Conference React показывает пример использования Web SDK и RoomApi в React приложении для публикации и проигрывания WebRTC потоков в чат-комнате
Проект доступен на GitHub, а также в архивах сборок Web SDK по следующему пути examples/react/conference-react, начиная со сборки 2.0.201.
Сборка проекта
1. Загрузите исходные тексты WebSDK
git clone https://github.com/flashphoner/flashphoner_client.git
2. Перейдите в каталог примера
cd flashphoner_client/examples/react/conference-react
3. Установите зависимости
npm install
4. Запустите сборку для локального тестирования
npm start
или для выгрузки на свой веб-сервер
npm run build
Работа с кодом примера
Для разбора исходного кода примера возьмем версию с хэшем 456b1c7, которая доступна здесь, а также в сборке Web SDK 2.0.201
Код приложения расположен в файле ConferenceApp.js, дополнительные функции в файле fp-utils.js
1. Импорт API
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
Flashphoner.init() code
componentDidMount() { try { Flashphoner.init({}); ... } catch(e) { console.log(e); ... } }
3. Установка соединения с сервером, получение события, подтверждающего установку соединения
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. Вход участника в комнату, получение текущего состояния комнаты
connection.join(), ROOM_EVENT.STATE code
Функции connection.join() передаются параметры:
- имя комнаты
- признак записи потоков в комнате в один файл
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. Публикация потока в комнате
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, Получение сообщения, подтверждающего публикацию
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. Получение события о присоединении участника к комнате
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. Получение события о публикации потока участником
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. Воспроизведение потока участника, изменение размеров картинки под 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. Отправка сообщения участникам
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. Получение сообщения от другого участника
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. Получение сообщения о выходе другого участника из комнаты
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. Остановка публикации потока
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. Выход участника из комнаты
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();}); }); } };