Versions Compared

Key

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

...

Code Block
languagejs
themeRDark
       Flashphoner.init({
            flashMediaProviderSwfLocation: '../../../../media-provider.swf',
            mediaProvidersReadyCallback: function (mediaProviders) {
                //hide remote video if current media provider is Flash
                if (mediaProviders[0] == "Flash") {
                    $("#fecForm").hide();
                    $("#stereoForm").hide();
                    $("#sendAudioBitrateForm").hide();
                    $("#cpuOveruseDetectionForm").hide();
                }
                if (Flashphoner.isUsingTemasys()) {
                    $("#audioInputForm").hide();
                    $("#videoInputForm").hide();
                }
            }
        })

...

Code Block
languagejs
themeRDark
    Flashphoner.getMediaDevices(null, true).then(function (list) {
        list.audio.forEach(function (device) {
            var audio = document.getElementById("audioInput");...
        });
    var i;
   list.video.forEach(function (device) {
       var deviceInList = false;
  ...
        });
  for (i = 0; i < audio..options.length; i++) {
    }).catch(function (error) {
        $("#notifyFlash").text("Failed to if (audio.options[i].value == device.id) {get media devices");
    });


3. Получение граничных параметров для аудио и видео со страницы клиента

getConstraints() код

Code Block
languagejs
themeRDark
function getConstraints() {
              deviceInList constraints = true;{
        audio: $("#sendAudio").is(':checked'),
           break;video: $("#sendVideo").is(':checked'),
           customStream: $("#sendCanvasStream").is(':checked')
     };

    if        }(constraints.audio) {
            if (!deviceInList) constraints.audio = {
                var option = document.createElement("option");deviceId: $('#audioInput').val()
        };
        option.text = device.label || device.id;if ($("#fec").is(':checked'))
                option.valueconstraints.audio.fec = device.id$("#fec").is(':checked');
                audio.appendChild(option);if ($("#sendStereoAudio").is(':checked'))
            }
        }constraints.audio.stereo = $("#sendStereoAudio").is(':checked');
        list.video.forEach(function (device) {if (parseInt($('#sendAudioBitrate').val()) > 0)
            console.log(device);
    constraints.audio.bitrate = parseInt($('#sendAudioBitrate').val());
    }

    varif (constraints.video = document.getElementById("videoInput");) {
        if    var i;(constraints.customStream) {
            varconstraints.customStream deviceInList = falsecanvas.captureStream(30);
            for (i constraints.video = 0false;
 i < video.options.length; i++) {
   } else {
           if (video.options[i].value == device.id) constraints.video = {
                deviceId:    deviceInList = true;{exact: $('#videoInput').val()},
                width: parseInt($('#sendWidth').val()),
   break;
                }height: parseInt($('#sendHeight').val())
            };
            if (Browser.isSafariWebRTC(!deviceInList) {
                var option = document.createElement("option");&& Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") {
                optionconstraints.video.textwidth = device.label || device.id {min: parseInt($('#sendWidth').val()), max: 640};
                optionconstraints.video.valueheight = device.id;
                if (option.text.toLowerCase().indexOf("back") >= 0 && video.children.length > 0) {
{min: parseInt($('#sendHeight').val()), max: 480};
            }
             video.insertBefore(option, video.children[0]);if (parseInt($('#sendVideoMinBitrate').val()) > 0)
                } else {constraints.video.minBitrate = parseInt($('#sendVideoMinBitrate').val());
            if (parseInt($('#sendVideoMaxBitrate').val()) > 0)
                constraints.video.appendChild(option.maxBitrate = parseInt($('#sendVideoMaxBitrate').val());
            if (parseInt($('#fps').val()) >  }0)
            }
     constraints.video.frameRate   });


        $("#url").val(setURL() + "/" + createUUID(8= parseInt($('#fps').val());

        //set initial button callback}
        onStopped();}

        if (list.audio.length === 0) {
            $("#sendAudio").prop('checked', false).prop('disabled', true);
        }
        if (list.video.length === 0) {
            $("#sendVideo").prop('checked', false).prop('disabled', true);
        }
    }).catch(function (error) {
        $("#notifyFlash").text("Failed to get media devices");
    });

3. Получение граничных параметров для аудио и видео со страницы клиента

getConstraints() код

Code Block
languagejs
themeRDark
function getConstraints() {
    constraints = {
        audio: $("#sendAudio").is(':checked'),
        video: $("#sendVideo").is(':checked'),
        customStream: $("#sendCanvasStream").is(':checked')
    };

    if (constraints.audio) {
        constraints.audio = {
            deviceId: $('#audioInput').val()
        };
        if ($("#fec").is(':checked'))
            constraints.audio.fec = $("#fec").is(':checked');
        if ($("#sendStereoAudio").is(':checked'))
            constraints.audio.stereo = $("#sendStereoAudio").is(':checked');
        if (parseInt($('#sendAudioBitrate').val()) > 0)
            constraints.audio.bitrate = parseInt($('#sendAudioBitrate').val());
    }

    if (constraints.video) {
        if (constraints.customStream) {
            constraints.customStream = canvas.captureStream(30);
            constraints.video = false;
        } else {
            constraints.video = {
                deviceId: {exact: $('#videoInput').val()},
                width: parseInt($('#sendWidth').val()),
                height: parseInt($('#sendHeight').val())
            };
            if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") {
                constraints.video.width = {min: parseInt($('#sendWidth').val()), max: 640};
                constraints.video.height = {min: parseInt($('#sendHeight').val()), max: 480};
            }
            if (parseInt($('#sendVideoMinBitrate').val()) > 0)
                constraints.video.minBitrate = parseInt($('#sendVideoMinBitrate').val());
            if (parseInt($('#sendVideoMaxBitrate').val()) > 0)
                constraints.video.maxBitrate = parseInt($('#sendVideoMaxBitrate').val());
            if (parseInt($('#fps').val()) > 0)
                constraints.video.frameRate = parseInt($('#fps').val());
        }
    }

    return constraints;
}

