...
Объявление конфигурации комнаты и публикации потоков по умолчанию, на случай, если нет файла конфигурации config.json
code
Клиент настраивается на соединение с сервером по WSS по адресу localhost для входа в комнату "ROOM1" с пин-кодом "1234" под именем "Alice". Секция media задает публикацию аудио и видео дорожек. Видео публикуется двумя дорожками с качествами high (h) и medium (m)
Code Block |
---|
|
const defaultConfig = {
room: {
url: "wss://127.0.0.1:8888",
name: "ROOM1",
pin: "1234",
nickName: "Alice"
},
media: {
audio: {
tracks: [
{
source: "mic",
channels: 1
}
]
},
video: {
tracks: [
{
source: "camera",
width: 1280,
height: 720,
codec: "H264",
encodings: [
{ rid: "hm", active: true, maxBitrate: 900000300000, scaleResolutionDownBy: 2},
{ rid: "mh", active: true, maxBitrate: 300000, scaleResolutionDownBy: 2 900000}
]
}
]
}
}
}; |
Отметим, что, начиная со сборки 2.0.248, качества должны быть перечислены по возрастанию
3. Инициализация
init() code
Функция init() вызывается после того, как страница загрузится. Функция загружает config.json или конфигурацию по умолчанию, создает элемент для отображения локального видео и открывает модальное окно входа
Code Block |
---|
|
/**
* Load loadtrack configconfiguration and show entrance modal
*/
const init = function () {
//read config
$.getJSON("config.json", function (config) {
cControls = createControls(config);
}).fail(function () {
//use default config
cControls = createControls(defaultConfig);
});
//create local display to show local streams
localDisplay = initLocalDisplay(document.getElementById("localDisplay"));
//open entrance modal
$('#entranceModal').modal('show');
} |
4. Соединение с сервером и создание либо вход в комнату
connect() code
Функция вызывается по щелчку пользователя по кнопке Enter в модальном окне входа
Code Block |
---|
|
/**
* connectConnect to server and publish preconfigured streams
*/
async function connect() {
// hide modal
$('#entranceModal').modal('hide');
// disable controls
cControls.muteInput();
//create peer connection
const pc = new RTCPeerConnection();
//get config object for room creation
const roomConfig = cControls.roomConfig();
roomConfig.pc = pc;
//kick off connect //kick off connect to server and local room creation
try {
const session = await sfu.createRoom(roomConfig);
session.on(constants.SFU_EVENT.CONNECTED, function(room) {
// Now we //connected to the server
(if no exception was thrown)
const chatDiv = document.getElementById('messages');
session.on(constants.SFU_EVENT.FAILED, function (e) {
const chatInput =if document.getElementById('localMessage');
(e.status && e.statusText) {
const chatButton = document.getElementById('sendMessage');
//create and bind chat to the new room
displayError("CONNECTION FAILED: " + e.status + " " + e.statusText);
createChat(room, chatDiv, chatInput, chatButton);
} else if (e.type && e.info) {
room.on(constants.SFU_ROOM_EVENT.FAILED, function(e) {
displayError("CONNECTION FAILED: " const errField = document.getElementById("errorMsg"+ e.info);
errField.style.color = "red";} else {
errField.innerText = e;
displayError("CONNECTION FAILED: " + e);
}
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILEDDISCONNECTED, function (e) {
const errField = document.getElementById("errorMsgdisplayError("DISCONNECTED. Refresh the page to enter the room again");
});
errField.style.color = "red";
const room = session.room();
errField.innerText = e.operation + " failed: " + e.error;
room.on(constants.SFU_ROOM_EVENT.FAILED, function (e) {
}displayError(e);
//setup remote display for showing remote audio/video tracks
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
displayError(e.operation + " constfailed: remoteDisplay" =+ document.getElementById("display"e.error);
initRemoteDisplay(room, remoteDisplay, pc);
})
//get configuredcreate local video display to show local streams
let streamslocalDisplay = cControlsinitLocalDisplay(document.getVideoStreamsgetElementById("localDisplay"));
//combine localdisplay videoaudio streamsand withvideo audiocontrol streamstables
streams.push.apply(streams,await cControls.getAudioStreamsdisplayTables());
//add our local streams to the room (to PeerConnection)
cControls.onTrack(async function (s) {
await streams.forEach(function (s) {
publishNewTrack(room, pc, s);
});
//addcreate and localbind streamchat to localthe new displayroom
const chatDiv = localDisplaydocument.add(s.stream.id, "local", s.streamgetElementById('messages');
const chatInput //add each track to PeerConnection= document.getElementById('localMessage');
const chatButton = s.stream.getTracks().forEach((track) => {document.getElementById('sendMessage');
addTrackToPeerConnection(pc, s.stream, track, s.encodings);createChat(room, chatDiv, chatInput, chatButton);
//setup remote display for showing remote subscribeTrackToEndedEvent(room, track, pc);audio/video tracks
const remoteDisplay }= document.getElementById("display");
});
initDefaultRemoteDisplay(room, remoteDisplay, {quality: true},{thresholds: [
//add callback for the new local stream to the local controls
{parameter: "nackCount", maxLeap: 10},
cControls.onTrack(function (s) {
//add local stream to local display
{parameter: "freezeCount", maxLeap: 10},
localDisplay.add(s.stream.id,{parameter: "localpacketsLost", s.stream); maxLeap: 10}
//add each track to PeerConnection
], abrKeepOnGoodQuality: ABR_KEEP_ON_QUALITY, abrTryForUpperQuality: ABR_TRY_UPPER_QUALITY, interval: ABR_QUALITY_CHECK_PERIOD});
//get s.stream.getTracks().forEach((track) => {configured local video streams
let streams addTrackToPeerConnection(pc, s.stream, track, s.encodings= cControls.getVideoStreams();
//combine local video streams with audio streams
subscribeTrackToEndedEvent(room, track, pc); streams.push.apply(streams, cControls.getAudioStreams());
// Publish preconfigured });streams
publishPreconfiguredStreams(room, pc, streams);
//kickoff renegotiation
} catch (e) {
roomconsole.updateStateerror(e);
});
//join room
room.join(displayError(e);
});
} |
5. Подробнее о функции connect()
Скрытие модального окна входа и отключение полей ввода до установки соединения с сервером
code
Code Block |
---|
|
//hide modal
$('#entranceModal').modal('hide');
//disable controls
cControls.muteInput(); |
Создание объекта PeerConnection и подготовка объекта конфигурации комнаты
code
Code Block |
---|
|
//create peer connection
const pc = new RTCPeerConnection();
//get config object for room creation
const roomConfig = cControls.roomConfig();
roomConfig.pc = pc; |
Создание сессии и установка соединения с сервером
code
Code Block |
---|
|
const session = await sfu.createRoom(roomConfig); |
Подписка на событие события сессии "CONNECTED"
code
Code Block |
---|
|
session.on(constants.SFU_EVENT.CONNECTEDFAILED, function (roome) { |
Инициализация чата после установки соединения
code
Code Block |
---|
|
//connected to server
const chatDiv = document.getElementById('messages');
const chatInput = document.getElementById('localMessage');
const chatButton = document.getElementById('sendMessage');
//create and bind chat to the new room
createChat(room, chatDiv, chatInput, chatButton); |
Подписка на сообщения об ошибках комнаты
code
Code Block |
---|
|
room.on(constants.SFU_ROOM_EVENT.FAILED, function(e) {
const errField = document.getElementById("errorMsg");
errField.style.color = "red";
errField.innerText = e;
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
const errField = document.getElementById("errorMsg");
errField.style.color = "red";
errField.innerText = e.operation + " failed: " + e.error;
}) |
Инициализация объекта для отображения потоков от других участников
code
Code Block |
---|
|
//setup remote display for showing remote audio/video tracks
const remoteDisplay = document.getElementById("display");
initRemoteDisplay(room, remoteDisplay, pc); |
Получение настроек публикации локального медиа
code
Code Block |
---|
|
//get configured local video streams
let streams = cControls.getVideoStreams();
//combine local video streams with audio streams
streams.push.apply(streams, cControls.getAudioStreams()); |
Добавление каждого потока в объект localDisplay для отображения и в объект PeerConnection для публикации
code
Code Block |
---|
|
if (e.status && e.statusText) {
//add our local streams to the room (to PeerConnection)
displayError("CONNECTION FAILED: " + e.status + " " + e.statusText);
} else streams.forEach(function (sif (e.type && e.info) {
//add local stream to local display
displayError("CONNECTION FAILED: " + e.info);
} localDisplay.add(s.stream.id, "local", s.stream);
else {
//add each track to PeerConnection
displayError("CONNECTION FAILED: " + e);
}
s.stream.getTracks().forEach((track) =>}).on(constants.SFU_EVENT.DISCONNECTED, function (e) {
displayError("DISCONNECTED. Refresh the page to if (s.source === "screen") {enter the room again");
}); |
Создание объекта комнаты и подписка на его события
code
Code Block |
---|
|
const config[track.id] room = ssession.source;
room();
room.on(constants.SFU_ROOM_EVENT.FAILED, function }(e) {
addTrackToPeerConnection(pc, s.stream, track, s.encodingsdisplayError(e);
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
subscribeTrackToEndedEvent(room, track, pc);
displayError(e.operation + " failed: " + }e.error);
}); |
...
Создание объекта для рендеринга локального видео
code
Code Block |
---|
|
//add callback for the new local stream to the local controlslocalDisplay = initLocalDisplay(document.getElementById("localDisplay"));
// display audio and video control tables
await cControls.displayTables();
cControls.onTrack(async function (s) {
let config = {}await publishNewTrack(room, pc, s);
}); |
Создание чата
code
Code Block |
---|
|
//add local stream to localconst display
chatDiv = document.getElementById('messages');
const localDisplay.add(s.stream.id, "local", s.streamchatInput = document.getElementById('localMessage');
const chatButton //add each track to PeerConnection= document.getElementById('sendMessage');
createChat(room, chatDiv, s.stream.getTracks().forEach((track) => {
chatInput, chatButton); |
Инициализация объекта для отображения потоков от других участников
code
Code Block |
---|
|
const remoteDisplay = document.getElementById("display");
if initDefaultRemoteDisplay(s.source === "screen") {room, remoteDisplay, {quality: true},{thresholds: [
{parameter: "nackCount", maxLeap: config[track.id] = s.source;
10},
{parameter: "freezeCount", maxLeap: 10},
addTrackToPeerConnection(pc, s.stream, track, s.encodings);{parameter: "packetsLost", maxLeap: 10}
], abrKeepOnGoodQuality: ABR_KEEP_ON_QUALITY, subscribeTrackToEndedEvent(room, track, pc);
abrTryForUpperQuality: ABR_TRY_UPPER_QUALITY, interval: ABR_QUALITY_CHECK_PERIOD}); |
Получение настроек публикации локального медиа и публикация треков согласно настройкам
code
Code Block |
---|
|
let streams }= cControls.getVideoStreams();
//combine local video //kickoff renegotiation
streams with audio streams
room.updateState(configstreams.push.apply(streams, cControls.getAudioStreams());
}); |
Настройка WebRTC соединения в комнате
code
Code Block |
---|
|
//join room
room.join(pc, null, config); // Publish preconfigured streams
publishPreconfiguredStreams(room, pc, streams); |
6. Завершение публикации потока
...