Versions Compared

Key

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

Table of Contents

Пример стримера c доступом к медиа-устройствам

Данный стример может использоваться для публикации следующих типов потоков с и проигрывания WebRTC потоков на Web Call Server

  • WebRTC
  • RTMFP
  • RTMP

и позволяет выбрать медиа-устройства и параметры для публикуемого видео

...

На скриншоте ниже представлен пример во время публикации потока.

Image RemovedImage Added


На странице вопроизводятся отображаются два видео элемента:

  • 'Local' - видео с камеры
  • 'PreviewPlayer' - видео, которое приходит с сервера

Код примера

Код данного примера находится на WCS-сервере по следующему пути:

...

Здесь host - адрес WCS-сервера.

Работа с кодом примера

Для разбора кода возьмем версию файла manager.js с хэшем 66cc393 ecbadc3, которая находится здесь и доступна для скачивания в соответствующей сборке 2.0.5.28.2753.133.212.

1. Инициализация API.

Flashphoner.init() code

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

2. Получение списка доступных медиа-устройств ввода

Flashphoner.getMediaDevices() code

При получении списка медиа-устройств заполняются выпадающие списки микрофонов и камер на странице клиента.

Code Block
languagejs
themeRDark
    Flashphoner.getMediaDevices(null, true).then(function (list) {
        list.audio.forEach(function (device) {
           $("#cpuOveruseDetectionForm").hide();
         ...
        });
                if (Flashphoner.isUsingTemasys()list.video.forEach(function (device) {
            ...
        $("#audioInputForm").hide()});
        ...
    }).catch(function (error) {
        $("#videoInputForm#notifyFlash").hide();
                }
            }
  text("Failed to get media devices");
      });

23. Получение списка доступных медиа-устройств вводавывода звука

Flashphoner.getMediaDevices() code

При получении списка медиа-устройств заполняются выпадающие списки микрофонов и камер выпадающий список устройств вывода звука на странице клиента.

Code Block
languagejs
themeRDark
    Flashphoner.getMediaDevices(null, true, MEDIA_DEVICE_KIND.OUTPUT).then(function (list) {
        list.audio.forEach(function (device) {
            ...
        });
        list..video.forEach(function (device) {
            ...
        });
        ...
    }).catch(function (error) {
        $("#notifyFlash").text("Failed to get media devices");
    });

3. Получение списка доступных медиа-устройств вывода звука

Flashphoner.getMediaDevices() code

При получении списка медиа-устройств заполняются выпадающий список устройств вывода звука на странице клиента.4. Получение граничных параметров для публикации аудио и видео со страницы клиента

getConstraints() code

Источники публикации:

  • камера (sendVideo)
  • микрофон (sendAudio)