4. Получение доступа к медиаустройствам для локального тестирования

Flashphoner.getMediaAccess() код

В метод передаются граничные параметры для аудио и видео (constrains), а также localVideo - div-элемент, в котором будет отображаться видео с выбранной камеры.

Code Block
languagejs
themeRDark
Flashphoner.getMediaAccess(getConstraints(), localVideo).then(function (disp) {
        $("#testBtn").text("Release").off('click').click(function () {
            $(this).prop('disabled', true);
            stopTest();
        }).prop('disabled', false);

        window.AudioContext = window.AudioContext || window.webkitAudioContext;
        if (Flashphoner.getMediaProviders()[0] == "WebRTC" && window.AudioContext) {
            for (i = 0; i < localVideo.children.length; i++) {
                if (localVideo.children[i] && localVideo.children[i].id.indexOf("-LOCAL_CACHED_VIDEO") != -1) {
                    var stream = localVideo.children[i].srcObject;
                    audioContextForTest = new AudioContext();
                    var microphone = audioContextForTest.createMediaStreamSource(stream);
                    var javascriptNode = audioContextForTest.createScriptProcessor(1024, 1, 1);
                    microphone.connect(javascriptNode);
                    javascriptNode.connect(audioContextForTest.destination);
                    javascriptNode.onaudioprocess = function (event) {
                        var inpt_L = event.inputBuffer.getChannelData(0);
                        var sum_L = 0.0;
                        for (var i = 0; i < inpt_L.length; ++i) {
                            sum_L += inpt_L[i] * inpt_L[i];
                        }
                        $("#micLevel").text(Math.floor(Math.sqrt(sum_L / inpt_L.length) * 100));
                    }
                }
            }
        } else if (Flashphoner.getMediaProviders()[0] == "Flash") {
            micLevelInterval = setInterval(function () {
                $("#micLevel").text(disp.children[0].getMicrophoneLevel());
            }, 500);
        }
        testStarted = true;
    }).catch(function (error) {
        $("#testBtn").prop('disabled', false);
        testStarted = false;
    });

