...
Для работы с исходным кодом примера возьмем версию файла player.js
, доступную здесь
1. Локальные переменные
Объявление локальных переменных для работы с константами, SFU SDK, для отображения видео и работы с конфигурацией клиента
Code Block | ||||
---|---|---|---|---|
| ||||
const constants = SFU.constants;
const sfu = SFU;
const PRELOADER_URL="../commons/media/silence.mp3";
const playStatus = "playStatus";
const playErrorInfo = "playErrorInfo"; |
2. Объект для хранения текущего состояния проигрывания
Хранит данные Websocket сессии, WebRTC соединения, SFU комнаты и объекта для отображения аудио и видео
Code Block | ||||
---|---|---|---|---|
| ||||
const CurrentState = function() { let state = { pc: null, session: null, room: null, remoteDisplay: null, roomEnded: false, set: function(pc, session, room) { state.pc = pc; state.session = session; state.room = room; state.roomEnded = false; }, clear: function() { state.room = null; state.session = null; state.pc = null; }, state.roomEnded = false; setDisplay}, setRoomEnded: function(display) { state.remoteDisplayroomEnded = displaytrue; }, disposeDisplayisRoomEnded: function() { ifreturn (state.remoteDisplay) { roomEnded; }, state.remoteDisplay.stopisConnected: function(); { return (state.session && state.session.remoteDisplaystate() === nullconstants.SFU_STATE.CONNECTED); }, } isActive: function() { } }; return state; } |
3. Инициализация
init() code
Функция init() вызывается после того, как страница загрузится:
- инициализирует объекты состояния
- инициализирует поля ввода
Code Block | ||||
---|---|---|---|---|
| ||||
const init = function() {
$("#playBtn").prop('disabled', true);
$("#url").prop('disabled', true);
$("#streamName").prop('disabled', true);
onDisconnected(CurrentState());
$("#url").val(setURL());
} |
4. Соединение с сервером
connect(), SFU.createRoom() code
Функция connect() вызывается по нажатию кнопки Play:
- создает объект PeerConnection
- очищает отображение статуса предыдущей сессии
- настраивает конфигурацию комнаты и создает Websocket сессию
- подписывается на события Websocket сессии
Code Block | ||||
---|---|---|---|---|
| ||||
const connect = function(state) { // Create peer connection let pc = new RTCPeerConnection(); // Create a config to connect to SFU room const roomConfig = { // Server websocket URL url:return (state.room && !state.roomEnded && state.pc); }, setDisplay: function(display) { state.remoteDisplay = display; }, disposeDisplay: function() { if (state.remoteDisplay) { state.remoteDisplay.stop(); state.remoteDisplay = null; } } }; return state; } |
3. Инициализация
init() code
Функция init() вызывается после того, как страница загрузится:
- инициализирует объекты состояния
- инициализирует поля ввода
Code Block | ||||
---|---|---|---|---|
| ||||
const init = function() { $("#playBtn").prop('disabled', true); $("#url").val(),prop('disabled', true); // Use stream name as room name to play ABR roomName:$("#streamName").prop('disabled', true); onDisconnected(CurrentState()); $("#streamName#url").val(setURL()), // Make a random participant name from stream name nickname: "Player-" + $("#streamName").val() + "-" + createUUID(4), // Set room pin pin: 123456 } // Clean state display items setStatus("playStatus", ""); setStatus("playErrorInfo", ""); // Connect to the server (room should already exist) const session = sfu.createRoom(roomConfig); session.on(constants.SFU_EVENT.CONNECTED, function() {; } |
4. Соединение с сервером
RTCPeerConnection(), SFU.createRoom() code
Функция connect() вызывается по нажатию кнопки Play:
- создает объект PeerConnection
- очищает отображение статуса предыдущей сессии
- настраивает конфигурацию комнаты и создает Websocket сессию
- подписывается на события Websocket сессии
Code Block | ||||
---|---|---|---|---|
| ||||
const connect = async function(state) { // Create peer connection let pc = new RTCPeerConnection(); // Create a config to connect to SFU room const roomConfig = { // Server websocket URL url: $("#url").val(), state.set(pc, session, session.room()); onConnected(state); // Use stream name as room name to play ABR roomName: setStatus$("playStatus#streamName").val(), "CONNECTING...", "black"); }).on(constants.SFU_EVENT.DISCONNECTED, function() { state.clear(); // Make a random participant name from stream name onDisconnected(state); setStatus("playStatus", "DISCONNECTED", "green"); }).on(constants.SFU_EVENT.FAILED, function(e) { state.clear(); onDisconnected(state); nickname: "Player-" + $("#streamName").val() + "-" + createUUID(4), // Set room pin pin: 123456 } // Clean state display items setStatus("playStatus", "FAILED""); setStatus(playErrorInfo, "red"); try { setStatus("playErrorInfo", e.status + " " + e.statusText, "red"); }); } |
5. Запуск проигрывания при установке соединения
onConnected() code
Функция onConnected():
- настраивает действия по нажатию кнопки Stop
- подписывается на событие SFU_ROOM_EVENT.PARTICIPANT_LIST для проверки, опубликован ли поток в SFU комнате
- подписывается на события об ошибках комнаты
- вызывает функцию проигрывания
Code Block | ||||
---|---|---|---|---|
| ||||
const onConnected = function(state) { $("#playBtn").text("Stop").off('click').click(function // Connect to the server (room should already exist) const session = await sfu.createRoom(roomConfig); // Set up session ending events session.on(constants.SFU_EVENT.DISCONNECTED, function() { onStopClick(state); }).prop('disabled', false onDisconnected(state); $('#url').prop('disabled', true); setStatus(playStatus, $("#streamName").prop('disabled'DISCONNECTED", true"green"); // Add room event handling state.room }).on(constants.SFU_ROOM_EVENT.PARTICIPANT_LISTFAILED, function(e) { // If the room is empty, the stream is not published yet if(!e.participants || e.participants.length === 0) { setStatus("playErrorInfo", "ABR stream is not published", "red"); onStopClick(state); onDisconnected(state); setStatus(playStatus, "FAILED", "red"); if (e.status && e.statusText) { setStatus(playErrorInfo, e.status + " " + e.statusText, "red"); } else if (e.type && e.info) { setStatus(playErrorInfo, e.type + ": " + e.info, "red"); } }); // Connected successfully onConnected(state, pc, session); setStatus(playStatus, "CONNECTING...", "black"); } catch(e) { onDisconnected(state); setStatus(playStatus, "FAILED", "red"); setStatus(playErrorInfo, e, "red"); } } |
5. Запуск проигрывания при установке соединения
onConnected() code
Функция onConnected():
- настраивает действия по нажатию кнопки Stop
- подписывается на событие SFU_ROOM_EVENT.PARTICIPANT_LIST для проверки, опубликован ли поток в SFU комнате
- подписывается на события об ошибках комнаты
- вызывает функцию проигрывания
Code Block | ||||
---|---|---|---|---|
| ||||
const onConnected = async function(state, pc, session) {
state.set(pc, session, session.room());
$("#playBtn").text("Stop").off('click').click(function () {
onStopClick(state);
});
$('#url').prop('disabled', true);
$("#streamName").prop('disabled', true);
// Add room event handling
state.room.on(constants.SFU_ROOM_EVENT.PARTICIPANT_LIST, function(e) {
// If the room is empty, the stream is not published yet
if (!e.participants || e.participants.length === 0) {
setStatus(playErrorInfo, "ABR stream is not published", "red");
onStopClick(state);
}
else {
setStatus(playStatus, "ESTABLISHED", "green");
$("#placeholder").hide();
}
}).on(constants.SFU_ROOM_EVENT.FAILED, function(e) {
// Display error state
setStatus(playErrorInfo, e, "red");
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
onOperationFailed(state);
}).on(constants.SFU_ROOM_EVENT.ENDED, function () {
// Publishing is stopped, dispose playback and close connection
setStatus(playErrorInfo, "ABR stream is stopped", "red");
state.setRoomEnded();
onStopClick(state);
}).on(constants.SFU_ROOM_EVENT.DROPPED, function () {
// Client dropped from the room, dispose playback and close connection
setStatus(playErrorInfo, "Playback is dropped due to network issues", "red");
state.setRoomEnded();
onStopClick(state);
});
await playStreams(state);
// Enable button after starting playback #WCS-3635
$("#playBtn").prop('disabled', false);
} |
6. Проигрывание потоков
initRemoteDisplay(), SFURoom.join() code
Функция playStreams():
- инициализирует базовый элемент для отображения входящих медиа потоков
- настраивает параметры отображения информации о входящих потоках
- настраивает ABR для переключения между доступными качествами видео при изменении параметров канала
- настраивает WebRTC соедиение в SFU комнате
Code Block | ||||
---|---|---|---|---|
| ||||
const playStreams = async function(state) { try { // Create remote display onStopClick(state);item to show remote streams } state.setDisplay(initRemoteDisplay({ else {div: document.getElementById("remoteVideo"), setStatus("playStatus", "ESTABLISHED", "green");room: state.room, $("#placeholder").hide();peerConnection: state.pc, } }).on(constants.SFU_ROOM_EVENT.FAILED, function(e)displayOptions: { // Display errorpublisher: statefalse, setStatus("playErrorInfo", e, "red"); }).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) { quality: true, // Display the operationtype: failedfalse, setStatus("playErrorInfo", e.operation + " failed: " + e.error, "red");abr: true, }).on(constants.SFU_ROOM_EVENT.ENDED, function () { // Publishing isabrKeepOnGoodQuality: stopped20000, dispose playback and close connection setStatus("playErrorInfo", "ABR stream is stopped", "red");abrTryForUpperQuality: 30000 onStopClick(state); }); playStreams(state); } |
6. Проигрывание потоков
playStreams(), SFURoom.join() code
Функция playStreams():
- инициализирует базовый элемент для отображения входящих медиа потоков
- настраивает WebRTC соедиение в SFU комнате
Code Block | ||||
---|---|---|---|---|
| ||||
const playStreams = function(state) { })); // CreateStart remoteWebRTC displaynegotiation item to show remote streams await state.room.setDisplay(initRemoteDisplay(join(state.pc); } catch(e) { div: document.getElementById("remoteVideo"), if (e.type === constants.SFU_ROOM_EVENT.OPERATION_FAILED) { room: onOperationFailed(state.room, e); } peerConnection: state.pc, else { displayOptions: { console.error("Failed to play streams: " + e); publisher: false,setStatus(playErrorInfo, e.name, "red"); quality: trueonStopClick(state); } })); state.room.join(state.pc); } |
7. Остановка проигрывания
stopStreams(), CurrentState.disposeDisplay() code
Code Block | ||||
---|---|---|---|---|
| ||||
const stopStreams = function(state) { state.disposeDisplay(); } |
...
onStartClick(), playFirstSound(), connect() code
Функция onStartClick():
- проверяет правильность заполнения полей ввода
- перед стартом воспроизведения, в браузере Safari вызывает функцию playFirstSound() для автоматического проигрывания аудио
- вызывает функцию connect()
...
onStopClick(), Session.disconnect() code
Функция onStopClick():
- останавливает публикацию или воспроизведение
- разрывает Websocket сессию
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| const onStopClick = function(state
| |||||||
const onStopClick = async function(state) { stopStreams(state); if (state.isConnected()) { $("#playBtn").prop('disabled', true); stopStreams(state); await state.session.disconnect(); onDisconnected(state); } } |
10. Действия при разрыве Websocket сессии
onDisconnected() code
Функция onDisconnected():
...
Code Block | ||||
---|---|---|---|---|
| ||||
const onDisconnected = function(state) {
state.clear();
$("#placeholder").show();
$("#playBtn").text("Play").off('click').click(function () {
onStartClick(state);
}).prop('disabled', false);
$('#url').prop('disabled', false);
$("#streamName").prop('disabled', false);
} |