Versions Compared

Key

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

...

Данный пример может использоваться для внедрения на веб-страницу плеера для воспроизведения живых (Live) потоков с веб-камер и IP камер. Поддерживаются следующие технологии воспроизведения:

  • WebRTC
  • MSE
  • WSPlayer (Websocket + HTML5 Canvas)

Интерфейс страницы внедрения:

Image RemovedImage Added

Код примера

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

/usr/local/FlashphonerWebCallServer/client2/examples/demo/streaming/embed_player 

player.css  - файл стилей
player.html  - страница с плеером
player.js  - скрипт, обеспечивающий работу плеера
sample.css  - файл стилей для страницы интерфейса внедрения
sample.html  - страница интерфейса внедрения
sample.js  - скрипт, обеспечивающий формирование кода внедрения

Тестировать данный пример можно по следующему адресу:

https://host:8888/client2/examples/demo/streaming/embed_player/sample.html 

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

...

Для разбора кода возьмем версию файла player.js  с хешем ecbadc324a69e1, которая находится здесь и доступна для скачивания в соответствующей сборке 2.0.212225.

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

Flashphoner.init()  code

Code Block
languagejs
themeRDark
        Flashphoner.init({
 preferredMediaProviders: mediaProviders && mediaProviders !== "" ? mediaProviders.split(','):    receiverLocation: '../../dependencies/websocket-player/WSReceiver2.js',
            decoderLocation: '../../dependencies/websocket-player/video-worker2.js',
            preferredMediaProviders: mediaProviders && mediaProviders !== "" ? mediaProviders.split(','): []
        });

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

Flashphoner.createSession() code

Методу createSession() передаются параметры:

...

[] });

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

Flashphoner.createSession()  code

Методу createSession()  передаются параметры:

  • urlServer  - URL WCS-сервера
  • mediaOptions  - параметры подключения к серверу через TURN-сервер
Code Block
languagejs
themeRDark
let mediaOptions = {"iceServers": [{'url': 'turn:turn.flashphoner.com:443?transport=tcp', 'username': 'flashphoner', 'credential': 'coM77EMrV7Cwhyan'}]};
Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions}).on(SESSION_STATUS.ESTABLISHED, function (session) {
    ...
});

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

SESSION_STATUS.ESTABLISHED  code

Code Block
languagejs
themeRDark
    var mediaOptions = {"iceServers": [{'url': 'turn:turn.flashphoner.com:443?transport=tcp', 'username': 'flashphoner', 'credential': 'coM77EMrV7Cwhyan'}]};Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions}).on(SESSION_STATUS.ESTABLISHED, function (session) {
    FlashphonersetStatus(session.createSession({urlServer: urlServer, mediaOptions: mediaOptionsstatus());
    //session connected, start playback
    playStream(session);
}).on(SESSION_STATUS.ESTABLISHEDDISCONNECTED, function (session) {
        ...
}).on(SESSION_STATUS.FAILED, function () {
    ...
});

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

ConnectionStatusEvent ESTABLISHED code

Code Block
languagejs
themeRDark
    Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions}).on(SESSION_STATUS.ESTABLISHED, function (session)

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

Session.createStream() , Stream.play()  code

В метод createStream  передаются:

  • имя видеопотока streamName 
  • remoteVideo  - div элемент, в котором будет отображаться видео
  • разрешение, с которым поток будет проигрываться (на сервере включается транскодинг
  • useControls - включает использование стандартных элементов управления проигрыванием потока
  • unmutePlayOnStart: false  - отключает автоматическое воспроизведение звука при автозапуске воспроизведения для соблюдения требований браузеров
Code Block
languagejs
themeRDark
let useVideoControls = true;
...
let options = {
    name:  streamName,
  setStatus(session.status());
  display: remoteVideo,
     //session connected, start playbackuseControls: useVideoControls
};
if (resolution) {
    playWidth    playStream(session)= resolution.split("x")[0];
    }).on(SESSION_STATUS.DISCONNECTED, function () {playHeight = resolution.split("x")[1];
    options.constraints = {
  ...
    }).on(SESSION_STATUS.FAILED, function ()video: {
            ...
    });

...

session.createStream(), play() code

В метод createStream передаются:

  • имя видеопотока streamName
  • remoteVideo - div-элемент, в котором будет отображаться видео
  • признак отображения кнопки полноэкранного режима
  • разрешение для окна плеера
  • unmutePlayOnStart: false - отключает автоматическое воспроизведение звука при autoplay для соблюдения требований браузеров
Code Block
languagejs
themeRDark
    var options =width: playWidth,
            height: playHeight
        },
        audio: true
    };
}
if (autoplay) {
    options.unmutePlayOnStart = false;
}
playingStream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
        name: streamName,
        display: remoteVideo,
        flashShowFullScreenButton: true
    };
    if (resolution_for_wsplayer) {
        options.playWidth = resolution_for_wsplayer.playWidth;
        options.playHeight = resolution_for_wsplayer.playHeight;
    } else if (resolution...
});
playingStream.play();

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