5. Подключение к серверу.

Flashphoner.createSession() код

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();
    });

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

ConnectionStatusEvent ESTABLISHED код

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();
    });

7. Публикация видеопотока

session.createStream(), publishStream.publish() код

Code Block
languagejs
themeRDark
  publishStream = session.createStream({
        name: streamName,
        display: localVideo,
        cacheLocalResources: true,
        constraints: constraints,
        mediaConnectionConstraints: mediaConnectionConstraints
    }).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
        $("#testBtn").prop('disabled', true);
        var video = document.getElementById(publishStream.id());
        //resize local if resolution is available
        if (video.videoWidth > 0 && video.videoHeight > 0) {
            resizeLocalVideo({target: video});
        }
        enableMuteToggles(true);
        if ($("#muteVideoToggle").is(":checked")) {
            muteVideo();
        }
        if ($("#muteAudioToggle").is(":checked")) {
            muteAudio();
        }
        //remove resize listener in case this video was cached earlier
        video.removeEventListener('resize', resizeLocalVideo);
        video.addEventListener('resize', resizeLocalVideo);
        setStatus(STREAM_STATUS.PUBLISHING);

        //play preview
        var constraints = {
            audio: $("#playAudio").is(':checked'),
            video: $("#playVideo").is(':checked')
        };
        if (constraints.video) {
            constraints.video = {
                width: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveWidth').val()) : 0,
                height: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveHeight').val()) : 0,
                bitrate: (!$("#receiveDefaultBitrate").is(":checked")) ? $("#receiveBitrate").val() : 0,
                quality: (!$("#receiveDefaultQuality").is(":checked")) ? $('#quality').val() : 0
            };
        }
        previewStream = session.createStream({
            name: streamName,
            display: remoteVideo,
            constraints: constraints
        }).on(STREAM_STATUS.PLAYING, function (previewStream) {
            document.getElementById(previewStream.id()).addEventListener('resize', function (event) {
                $("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight);
                resizeVideo(event.target);
            });
            //enable stop button
            onStarted(publishStream, previewStream);
            //wait for incoming stream
            if (Flashphoner.getMediaProviders()[0] == "WebRTC") {
                setTimeout(function () {
                    detectSpeech(previewStream);
                }, 3000);
            }

            drawSquare();
        }).on(STREAM_STATUS.STOPPED, function () {
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function () {
            //preview failed, stop publishStream
            if (publishStream.status() == STREAM_STATUS.PUBLISHING) {
                setStatus(STREAM_STATUS.FAILED);
                publishStream.stop();
            }
        });
        previewStream.play();
    }).on(STREAM_STATUS.UNPUBLISHED, function () {
        setStatus(STREAM_STATUS.UNPUBLISHED);
        //enable start button
        onStopped();
    }).on(STREAM_STATUS.FAILED, function () {
        setStatus(STREAM_STATUS.FAILED);
        //enable start button
        onStopped();
    });
    publishStream.publish();

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

StreamStatusEvent PUBLISHING код

При получении данного события создается превью-видеопоток при помощи createStream() и вызывается play() для его воспроизведения.

