Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

Описание

Web Call Server позволяет внедрить видеочат, который будет работать в большинстве современных веб-браузеров без установки дополнительного ПО, а также на мобильных устройствах, в ваш веб-проект.

Поддерживаемые платформы и браузеры


Chrome

Firefox

Safari 11

Edge

Windows

+

+


+

Mac OS

+

+

+


Android

+

+



iOS

-

-

+


Поддерживаемые кодеки

  • Видео: H.264, VP8
  • Аудио: Opus, G.711

Функции

  • Видеочат
  • Текстовый чат
  • Видеоконференция
  • Видеоконференция с отображением экрана пользователя

Схема работы


  1. Браузер участника 1 соединяется с сервером по Websocket и отправляет команду join.
  2. Браузер участника 1 может передавать поток по WebRTC для публикации в чат-комнате и получать потоки, опубликованные в комнате
  3. Браузер участника 2 соединяется с сервером при помощи Flash и отправляет команду join.
  4. Браузер участника 2 может передавать поток по RTMP для публикации в чат-комнате и получать потоки, опубликованные в комнате

Видеоконференция

1. Для теста используем:

2. Откройте веб-приложение Conference. В поле "Login" введите произвольное имя пользователя, например test:


3. Нажмите кнопку Join. Установится соединение с сервером, отобразится надпись "ESTABLISHED", будет автоматически создана чат-комната:


Внизу экрана отобразится изображение с веб-камеры, текстовый чат и ссылка на комнату для приглашения других пользователей:


4. Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например, test2, и нажмите кнопку Join. На странице будет показано изображение с веб-камеры участника test (слева) и с веб-камеры участника test2 (внизу):


5. Введите в окне текстового чата участника test2 сообщение и нажмите кнопку Send:


6. На вкладке участника test введите ответное сообщение:


7. Убедитесь, что ответ получен:


8. Для выхода из-чат-комнаты нажмите кнопку Leave.

Видеочат

1. Для теста используем:

2. Откройте веб-приложение Two Way Video Chat. В поле "Login" введите произвольное имя пользователя, например test:


3. Нажмите кнопку Join. Установится соединение с сервером, отобразится надпись "ESTABLISHED", будет автоматически создана чат-комната. Будет показано изображение с веб-камеры:


Внизу экрана отобразится текстовый чат и ссылка на комнату для приглашения других пользователей:


4. Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например, test2, и нажмите кнопку Join. На странице будет показано изображение с веб-камеры пользователя test крупно и с веб-камеры пользователя test2 (внизу слева):


5. Введите в окне текстового чата сообщение и нажмите кнопку Send:


6. На вкладке пользователя test введите ответное сообщение:


7. Убедитесь, что ответ получен:


8. Для выхода из-чат-комнаты нажмите кнопку Leave.

Видеоконференция с отображением экрана компьютера (screen sharing)

1. Для теста используем:

2. Откройте веб-приложение "Two Way Video Chat & Screen". Если активна кнопка Install Now, нажмите ее и установите расширение.
В поле "Login" введите произвольное имя пользователя, например test. Нажмите кнопку Join. Установится соединение с сервером, отобразится надпись "ESTABLISHED", будет автоматически создана чат-комната. Будет показано изображение с веб-камеры:


3. Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например, test2, и нажмите кнопку Join. На странице будет показано изображение с веб-камеры:


4. Нажмите кнопку "Share" и разрешите браузеру доступ к экрану или к окну приложения:


5. На вкладке пользователя test отобразится экран или окно приложения, к которому был разрешен доступ:


6. Для выхода из-чат-комнаты нажмите кнопку "Leave".

Последовательность выполнения операций (Call Flow)

Ниже описана последовательность вызовов при использовании примера Conference

conference.html

conference.js


1. Установка участником 1 соединения с сервером.

Flashphoner.roomApi.connect(); code

    connection = Flashphoner.roomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){
        setStatus('#status', session.status());
        onLeft();
    }).on(SESSION_STATUS.DISCONNECTED, function(session) {
        setStatus('#status', session.status());
        onLeft();
    }).on(SESSION_STATUS.ESTABLISHED, function(session) {
        setStatus('#status', session.status());
        joinRoom();
    });


