Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Для работы с исходным кодом примера возьмем версию файла player.js, доступную здесь

1. Локальные переменные

Объявление локальных переменных для работы с константами, SFU SDK, для отображения видео и работы с конфигурацией клиента

code

Code Block
languagejs
themeRDark
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

Code Block
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
const stopStreams = function(state) {
    state.disposeDisplay();
}

...

onStartClick(), playFirstSound(), connect() code

Функция onStartClick():

  • проверяет правильность заполнения полей ввода
  • перед стартом воспроизведения, в браузере Safari  вызывает функцию playFirstSound() для автоматического проигрывания аудио
  • вызывает функцию connect()

...

onStopClick(), Session.disconnect() code

Функция onStopClick():

  • останавливает публикацию или воспроизведение
  • разрывает Websocket сессию
const onStopClick = function(state
Code Block
languagejs
themeRDark
themeRDark
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
languagejs
themeRDark
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);
}