Code Block
languagejs
themeRDark
publishStream = session.createStream({
        name: streamName,
        display: localVideo,
        cacheLocalResources: true,
        constraints: constraints,
        mediaConnectionConstraints: mediaConnectionConstraints
    }).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
        $("#testBtn").prop('disabled', true);
        var video = document.getElementById(publishStream.id());
        //resize local if resolution is available
        if (video.videoWidth > 0 && video.videoHeight > 0) {
            resizeLocalVideo({target: video});
        }
        enableMuteToggles(true);
        if ($("#muteVideoToggle").is(":checked")) {
            muteVideo();
        }
        if ($("#muteAudioToggle").is(":checked")) {
            muteAudio();
        }
        //remove resize listener in case this video was cached earlier
        video.removeEventListener('resize', resizeLocalVideo);
        video.addEventListener('resize', resizeLocalVideo);
        setStatus(STREAM_STATUS.PUBLISHING);

        //play preview
        var constraints = {
            audio: $("#playAudio").is(':checked'),
            video: $("#playVideo").is(':checked')
        };
        if (constraints.video) {
            constraints.video = {
                width: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveWidth').val()) : 0,
                height: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveHeight').val()) : 0,
                bitrate: (!$("#receiveDefaultBitrate").is(":checked")) ? $("#receiveBitrate").val() : 0,
                quality: (!$("#receiveDefaultQuality").is(":checked")) ? $('#quality').val() : 0
            };
        }
        previewStream = session.createStream({
            name: streamName,
            display: remoteVideo,
            constraints: constraints
        }).on(STREAM_STATUS.PLAYING, function (previewStream) {
            document.getElementById(previewStream.id()).addEventListener('resize', function (event) {
                $("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight);
                resizeVideo(event.target);
            });
            //enable stop button
            onStarted(publishStream, previewStream);
            //wait for incoming stream
            if (Flashphoner.getMediaProviders()[0] == "WebRTC") {
                setTimeout(function () {
                    detectSpeech(previewStream);
                }, 3000);
            }

            drawSquare();
        }).on(STREAM_STATUS.STOPPED, function () {
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function () {
            //preview failed, stop publishStream
            if (publishStream.status() == STREAM_STATUS.PUBLISHING) {
                setStatus(STREAM_STATUS.FAILED);
                publishStream.stop();
            }
        });
        previewStream.play();
    }).on(STREAM_STATUS.UNPUBLISHED, function () {
        setStatus(STREAM_STATUS.UNPUBLISHED);
        //enable start button
        onStopped();
    }).on(STREAM_STATUS.FAILED, function () {
        setStatus(STREAM_STATUS.FAILED);
        //enable start button
        onStopped();
    });
    publishStream.publish();

9. Остановка воспроизведения превью-видеопотока.

previewStream.stop() код

Code Block
languagejs
themeRDark
 $("#publishBtn").text("Stop").off('click').click(function () {
        $(this).prop('disabled', true);
        previewStream.stop();
    }).prop('disabled', false);

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

StreamStatusEvent STOPPED код