2. Получение участником 1 от сервера события, подтверждающего успешное соединение.

ConnectionStatusEvent ESTABLISHED code

    connection = Flashphoner.roomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){
        ...
    }).on(SESSION_STATUS.DISCONNECTED, function(session) {
        ...
    }).on(SESSION_STATUS.ESTABLISHED, function(session) {
        setStatus('#status', session.status());
        joinRoom();
    });


3. Вход в чат-комнату участника 1.

connection.join(); code

    connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
        ...
    });


4. Получение участником 1 от сервера события, описывающего состояние комнаты.

RoomStatusEvent STATE code

    connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
        var participants = room.getParticipants();
        console.log("Current number of participants in the room: " + participants.length);
        if (participants.length >= _participants) {
            console.warn("Current room is full");
            $("#failedInfo").text("Current room is full.");
            room.leave().then(onLeft, onLeft);
            return false;
        }
        setInviteAddress(room.name());
        if (participants.length > 0) {
            var chatState = "participants: ";
            for (var i = 0; i < participants.length; i++) {
                installParticipant(participants[i]);
                chatState += participants[i].name();
                if (i != participants.length - 1) {
                    chatState += ",";
                }
            }
            addMessage("chat", chatState);
        } else {
            addMessage("chat", " room is empty");
        }
        publishLocalMedia(room);
        onJoined(room);
        ...
    });


5. Публикация медиапотока участником 1.

room.publish(); code

    room.publish({
        display: display,
        constraints: constraints,
        record: false,
        receiveVideo: false,
        receiveAudio: false
        ...
    });


6. Получение участником 1 от сервера события, подтверждающего успешную публикацию потока.

StreamStatusEvent PUBLISHING code

    room.publish({
        display: display,
        constraints: constraints,
        record: false,
        receiveVideo: false,
        receiveAudio: false
    }).on(STREAM_STATUS.FAILED, function (stream) {
        ...
    }).on(STREAM_STATUS.PUBLISHING, function (stream) {
        setStatus("#localStatus", stream.status());
        onMediaPublished(stream);
    }).on(STREAM_STATUS.UNPUBLISHED, function(stream) {
        ...
    });


7. Отправка участником 1 потока по WebRTC

8. Установка участником 2 соединения с сервером.

9. Получение участником 2 от сервера события, подтверждающего успешное соединение.

10. Вход в чат-комнату участника 2.

11. Получение участником 2 от сервера события, описывающего состояние комнаты.

12. Получение участником 1 от сервера события о присоединении участника 2.

RoomStatusEvent JOINED code

    connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
        ...
    }).on(ROOM_EVENT.JOINED, function(participant){
        installParticipant(participant);
        addMessage(participant.name(), "joined");
    }).on(ROOM_EVENT.LEFT, function(participant){
        ...
    }).on(ROOM_EVENT.PUBLISHED, function(participant){
        ...
    }).on(ROOM_EVENT.FAILED, function(room, info){
        ...
    }).on(ROOM_EVENT.MESSAGE, function(message){
        ...
    });


13. Получение участником 2 потока, опубликованного участником 1.

14. Публикация медиапотока участником 2.

15. Получение участником 2 от сервера события, подтверждающегог успешную публикацию потока.

16. Отправка участником 2 потока по WebRTC и получение его участником 1.

17. Выход участника 1 из чат-комнаты.

room.leave(); code

function onJoined(room) {
    $("#joinBtn").text("Leave").off('click').click(function(){
        $(this).prop('disabled', true);
        room.leave().then(onLeft, onLeft);
    }).prop('disabled', false);
    ...
}


18. Получение участниками комнаты от сервера события о выходе участника 1.

RoomStatusEvent LEFT code

    connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){
        ...
    }).on(ROOM_EVENT.JOINED, function(participant){
        ...
    }).on(ROOM_EVENT.LEFT, function(participant){
        //remove participant
        removeParticipant(participant);
        addMessage(participant.name(), "left");
    }).on(ROOM_EVENT.PUBLISHED, function(participant){
        ...
    }).on(ROOM_EVENT.FAILED, function(room, info){
        ...
    }).on(ROOM_EVENT.MESSAGE, function(message){
        ...
    });