Code Block
languagejs
themeRDark
    Flashphoner.getMediaDevices(null, true, MEDIA_DEVICE_KIND.OUTPUT).then(function (list) constraints = {
        list.audio.forEach(function (device) {audio: $("#sendAudio").is(':checked'),
        video: $("#sendVideo").is(':checked'),
   ...
 };

Параметры аудио:

  • выбор микрофона (deviceId)
  • коррекция ошибок для кодека Opus (fec)
  • режим стерео (stereo)
  • битрейт аудио (bitrate)
Code Block
languagejs
themeRDark
    if    });(constraints.audio) {
        constraints...
audio = {
  }).catch(function (error) {
        deviceId: $("#notifyFlash"'#audioInput').textval("Failed)
 to get media devices");
    });

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

getConstraints() code

Источники публикации:

  • камера (sendVideo)
  • микрофон (sendAudio)
Code Block
languagejs
themeRDark
    constraints = {
        audio:if ($("#sendAudio#fec").is(':checked'),)
          video:   constraints.audio.fec = $("#sendVideo#fec").is(':checked'),;
         };

Параметры аудио:

  • выбор микрофона (deviceId)
  • коррекция ошибок для кодека Opus (fec)
  • режим стерео (stereo)
  • битрейт аудио (bitrate)
Code Block
languagejs
themeRDark
if ($("#sendStereoAudio").is(':checked'))
     if (constraints.audio) {
        constraints.audio.stereo = {
            deviceId: $('#audioInput'"#sendStereoAudio").valis()
        }':checked');
        if (parseInt($("#fec"'#sendAudioBitrate').is(':checked')val()) > 0)
            constraints.audio.fecbitrate = parseInt($("#fec"'#sendAudioBitrate').is(':checked'val());
        if ($("#sendStereoAudio").is(':checked'))
}

Параметры видео:

  • выбор камеры (deviceId)
  • размеры при публикации (width, height)
  • минимальный и максимальный битрейт видео (minBitrate, maxBitrate)
  • FPS (frameRate)
Code Block
languagejs
themeRDark
            constraints.audio.stereovideo = $("#sendStereoAudio").is(':checked');
 {
                deviceId: {exact: $('#videoInput').val()},
                ifwidth: (parseInt($('#sendAudioBitrate#sendWidth').val()),
  > 0)
            constraints.audio.bitrate = height: parseInt($('#sendAudioBitrate#sendHeight').val());
            }

Параметры видео:

  • выбор камеры (deviceId)
  • размеры при публикации (width, height)
  • минимальный и максимальный битрейт видео (minBitrate, maxBitrate)
  • FPS (frameRate)
Code Block
languagejs
themeRDark
;
            if (Browser.isSafariWebRTC() && Browser.isiOS() && constraints.video =Flashphoner.getMediaProviders()[0] === "WebRTC") {
                deviceId:constraints.video.deviceId = {exact: $('#videoInput').val()},
;
            }
           width: if (parseInt($('#sendWidth#sendVideoMinBitrate').val()) > 0),
                 height:constraints.video.minBitrate = parseInt($('#sendHeight#sendVideoMinBitrate').val());
            if (parseInt($('#sendVideoMaxBitrate').val()) > };0)
             if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") {
                constraints.video.deviceId = {exact: $('#videoInputconstraints.video.maxBitrate = parseInt($('#sendVideoMaxBitrate').val()};
            });
            if (parseInt($('#sendVideoMinBitrate#fps').val()) > 0)
                constraints.video.minBitrateframeRate = parseInt($('#sendVideoMinBitrate#fps').val());
   


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

Flashphoner.getMediaAccess() code

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

Code Block
languagejs
themeRDark
    Flashphoner.getMediaAccess(getConstraints(), localVideo).then(function (disp) {
  if      (parseInt($('#sendVideoMaxBitrate$("#testBtn").text("Release").off('click').valclick(function ()) > 0)
    {
            constraints.video.maxBitrate = parseInt($('#sendVideoMaxBitrate'this).val())prop('disabled', true);
            if (parseInt($('#fps').val()) > 0)stopTest();
          }).prop('disabled', false);
      constraints.video.frameRate = parseInt($('#fps').val());

...

.

...

.

...

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

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

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

Flashphoner.createSession() code

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: url, timeout:  tm}).prop('disabled', false);on(SESSION_STATUS.ESTABLISHED, function (session) {
        ...
        testStarted = true;
    }).catch(}).on(SESSION_STATUS.DISCONNECTED, function (error) {
        ...
    $("#testBtn"}).prop('disabled', false);on(SESSION_STATUS.FAILED, function () {
        testStarted = false;...
    });

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

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

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: url, timeout: tm}).on(SESSION_STATUS.ESTABLISHED, function (session) {
        setStatus("#connectStatus", session.status());
        onConnected(session));
        onConnected(session);...
    }).on(SESSION_STATUS.DISCONNECTED, function () ;

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

session.createStream(), publishStream.publish() code

Code Block
languagejs
themeRDark
    publishStream = session.createStream({
        setStatus("#connectStatus", SESSION_STATUS.DISCONNECTED);
name: streamName,
        display: localVideo,
  onDisconnected();
    }).on(SESSION_STATUS.FAILED, function () {
cacheLocalResources: true,
         setStatus("#connectStatus", SESSION_STATUS.FAILED);
constraints: constraints,
         onDisconnected();
    });

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

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
mediaConnectionConstraints: mediaConnectionConstraints,
        Flashphoner.createSession({urlServersdpHook: urlrewriteSdp, timeout: tm}).on(SESSION_STATUS.ESTABLISHED, function (session) {
        transport: transportInput,
        setStatus("#connectStatus", session.status());
cvoExtension: cvo,
         onConnected(session);
       stripCodecs: strippedCodecs,
        videoContentHint: contentHint
        ...
    });

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

...


    publishStream.publish();

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

StreamStatusEvent PUBLISHING code

Code Block
languagejs
themeRDark
    publishStream = session.createStream({
        name: streamName,...
        display: localVideo,
        cacheLocalResources: true,
        constraints: constraints,}).on(STREAM_STATUS.PUBLISHING, function (stream) {
        mediaConnectionConstraints: mediaConnectionConstraints,$("#testBtn").prop('disabled', true);
        sdpHook: rewriteSdp,
  var video = document.getElementById(stream.id());
      transport: transportInput,
 //resize local if resolution    cvoExtension: cvo,is available
        stripCodecs: strippedCodecs
        ...
    });
    publishStream.publish();

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

StreamStatusEvent PUBLISHING code

Code Block
languagejs
themeRDark
    publishStream = session.createStream({if (video.videoWidth > 0 && video.videoHeight > 0) {
            resizeLocalVideo({target: video});
        ...}
    }).on(STREAM_STATUS.PUBLISHING, function (stream) {    enablePublishToggles(true);
        if ($("#testBtn#muteVideoToggle").prop('disabled', true);is(":checked")) {
        var  video = document.getElementById(stream.id() muteVideo();
        //resize local if resolution is available}
        if (video.videoWidth > 0 && video.videoHeight > 0($("#muteAudioToggle").is(":checked")) {
            resizeLocalVideo({target: video}muteAudio();
        }
        enablePublishToggles(true);
        if ($("#muteVideoToggle").is(":checked")) {//remove resize listener in case this video was cached earlier
            muteVideo(video.removeEventListener('resize', resizeLocalVideo);
         }video.addEventListener('resize', resizeLocalVideo);
        if ($("#muteAudioToggle").is(":checked")) {publishStream.setMicrophoneGain(currentGainValue);
            muteAudio(setStatus("#publishStatus", STREAM_STATUS.PUBLISHING);
        }onPublishing(stream);
    }).on(STREAM_STATUS.UNPUBLISHED, function   //remove resize listener in case this video was cached earlier
() {
        ...
    video}).removeEventListener('resize', resizeLocalVideo);on(STREAM_STATUS.FAILED, function () {
        video.addEventListener('resize', resizeLocalVideo...
    });
    publishStream.publish();

10. Воспроизведение потока

session.createStream(), previewStream.play() code

Code Block
languagejs
themeRDark
    previewStream = publishStreamsession.setMicrophoneGaincreateStream(currentGainValue);{
        setStatus("#publishStatus", STREAM_STATUS.PUBLISHING);
name: streamName,
         onPublishing(stream);
display: remoteVideo,
      }).on(STREAM_STATUS.UNPUBLISHED, function () {
constraints: constraints,
         ...transport: transportOutput,
    }).on(STREAM_STATUS.FAILED, function () {    stripCodecs: strippedCodecs
        ...
    });
    publishStreampreviewStream.publishplay();

10. Воспроизведение потока

session.createStream(), previewStream.play() 11. Получение от сервера события, подтверждающего успешное воспроизведение потока

StreamStatusEvent PLAYING code

Code Block
languagejs
themeRDark
    previewStream = session.createStream({
        name: streamName,...
    }).on(STREAM_STATUS.PLAYING, function (stream) {
 display: remoteVideo,
      playConnectionQualityStat.connectionQualityUpdateTimestamp = constraints: constraints,new Date().valueOf();
        transport: transportOutput, setStatus("#playStatus", stream.status());
        stripCodecs: strippedCodecsonPlaying(stream);
        document.getElementById(stream..
    });
    previewStream.play();

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

StreamStatusEvent PLAYING code

Code Block
languagejs
themeRDark
id()).addEventListener('resize', function (event) {
          previewStream = session.createStream({
 $("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight);
         ...   resizeVideo(event.target);
    }).on(STREAM_STATUS.PLAYING, function (stream) {    });
        playConnectionQualityStat.connectionQualityUpdateTimestamp = new Date().valueOf();//wait for incoming stream
        if setStatus("#playStatus", stream.status());
    (Flashphoner.getMediaProviders()[0] == "WebRTC") {
    onPlaying(stream);
        document.getElementById(stream.id()).addEventListener('resize', setTimeout(function (event) {
            $("#playResolution").text(event.target.videoWidth + "x" + event.target.videoHeight);if(Browser.isChrome()) {
            resizeVideo(event.target);
        }detectSpeechChrome(stream);
          //wait for incoming stream
   } else {
   if (Flashphoner.getMediaProviders()[0] == "WebRTC") {
            setTimeout(function detectSpeech(stream) {;
                detectSpeech(stream);}
            }, 3000);
        }
           ...
    });
    previewStream.play();

12. Остановка воспроизведения потока.

stream.stop() code

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

...

StreamStatusEvent STOPPED code

Code Block
languagejs
themeRDark
    previewStream = session.createStream({
        ...
    }).on(STREAM_STATUS.STOPPED, function () {
        setStatus("#playStatus", STREAM_STATUS.STOPPED);
        onStopped();
        ...
    });
    previewStream.play();

14. Остановка публикации видеопотока

stream.stop() code

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

...

StreamStatusEvent UNPUBLISHED code

Code Block
languagejs
themeRDark
    publishStream = session.createStream({
        ...
    }).on(STREAM_STATUS.UNPUBLISHED, function () {
        setStatus("#publishStatus", STREAM_STATUS.UNPUBLISHED);
        onUnpublished();
        ...
    });
    publishStream.publish();

16. Отключение микрофонамикрофона

stream.muteAudio() code:

Code Block
languagejs
themeRDark
function muteAudio()  {
     if ($("#muteAudioToggle").is(":checked"))publishStream) {
            publishStream.muteAudio();
        }
}

17. Отключение камеры

stream.muteVideo() code:

Code Block
languagejs
themeRDark
function muteVideo() {
      if ($("#muteVideoToggle").is(":checked"))publishStream) {
            publishStream.muteVideo();
        }
}

18. Отображение статистики при публикации потока

...