Code Block
languagejs
themeRDark
previewStream = session.createStream({
            name: streamName,
            display: remoteVideo,
            constraints: constraints
        }).on(STREAM_STATUS.PLAYING, function (previewStream) {
            document.getElementById(previewStream.id()).addEventListener('resize', function (event) {
                $("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight);
                resizeVideo(event.target);
            });
            //enable stop button
            onStarted(publishStream, previewStream);
            //wait for incoming stream
            if (Flashphoner.getMediaProviders()[0] == "WebRTC") {
                setTimeout(function () {
                    detectSpeech(previewStream);
                }, 3000);
            }

            drawSquare();
        }).on(STREAM_STATUS.STOPPED, function () {
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function (return constraints;
}


4. Получение доступа к медиаустройствам для локального тестирования

Flashphoner.getMediaAccess() код

В метод передаются граничные параметры для аудио и видео (constrains), а также localVideo - div-элемент, в котором будет отображаться видео с выбранной камеры.

Code Block
languagejs
themeRDark
    Flashphoner.getMediaAccess(getConstraints(), localVideo).then(function (disp) {
            //preview failed, stop publishStream
            if (publishStream.status() == STREAM_STATUS.PUBLISHING$("#testBtn").text("Release").off('click').click(function () {
                setStatus(STREAM_STATUS.FAILED$(this).prop('disabled', true);
                publishStream.stopstopTest();
            }
        });
        previewStream.play();

11. Остановка публикации видеопотока после остановки воспроизведения превью-потока.

publishStream.stop() код

Code Block
languagejs
themeRDark
 previewStream = session.createStream({
   .prop('disabled', false);
        ...
        testStarted name: streamName,= true;
    }).catch(function (error) {
       display: remoteVideo, $("#testBtn").prop('disabled', false);
        testStarted = false;
  constraints: constraints
  });


5. Подключение к серверу.

Flashphoner.createSession() код

Code Block
languagejs
themeRDark
        Flashphoner.createSession({urlServer: url}).on(STREAMSESSION_STATUS.PLAYINGESTABLISHED, function (previewStreamsession) {
        //session connected, start streaming
        document.getElementById(previewStream.id()).addEventListener('resize'startStreaming(session);
    }).on(SESSION_STATUS.DISCONNECTED, function (event) {
        setStatus(SESSION_STATUS.DISCONNECTED);
        $onStopped("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight););
    }).on(SESSION_STATUS.FAILED, function () {
        setStatus(SESSION_STATUS.FAILED);
        resizeVideoonStopped(event.target);
    });


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

ConnectionStatusEvent ESTABLISHED код

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function  });
  (session) {
          //enable stop buttonsession connected, start streaming
            onStarted(publishStream, previewStreamstartStreaming(session);
    }).on(SESSION_STATUS.DISCONNECTED, function () {
     //wait for incoming stream...
            if (Flashphoner.getMediaProviders()[0] == "WebRTC"}).on(SESSION_STATUS.FAILED, function () {
        ...
    });


7. Публикация видеопотока

session.createStream(), publishStream.publish() код

Code Block
languagejs
themeRDark
    publishStream setTimeout(function () = session.createStream({
        name: streamName,
        display: localVideo,
  detectSpeech(previewStream);
      cacheLocalResources: true,
        constraints: }constraints, 3000);
            }

mediaConnectionConstraints: mediaConnectionConstraints
        ...
    drawSquare(});
        }).on(STREAM_STATUS.STOPPED, function () {
   publishStream.publish();


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

StreamStatusEvent PUBLISHING код

При получении данного события создается превью-видеопоток при помощи createStream() и вызывается play() для его воспроизведения.

Code Block
languagejs
themeRDark
    publishStream = session.createStream({
         publishStream.stop();
name: streamName,
         }).on(STREAM_STATUS.FAILED, function () {
display: localVideo,
        cacheLocalResources: true,
      //preview failed, stopconstraints: publishStreamconstraints,
        mediaConnectionConstraints: mediaConnectionConstraints
   if (publishStream}).statuson() == STREAM_STATUS.PUBLISHING, function (publishStream) {
                setStatus(STREAM_STATUS.FAILED);
    $("#testBtn").prop('disabled', true);
        var video =  document.getElementById(publishStream.stopid());
        //resize local if resolution }is available
        });
        previewStream.play();

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

StreamStatusEvent UNPUBLISHED код

Code Block
languagejs
themeRDark
publishStream = session.createStream({
        name: streamName,
if (video.videoWidth > 0 && video.videoHeight > 0) {
            displayresizeLocalVideo({target: localVideo,video});
        cacheLocalResources: true,}
        constraints: constraints,enableMuteToggles(true);
        mediaConnectionConstraints: mediaConnectionConstraints
    }).on(STREAM_STATUS.PUBLISHING, function (publishStreamif ($("#muteVideoToggle").is(":checked")) {
        $("#testBtn").prop('disabled', true    muteVideo();
        }
      var video = document.getElementById(publishStream.id());if ($("#muteAudioToggle").is(":checked")) {
        //resize local if resolution is available muteAudio();
        if (video.videoWidth > 0 && video.videoHeight > 0) {
            resizeLocalVideo({target: video});
}
        //remove resize listener in case this video was cached earlier
         }video.removeEventListener('resize', resizeLocalVideo);
        enableMuteToggles(truevideo.addEventListener('resize', resizeLocalVideo);
        if ($("#muteVideoToggle").is(":checked")) {setStatus(STREAM_STATUS.PUBLISHING);

        //play preview
   muteVideo();
     var constraints = }{
           if audio: ($("#muteAudioToggle#playAudio").is("':checked"')) {,
            muteAudio();video: $("#playVideo").is(':checked')
        };
        //remove resize listener in case this video was cached earlier
if (constraints.video) {
            constraints.video =  video.removeEventListener('resize', resizeLocalVideo);
{
          video.addEventListener('resize', resizeLocalVideo);
     width: (!$("#receiveDefaultSize").is(":checked")) ? setStatus(STREAM_STATUS.PUBLISHING);
parseInt($('#receiveWidth').val()) : 0,
        //play preview
        var constraints = {
height: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveHeight').val()) : 0,
                audiobitrate: (!$("#playAudio#receiveDefaultBitrate").is('":checked'),
")) ? $("#receiveBitrate").val() : 0,
                videoquality: (!$("#playVideo#receiveDefaultQuality").is('":checked")) ? $('#quality').val() : 0
            };
        }
        if (constraints.video) previewStream = session.createStream({
            name: streamName,
 constraints.video = {
         display: remoteVideo,
      width: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveWidth').val()) : 0,      constraints: constraints
            ...
       height: (!$("#receiveDefaultSize").is(":checked")) ? parseInt($('#receiveHeight').val()) : 0,
      });
        previewStream.play();
    }).on(STREAM_STATUS.UNPUBLISHED, function () {
        ...
   bitrate: (!$("#receiveDefaultBitrate" }).is(":checked")) ? $("#receiveBitrate").val() : 0,
on(STREAM_STATUS.FAILED, function () {
        ...
    });
    publishStream.publish();


9. Остановка воспроизведения превью-видеопотока.

previewStream.stop() код

Code Block
languagejs
themeRDark
   quality: (!$("#receiveDefaultQuality#publishBtn").istext(":checkedStop")) ? $.off('#qualityclick').valclick(function () : 0
{
        $(this).prop('disabled', true);
      }  previewStream.stop();
        }
}).prop('disabled', false);


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

StreamStatusEvent STOPPED код

Code Block
languagejs
themeRDark
        previewStream = session.createStream({
            name: streamName,
            display: remoteVideo,
            constraints: constraints
        }).on(STREAM_STATUS.PLAYING, function (previewStream) {
            document.getElementById(previewStream.id()).addEventListener('resize', function (event) {
                $("#playResolution"}).texton(event.target.videoWidth + "x" + event.target.videoHeight);
                resizeVideo(event.target);STREAM_STATUS.STOPPED, function () {
            }publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function   //enable stop button() {
            onStarted(publishStream, previewStream);...
        });
    //wait for incoming stream
  previewStream.play();


11. Остановка публикации видеопотока после остановки воспроизведения превью-потока.

publishStream.stop() код

Code Block
languagejs
themeRDark
        previewStream =  if (Flashphoner.getMediaProviders()[0] == "WebRTC") session.createStream({
                setTimeout(function () {name: streamName,
            display: remoteVideo,
       detectSpeech(previewStream);
     constraints:   constraints
        }).on(STREAM_STATUS.PLAYING, function 3000(previewStream);
            }

 {
            drawSquare();...
        }).on(STREAM_STATUS.STOPPED, function () {
            publishStream.stop();
        }).on(STREAM_STATUS.FAILED, function () {
            //preview failed, stop publishStream
...
        });
       if (publishStreampreviewStream.status() == STREAM_STATUS.PUBLISHING) play();


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

StreamStatusEvent UNPUBLISHED код

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

...