Пример клиента для участника многоточечной конференции
Данный пример может использоваться для организации многоточечной видео конференции (MCU) на Web Call Server. Каждый участник такой конференции может публиковать WebRTC-поток и вопроизводить микшированный поток с аудио и видео других участников и собственным видео (без собственного аудио).
Для работы примера требуются следующие настройки в конфиге flashphoner.properties WCS-сервера
mixer_auto_start=true mixer_mcu_audio=true mixer_mcu_video=true
Когда новый участние подключается к конференции, используя данный клиент
- публикуется поток с видео участника и именем <participantName> + "#" + <roomName>
- этот поток добавляется к микшеру с именем <roomName> (если такой микшер еще не существует, то он создается)
- публикуется другой микшер с именем <roomName> + "-" + <participantName> + <roomName>, который содержит видео всех участников (включая данного) и аудио только от других участников, и начанается воспроизведение этого микшера
На скриншоте ниже участник конференции публикует поток и воспроизводит микшированный поток конференции:
Код примера
Код данного примера находится на WCS-сервере по следующему пути:
/usr/local/FlashphonerWebCallServer/client/examples/demo/streaming/mcu_client
mcu_client.css - файл стилей
mcu_client.html - страница участника MCU-конференции
mcu_client.js - скрипт для участия в MCU-конференции
Тестировать данный пример можно по следующему адресу:
https://host:8888/client/examples/demo/streaming/mcu_client/mcu_client.html
Здесь host - адрес WCS-сервера.
Работа с кодом примера
Для разбора кода возьмем файл mcu_client.js, который находится здесь и доступен для скачивания в соответствующей сборке 0.5.28.2753.123.
1. Инициализация API
Flashphoner.init() код
Flashphoner.init({ flashMediaProviderSwfLocation: '../../../../media-provider.swf' });
2. Подключение к серверу
Flashphoner.createSession() код
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function (session) { setStatus(session.status()); //session connected, start playback startStreaming(session); }).on(SESSION_STATUS.DISCONNECTED, function () { setStatus(SESSION_STATUS.DISCONNECTED); onStopped(); }).on(SESSION_STATUS.FAILED, function () { setStatus(SESSION_STATUS.FAILED); onStopped(); })
3. Получение от сервера события, подтверждающего успешное соединение
ConnectionStatusEvent ESTABLISHED код
On receiving the event, streaming is started
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){ setStatus(session.status()); //session connected, start playback startStreaming(session); }).on(SESSION_STATUS.DISCONNECTED, function(){ ... }).on(SESSION_STATUS.FAILED, function(){ ... });
4. Get audio publishing and playing constraints from the client page
getConstraints() код
Audio constraint: true or false (depending on the value both published and played stream will have or have not audio)
Video constraint: true (published and played streams will have video)
var constraints = { audio: $("#hasAudio").is(':checked'), video: true };
5. Video streaming
session.createStream(), publish() код
When stream is created, the following parameters are passed
- streamName - имя поток, публикуемого участником конференции (в данном случае login + "#" + roomName, где login - имя участника)
- mockLocalDisplay - div-элемент, required for the local camera video (will not be displayed to the user in the case)
- constraints - getConstraints() код (in this case is used to specify if the published stream will have audio)
publishStream = session.createStream({ name: streamName, display: mockLocalDisplay, receiveVideo: false, receiveAudio: false, constraints: getConstraints() }).on(STREAM_STATUS.PUBLISHING, function (publishStream) { ... }); publishStream.publish();
6. Receiving the event confirming successful streaming
StreamStatusEvent PUBLISHING код
On receiving the event, a stream for playing the participant's conference mixer is created
publishStream = session.createStream({ ... }).on(STREAM_STATUS.PUBLISHING, function (publishStream) { //play preview playStream(session); ... });
7. Воспроизведение потока конференцции
session.createStream(), play() код
When stream is created, the following parameters are passed
- streamName - имя микшера, кторый будет воспроизводиться для участника (в данном случае roomName + "-" + login + roomName, где login - имя участника)
- remoteVideo - div-элемент, в котором будет отображаться видео
- constraints - getConstraints() код (in this case is used to specify if the played stream will have audio)
conferenceStream = session.createStream({ name: streamName, display: remoteVideo, constraints: getConstraints() ... }); conferenceStream.play();
8. Receiving the event confirming successful playback
StreamStatusEvent PLAYING code
conferenceStream = session.createStream({ name: streamName, display: remoteVideo, constraints: getConstraints() }).on(STREAM_STATUS.PENDING, function (stream) { ... }).on(STREAM_STATUS.PLAYING, function (stream) { $("#preloader").hide(); setStatus(stream.status()); onStarted(); }).on(STREAM_STATUS.STOPPED, function () { ... }).on(STREAM_STATUS.FAILED, function (stream) { ... });
9. Остановка публикации и воспроизведения видеопотоков при отключении от конференции
stopStreams() код
conferenceStream.stop(); publishStream.stop();
10. Receiving the event confirming successful streaming stop
StreamStatusEvent UNPUBLISHED код
publishStream = session.createStream({ name: streamName, display: mockLocalDisplay, receiveVideo: false, receiveAudio: false, constraints: getConstraints() }).on(STREAM_STATUS.PUBLISHING, function (publishStream) { ... }).on(STREAM_STATUS.UNPUBLISHED, function () { onStopped(); }).on(STREAM_STATUS.FAILED, function (stream) { ... });
11. Receiving the event confirming playback stop
StreamStatusEvent STOPPED код
conferenceStream = session.createStream({ name: streamName, display: remoteVideo, constraints: getConstraints() }).on(STREAM_STATUS.PENDING, function (stream) { ... }).on(STREAM_STATUS.PLAYING, function (stream) { ... }).on(STREAM_STATUS.STOPPED, function () { $("#preloader").hide(); setStatus(STREAM_STATUS.STOPPED); onStopped(); }).on(STREAM_STATUS.FAILED, function (stream) { ... });