Запись потоков, опубликованных участниками конференции

Видеопотоки, опубликованные каждым из участников конференции, могут быть записаны. Для этого необходимо установить параметр 'record' в 'true' при публикации потока:

    room.publish({
        display: display,
        constraints: constraints,
        record: true,
        receiveVideo: false,
        receiveAudio: false
        ...
    });

Поток от каждого участника записывается в отдельный файл. Особенность этих файлов при дальнейшей обработке в том, что публикация начинается не одновременно. Для того, чтобы дать возможность объединить потоки участников, потоки комнаты синхронизируются по первому опубликованному потоку.

Например, если участник User1 начал публиковать поток в 00:00:10, а участник User2 в 00:00:55, то второй пользователь получит в начале записи 45 секунд пустого видео (черный экран и тишина). Таким образом, файлы записи потоков User1.mp4 и User2.mp4 будут одинаковы по времени, и их можно будет объединить. Кроме того, потоки участников можно направлять в микшер во время публикации.

Тестирование записи потоков

1. Для теста используем:

  • ваш WCS сервер, например test2.flashphoner.com;
  • веб-приложение Conference

2. Включите запись потоков в веб-приложении Conference

3. Откройте веб-приложение Conference. В поле "Login" введите имя пользователя Alice  и нажмите 'Join'. Опубликуется поток от пользователя Alice:

4. Скопируйте ссылку из поля "Invite":

5. В новом окне браузера перейдите по данной ссылке.  В поле "Login" введите имя пользователя Bob и нажмите 'Join'. Отобразится поток от пользователя Alice, и опубликуется поток от пользователя Bob:

6. Нажмите 'Leave' на вкладке пользователя Bob, чтобы выйти из комнаты. Нажмите 'Leave' на вкладке пользователя Alice, чтобы завершить конференцию.

7. В каталоге /usr/local/FlashphonerWebCallServer/records располагаются файлы записи потоков:

-rw-r--r-- 1 root root 1569566 Jun 29 07:51 stream-34296a60-7b36-11e8-bd9c-31aaed48935e-db8mp51bajcidn9qmcnda3967k.mp4
-rw-r--r-- 1 root root 516509 Jun 29 07:51 stream-5aeb2351-7b36-11e8-b398-b74e804508b2-g97j81cgrf8h1m7jl7184fa788.mp4

Файл от пользователя Bob меньшего размера, поскольку в начале файла идет пустое видео для синхронизации. Загрузите файлы на ПК и воспроизведите.

8. Поток от Alice опубликован, Bob еще не вошел в комнату

9. Опубликован поток от Bob

Объединение записанных потоков при помощи ffmpeg

Файлы записей потоков могут быть объединены при помощи ffmpeg с сохранением хронологического порядка. Для этого при создании потока на стороне сервера фиксируется его сдвиг относительно времени создания комнаты. Записанные таким образом файлы потоков объединяются командой (пример для двух участников)

ffmpeg -i stream1.mp4 -i stream2.mp4 -filter_complex "[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid];[0:a][1:a]amerge[a]" -map [vid] -map "[a]" -ac 2 -strict -2 -c:v libx264 -crf 23 -preset veryfast output.mp4

Здесь

  • stream1 - поток первого участника
  • stream2 - поток второго участника

Для того, чтобы объединить файлы, полученные в ходе тестирования, введите команду:

ffmpeg -i stream-34296a60-7b36-11e8-bd9c-31aaed48935e-db8mp51bajcidn9qmcnda3967k.mp4 -i stream-5aeb2351-7b36-11e8-b398-b74e804508b2-g97j81cgrf8h1m7jl7184fa788.mp4 -filter_complex "[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid];[0:a][1:a]amerge[a]" -map [vid] -map "[a]" -ac 2 -strict -2 -c:v libx264 -crf 23 -preset veryfast output.mp4

Воспроизведите файл output.mp4:


  • No labels