STREAM_STATUS.PENDING  code

По данному событию:

  • в браузере Chrome отключается собственный прелоадер, поскольку есть стандартный при включенных стандартных элементах управления
  • настраивается обработчик изменения размера видео элемента по событию resize 
  • настраиваются обработчики событий в браузере Safari и в остальных браузерах
Code Block
languagejs
themeRDark
playingStream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
    if (Browser.isChrome()) {
        options.playWidth = resolution.split("x")[0];
        options.playHeight = resolution.split("x")[1]; // Hide a custom preloader in Chrome because there is a standard one with standard controls
    }
    if (autoplay) {
hideItem('preloader');
    }
    let options.unmutePlayOnStartvideo = falsedocument.getElementById(stream.id());
    }
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(streamif (!video.hasListeners) {
        ...
    }video.hasListeners = true;
        setResizeHandler(video, stream, playWidth);
     stream.play();

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

StreamStatusEvent PENDING code

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

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
if (Browser.isSafariWebRTC()) {
         var video = document.getElementById(stream.id()setWebkitEventHandlers(video);
        if (!video.hasListeners)} else {
            video.hasListeners = truesetEventHandlers(video);
        }
    video.addEventListener('playing'}
}).on(STREAM_STATUS.PLAYING, function (stream) {
    ...
}).on(STREAM_STATUS.STOPPED, function () {
    ...
}).on(STREAM_STATUS.FAILED, function(stream) {
    $("#preloader").hide();
            });
            video.addEventListener('resize', function (event) ...
}).on(STREAM_EVENT, function(streamEvent){
                var streamResolution = stream.videoResolution();
                if (Object.keys(streamResolution).length === 0) ...
});
playingStream.play();

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

STREAM_STATUS.PLAYING  code

По этому событию снимается с паузы проигрывание потока по MSE в браузере Android Firefox

Code Block
languagejs
themeRDark
playingStream = session.createStream(options).on(STREAM_STATUS.PENDING, function (stream) {
    ...
}).on(STREAM_STATUS.PLAYING, function (stream) {
    // Android Firefox may pause stream playback via  resizeVideo(event.target);
     MSE even if video element is muted
           } elseif (Flashphoner.getMediaProviders()[0] == "MSE" && autoplay && Browser.isAndroidFirefox()) {
        let video = document.getElementById(stream.id());
        if // Change aspect ratio to prevent video stretching
(video && video.paused) {
            video.play();
        }
    var}
 ratio = streamResolution.width / streamResolution.height setStatus(STREAM_STATUS.PLAYING);
    onStarted();
}).on(STREAM_STATUS.STOPPED, function () {
    ...
}).on(STREAM_STATUS.FAILED, function(stream) {
    ...
}).on(STREAM_EVENT, function(streamEvent){
  var newHeight = Math.floor(options.playWidth / ratio);
                    resizeVideo(event.target, options.playWidth, newHeight);
                }
            });
        }
    }...
});
playingStream.play();

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

Stream.stop()  code

Code Block
languagejs
themeRDark
playingStream.stop();

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

STREAM_STATUS.STOPPED  code

Code Block
languagejs
themeRDark
playingStream = session.createStream(options).on(STREAM_STATUS.PLAYINGPENDING, function (stream) {
        ...
    }).on(STREAM_STATUS.STOPPEDPLAYING, function (stream) {
        ...
    }).on(STREAM_STATUS.FAILEDSTOPPED, function () {
        ...setStatus(STREAM_STATUS.STOPPED);
    onStopped();
}).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTHFAILED, function (stream) {
        ...
    });}).on(STREAM_EVENT, function(streamEvent){
    stream....
});
playingStream.play(); 

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

StreamStatusEvent PLAYING 9. Автозапуск воспроизведения при загрузке страницы

