Versions Compared

Key

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

...

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


Chrome

Firefox

Safari

Windows

+

+


Mac OS

+

+

+

Схема работы


  1. Браузер соединяется с сервером по протоколу Websocket и отправляет команду publish.
  2. Браузер захватывает экран и отправляет WebRTC поток на сервер.
  3. Второй браузер устанавливает соединение также по Websocket и отправляет команду play.
  4. Второй браузер получает WebRTC поток и воспроизводит этот поток на странице.

...

https://demo.flashphoner.com/client2/examples/demo/streaming/screen-sharing/screen-sharing.html

Image RemovedImage Added

2. Установите расширение, нажав кнопку "Install Now"

Image Removed

3. Нажмите кнопку "Start". Расширение Браузер запросит доступ к экрану, и начнется захват экрана и подготовка потока к трансляциитрансляция видеопотока:

Image RemovedImage Added

43. Убедитесь, что поток отправляется на сервер и система работает нормально, откройте chrome://webrtc-internals

54. Откройте Two Way Streaming в отдельном окне, нажмите Connect и укажите идентификатор потока, затем нажмите Play.

Image RemovedImage Added

65. Графики воспроизведения chrome://webrtc-internals

...

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

screen-sharing.html

screen-sharing.js


1. Проверка необходимости установки расширения

Browser.isFirefox(), Browser.isChrome(); code

Code Block
languagejs
themeRDark
    if (Browser.isFirefox()) {
        $("#installExtensionButton").show();
        ...
    } else if (Browser.isChrome()) {
        $('#mediaSourceForm').hide();
        interval = setInterval(function() {
            chrome.runtime.sendMessage(extensionId, {type: "isInstalled"}, function (response) {
.                if (response) {
                    $("#extension").hide();
                    clearInterval(interval);
                    onExtensionAvailable();
                } else {
                    (inIframe()) ? $("#installFromMarket").show() : $("#installExtensionButton").show();
                }
            });
        }, 500);
    } else {
        $("#notify").modal('show');
        return false;
    }

...

Flashphoner.createSession(); code

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
        //session connected, start streaming
        startStreaming(session);
    }).on(SESSION_STATUS.DISCONNECTED, function(){
        setStatus(SESSION_STATUS.DISCONNECTED);
        onStopped();
    }).on(SESSION_STATUS.FAILED, function(){
        setStatus(SESSION_STATUS.FAILED);
        onStopped();
    });

...

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
        //session connected, start streaming
        startStreaming(session);
        ...
    });

4. Публикация потока.

stream.publish(); code

Code Block
languagejs
themeRDark
    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: constraints
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        ...
    }).on(STREAM_STATUS.UNPUBLISHED, function(){
        ...
    }).on(STREAM_STATUS.FAILED, function(stream){
        ...
    }).publish();

...

StreamStatusEvent, статус PUBLISHING code

Code Block
languagejs
themeRDark
    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: constraints
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        ...
        setStatus(STREAM_STATUS.PUBLISHING);
        //play preview
        session.createStream({
            name: streamName,
            display: remoteVideo
        }).on(STREAM_STATUS.PLAYING, function(previewStream){
            document.getElementById(previewStream.id()).addEventListener('resize', function(event){
                resizeVideo(event.target);
            });
            //enable stop button
            onStarted(publishStream, previewStream);
        }).on(STREAM_STATUS.STOPPED, function(){
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function(stream){
            //preview failed, stop publishStream
            if (publishStream.status() == STREAM_STATUS.PUBLISHING) {
                setStatus(STREAM_STATUS.FAILED, stream);
                publishStream.stop();
            }
        }).play();
    }).on(STREAM_STATUS.UNPUBLISHED, function(){
        ...
    }).on(STREAM_STATUS.FAILED, function(stream){
        ...
    }).publish();

...

7. Остановка публикации потока.

stream.stop(); code

Code Block
languagejs
themeRDark
    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: constraints
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        /*
         * User can stop sharing screen capture using Chrome "stop" button.
         * Catch onended video track event and stop publishing.
         */
        document.getElementById(publishStream.id()).srcObject.getVideoTracks()[0].onended = function (e) {
            publishStream.stop();
        };
        ...
        setStatus(STREAM_STATUS.PUBLISHING);
        //play preview
        session.createStream({
            name: streamName,
            display: remoteVideo
        }).on(STREAM_STATUS.PLAYING, function(previewStream){
            ...
        }).on(STREAM_STATUS.STOPPED, function(){
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function(stream){
            //preview failed, stop publishStream
            if (publishStream.status() == STREAM_STATUS.PUBLISHING) {
                setStatus(STREAM_STATUS.FAILED, stream);
                publishStream.stop();
            }
        }).play();
        ...
    }).publish();

...

StreamStatusEvent, статус UNPUBLISHED code

Code Block
languagejs
themeRDark
    session.createStream({
        name: streamName,
        display: localVideo,
        constraints: constraints
    }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
        ...
    }).on(STREAM_STATUS.UNPUBLISHED, function(){
        setStatus(STREAM_STATUS.UNPUBLISHED);
        //enable start button
        onStopped();
    }).on(STREAM_STATUS.FAILED, function(stream){
        ...
    }).publish();

...

Excerpt Include
WEBSDK2RU:Screen Sharing
WEBSDK2RU:Screen Sharing
nopaneltrue

Известные проблемы

1) . Если веб-приложение расположено внутри iframe элемента, публикация видеопотока может не пройти.

Симптомы: ошибки IceServer error в консоли браузера.
Решение: вынести приложение из iframe на отдельную страницу.

2) . Если публикация потока идет с Windows 10 или Windows 8 и в браузере Google Chrome включено аппаратное ускорение, могут быть проблемы с битрейтом.

Симптомы: качество видео плохое, мутное, битрейт в chrome://webrtc-internals показывает меньше 100 kbps.
Решение: отключите аппаратное ускорение в браузере, переключите браузер или сервер на использование кодека VP8.

3) . Остановка всех потоков, захваченных с экрана, при остановке одного из них

...

Code Block
languagejs
themeRDark
            var handleUnpublished = function(stream) {
                console.log("Stream unpublished with status " + stream.status());
                //get track label
                var video = document.getElementById(stream.id() + LOCAL_CACHED_VIDEO);
                var track = video.srcObject.getVideoTracks()[0];
                var label = track.label;
                //see if someone using this source
                if (countDisplaysWithVideoLabel(label) > 1) {
                    //remove srcObject but don't stop tracks
                    pushTrack(track);
                    video.srcObject = null;
                } else {
                    var tracks = popTracks(track);
                    for (var i = 0; i < tracks.length; i++) {
                        tracks[i].stop();
                    }
                }
                //release resources
                Flashphoner.releaseLocalMedia(streamVideoDisplay);
                //remove stream display
                display.removeChild(streamDisplay);
                session.disconnect();
            };

4. При сворачивании окна, с которогого захватывается поток, браузер Chrome перестает высылать трафик

Симптомы: если окно, с которого захватывается видеопоток, свернуто на панель задач, на стороне подписчика виден фриз, поток может завершиться по отсутствию трафика: Failed by RTP activity 

Решение: в сборках до 5.2.1784 отключить контроль видео трафика для всех потоков

Code Block
themeRDark
rtp_activity_video=false

в сборках, начиная с 5.2.1784, отключить контроль видео трафика для потоков с экрана по шаблону имени, например

Code Block
themeRDark
rtp_activity_video_exclude=.*-screen$