Versions Compared

Key

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

...

Для работы с исходным кодом примера возьмем версию файла two-way-streaming.js, доступную здесь, которую также можно загрузить в сборке 1.0.41

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

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

code

Code Block
languagejs
themeRDark
const constants = SFU.constants;
const sfu = SFU;
let mainConfig;
let localDisplay;
let remoteDisplay;
let publishState;
let playState;
const PUBLISH = "publish";
const PLAY = "play";
const STOP = "stop";
const PRELOADER_URL="../commons/media/silence.mp3"

...

Объявление конфигурации комнаты и публикации потоков по умолчанию, на случай, если нет файла конфигурации config.json

code

Code Block
languagejs
themeRDark
const defaultConfig = {
    room: {
        url: "wss://127.0.0.1:8888",
        name: "ROOM1",
        pin: "1234",
        nickName: "User1"
    },
    media: {
        audio: {
            tracks: [
                {
                    source: "mic",
                    channels: 1
                }
            ]
        },
        video: {
            tracks: [
                {
                    source: "camera",
                    width: 640,
                    height: 360,
                    codec: "H264",
                    encodings: [
                        { rid: "360p", active: true, maxBitrate: 500000 },
                        { rid: "180p", active: true, maxBitrate: 200000, scaleResolutionDownBy: 2 }
                    ]
                }
            ]
        }
    }
};

...

Хранит данные Websocket сессии, WebRTC соединения и комнаты, формирует идентификаторы элементов на странице для доступа к ним

code

Code Block
languagejs
themeRDark
const CurrentState = function(prefix) {
    let state = {
        prefix: prefix,
        pc: null,
        session: null,
        room: null,
        timer: null,
        set: function(pc, session, room) {
            state.pc = pc;
            state.session = session;
            state.room = room;
        },
        clear: function() {
            state.stopWaiting();
            state.room = null;
            state.session = null;
            state.pc = null;
        },
        waitFor: function(div, timeout) {
            state.stopWaiting();
            state.timer = setTimeout(function () {
                if (div.innerHTML !== "") {
                    // Enable stop button
                    $("#" + state.buttonId()).prop('disabled', false);
                }
                else if (state.isConnected()) {
                    setStatus(state.errInfoId(), "No media capturing started in " + timeout + " ms, stopping", "red");
                    onStopClick(state);
                }
            }, timeout);        
        },
        stopWaiting: function() {
            if (state.timer) {
                clearTimeout(state.timer);
                state.timer = null;                
            }
        },
        buttonId: function() {
            return state.prefix + "Btn";
        },
        buttonText: function() {
            return (state.prefix.charAt(0).toUpperCase() + state.prefix.slice(1));
        },
        inputId: function() {
            return state.prefix + "Name";
        },
        statusId: function() {
            return state.prefix + "Status";
        },
        formId: function() {
            return state.prefix + "Form";
        },
        errInfoId: function() {
            return state.prefix + "ErrorInfo";
        },
        is: function(value) {
            return (prefix === value);
        },
        isActive: function() {
            return (state.room && state.pc);
        },
        isConnected: function() {
            return (state.session && state.session.state() == constants.SFU_STATE.CONNECTED);
        }
    };
    return state;
}

4. Инициализация

init() code

Функция init() вызывается после того, как страница загрузится:

...

connect(), SFU.createRoom() code

Функция connect() вызывается по нажатию кнопки Publish или Play:

...

6. Запуск публикации или проигрывания при установке соединения

onConnected() code

Функция onConnected():

  • настраивает действия по нажатию кнопки Stop
  • подписывается на события об ошибках комнаты
  • вызывает функцию публикации или проигрывания

...

publishStreams(), SFURoom.join() code

Функция publishStreams():

...

addTrackToPeerConnection(), PeerConnection.addTransceiver() code

Code Block
languagejs
themeRDark
const addTrackToPeerConnection = function(pc, stream, track, encodings) {
    pc.addTransceiver(track, {
        direction: "sendonly",
        streams: [stream],
        sendEncodings: encodings ? encodings : [] //passing encoding types for video simulcast tracks
    });
}

...

subscribeTrackToEndedEvent(), MediaTrack.addEventListener(), SFURoom.updateState() code

Code Block
languagejs
themeRDark
const subscribeTrackToEndedEvent = function(room, track, pc) {
    track.addEventListener("ended", function() {
        //track ended, see if we need to cleanup
        let negotiate = false;
        for (const sender of pc.getSenders()) {
            if (sender.track === track) {
                pc.removeTrack(sender);
                //track found, set renegotiation flag
                negotiate = true;
                break;
            }
        }
        if (negotiate) {
            //kickoff renegotiation
            room.updateState();
        }
    });
};

...

playStreams(), SFURoom.join() code

Функция playStreams():

  • инициализирует базовый элемент для отображения входящих медиа потоков
  • входит в комнату на сервере
Code Block
languagejs
themeRDark
const playStreams = function(state) {
    if (state.isConnected() && state.isActive()) {
        //create remote display item to show remote streams
        remoteDisplay = initRemoteDisplay({
            div: document.getElementById("remoteVideo"),
            room: state.room,
            peerConnection: state.pc
        });
        state.room.join(state.pc);
    }
    $("#" + state.buttonId()).prop('disabled', false);
}

...

unPublishStreams(), localDisplay.stop() code

Code Block
languagejs
themeRDark
const unPublishStreams = function(state) {
    if (localDisplay) {
        localDisplay.stop();
    }
}

...

stopStreams(), remoteDisplay.stop() code

Code Block
languagejs
themeRDark
const stopStreams = function(state) {
    if (remoteDisplay) {
        remoteDisplay.stop();
    }
}

...

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

Функция onStartClick():

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

...

onStopClick(), Session.disconnect() code

Функция onStopClick():

  • останавливает публикацию или воспроизведение
  • разрывает Websocket сессию

...

13. Действия при разрыве Websocket сессии

onDisconnected() code

Функция onDisconnected():

...

14.1. Запуск публикации или проигрывания

startStreaming() code

Code Block
languagejs
themeRDark
const startStreaming = function(state) {
    if (state.is(PUBLISH)) {
        publishStreams(state);
    } else if (state.is(PLAY)) {
        playStreams(state);
    }
}

14.2. Остановка публикации или проигрывания

stopStreaming() code

Code Block
languagejs
themeRDark
const stopStreaming = function(state) {
    state.stopWaiting();
    if (state.is(PUBLISH)) {
        unPublishStreams(state);
    } else if (state.is(PLAY)) {
        stopStreams(state);
    }
}