code

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(streamif (autoplay) {
        ...
    }).on(STREAM_STATUS.PLAYING, function (streamcentralButton.click();
}

10. Настройка обработчика события resize 

code

По данному событию меняется размер контейнера для video элемента

Code Block
languagejs
themeRDark
function setResizeHandler(video, stream, playWidth) {
        setStatus(stream.status());video.addEventListener('resize', function (event) {
        onStarted(stream);
    }).on(STREAM_STATUS.STOPPED, function () {
let streamResolution = stream.videoResolution();
        if ...
    }).on(STREAM_STATUS.FAILED, function ((Object.keys(streamResolution).length === 0) {
        ...
    }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function (stream) {
resizeVideo(event.target);
        } else  ...
{
         });
    stream.play();

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

stream.stop() code

Code Block
languagejs
themeRDark
      // Change aspect ratio to prevent video stretching
      $that.find('.play-pause').bind('click', function () {
   let ratio = streamResolution.width / streamResolution.height;
        // If playing, etc, changelet classesnewHeight to show pause or play button= Math.floor(playWidth / ratio);
            resizeVideo(event.target,    if (!$(this).prop('disabled')) {playWidth, newHeight);
        }
            if (stopped) {
                        ...
                    } else {
                        if (stream) {
                            stream.stop();
                        }
                        ...
                    }
                }
            });

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

StreamStatusEvent STOPPED code

Code Block
languagejs
themeRDark
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    }).on(STREAM_STATUS.PLAYING, function (stream) {
});
}

11. Настройка обработчиков событий видео в браузере Safari

code

Обрабатываются следующие события:

  • playing - скрывается собственный прелоадер при проигрывании потока
  • webkitbeginfullscreen , webkitendfullscreen - определяется полноэранный режим для снятия потока с паузы при выходе из него
  • pause - проигрывание снимается с паузы при выходе из полноэкранного режима; при нажатии на стандартную кнопку паузы в обычном режиме останавливается проигрывание потока
Code Block
languagejs
themeRDark
function setWebkitEventHandlers(video) {
    let needRestart = false;
    let isFullscreen = false;
    // Hide custom preloader
    video.addEventListener('playing', function () {
        hideItem('preloader');
    });
    // Use webkitbeginfullscreen event to detect full screen mode in iOS Safari
    video.addEventListener("webkitbeginfullscreen", function () {
         ...isFullscreen = true;
    }).on(STREAM_STATUS.STOPPED, function () {
;        setStatus(STREAM_STATUS.STOPPED);
        onStopped();
    })video.on(STREAM_STATUS.FAILEDaddEventListener("pause", function () {
         ...
if (needRestart) {
     }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function (stream) {
       console.log("Video paused after fullscreen,  continue...");
    });
    stream.play();

9. Регулировка громкости воспроизведения

stream.unmuteRemoteAudio(), stream.setVolume(currentVolumeValue) code

Code Block
languagejs
themeRDark
    if video.play(stream) {;
        if (volume > 0) {
needRestart = false;
        } else if (!firstUnmuted && slider && Browser.isAndroid((isFullscreen || document.webkitFullscreenElement)) {
                console.error("User should click volume unmute button to enable audio");
    // Stop stream by standard play/pause control
            returnplayingStream.stop(false);
        }
    });
  else if (stream.isRemoteAudioMuted()video.addEventListener("webkitendfullscreen", function () {
        video.play();
         stream.unmuteRemoteAudio()needRestart = true;
        isFullscreen = false;
    });  firstUnmuted = true;
            }
        }
}

12. Настройка обработчиков событий видео в других браузерах

code

Обрабатываются следующие события:

  • playing - скрывается собственный прелоадер при проигрывании потока
  • pause - при нажатии на стандартную кнопку паузы в обычном режиме останавливается проигрывание потока
Code Block
languagejs
themeRDark
function setEventHandlers(video) {
    // Hide   stream.setVolume(volume);
    }
    // Save current volume in page element to restore it when mute/unmute
custom preloader
    video.addEventListener('playing', function () {
        $hideItem('#volume-range').val(volumepreloader');
    ...

10. Автозапуск воспроизведения при загрузке страницы

code

Code Block
languagejs
themeRDark
    if (autoplay ) {});
    // Use standard pause control to stop playback
    video.addEventListener("pause", function () {
 // Autoplay will start for muted video tag only, adjust mute button and slider view
if (!(document.fullscreenElement || document.mozFullscreenElement)) {
           firstUnmuted = false;
        $('.volume').addClass('volume-none');
        $('.volume').html(HTML_VOLUME_MUTE);
// Stop stream by standard play/pause control if we're not in fullscreen
            $('#slider').slider( "value", 1 playingStream.stop();
        $(".play-pause").click();}
    });
}