Versions Compared

Key

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

Table of Contents

Описание

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

 

Chrome

Firefox

Windows

+

+

Mac OS

+

+

Схема работы

Image Added


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

Краткое руководство по тестированию

Захват видеопотока с экрана компьютера и подготовка к его трансляции

1. Для теста используем демо-сервер demo.flashphoner.com и веб-приложение Screen Sharing в браузере Chrome

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

Image Added


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

Image Added


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

Image Added


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

Image Added


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

Image Added


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

Image Added

Последовательность выполнения операций (Call Flow)

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

screen-sharing.html

screen-sharing.js

Image Added


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

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

Code Block
languagejs
if (Browser.isFirefox()) {
$("#installExtensionButton").show();
interval = setInterval(function() {
if (Flashphoner.firefoxScreenSharingExtensionInstalled) {
$("#extension").hide();
$("#installExtensionButton").hide();
clearInterval(interval);
onExtensionAvailable();
}
}, 500);

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


2. Установка соединения с сервером.

Flashphoner.createSession(); code

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


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

ConnectionStatusEvent ESTABLISHED code

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


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

stream.publish(); code

Code Block
languagejs
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();
};
document.getElementById(publishStream.id()).addEventListener('resize', function(event){
resizeVideo(event.target);
});
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(){
setStatus(STREAM_STATUS.UNPUBLISHED);
//enable start button
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream){
setStatus(STREAM_STATUS.FAILED, stream);
//enable start button
onStopped();
}).publish();


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

StreamStatusEvent, статус PUBLISHING code

Code Block
languagejs
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();
};
document.getElementById(publishStream.id()).addEventListener('resize', function(event){
resizeVideo(event.target);
});
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(){
setStatus(STREAM_STATUS.UNPUBLISHED);
//enable start button
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream){
setStatus(STREAM_STATUS.FAILED, stream);
//enable start button
onStopped();
}).publish();


6. Отправка аудио-видео потока по WebRTC

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

stream.stop(); code

Code Block
languagejs
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();
};
document.getElementById(publishStream.id()).addEventListener('resize', function(event){
resizeVideo(event.target);
});
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(){
setStatus(STREAM_STATUS.UNPUBLISHED);
//enable start button
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream){
setStatus(STREAM_STATUS.FAILED, stream);
//enable start button
onStopped();
}).publish();


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

StreamStatusEvent, статус UNPUBLISHED code

Code Block
languagejs
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();
};
document.getElementById(publishStream.id()).addEventListener('resize', function(event){
resizeVideo(event.target);
});
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(){
setStatus(STREAM_STATUS.UNPUBLISHED);
//enable start button
onStopped();
}).on(STREAM_STATUS.FAILED, function(stream){
setStatus(STREAM_STATUS.FAILED, stream);
//enable start button
onStopped();
}).publish();

Разработчику

Функция демонстрации экрана может быть использована для публикации видеопотока, демонстрирующего рабочий стол или окно приложения.
Для демонстрации экрана WCS API использует расширение для браузера Chrome.
Эти расширения могут быть адаптированы для работы с необходимым именем домена.
Для публикации адаптированного расширения в интернет-магазине браузера потребуется создать аккаунт разработчика.

Аккаунт разработчика

Создайте аккаунт Google

1. Зайдите на google.com и кликните кнопку ‘Sign in’

Image Added


2. Кликните ссылку ‘Create account’ на странице ‘Sign in’

Image Added


3. Будет открыта страница ‘Create your Google Account’
Заполните необходимые поля и кликните кнопку ‘Next step’, чтобы создать аккаунт.

Зарегистрируйтесь как разработчик Chrome Web Store

1. Войдите в Chrome Developer Dashboard, используя созданный аккаунт Google

2. Внесите единовременную плату в размере US$5, чтобы подтвердить аккаунт

Image Added

Расширение браузера

Скачайте исходный код расширения, адаптируйте его для использования своего домена, и опубликуйте в магазине браузера, как описано ниже.

Адаптация

Отредактируйте файл манифеста manifest.json расширения для Chrome.
Измените:

  • имя (name)
  • автора (author)
  • описание (description)
  • адрес домашней страницы (homepage_url)
  • в "externally_connectable":"matches" замените flashphoner.com на свой домен

Добавьте свои иконки в директорию chrome-extension и отредактируйте имена файлов в "icons" и "web_accessible_resources". (Для дополнительной информации см. Manifest - Icons и Supplying Images.)

Публикация

Упакуйте файлы из директории chrome-extension в zip-архив. Опубликуйте расширение:

1. Войдите в Chrome Developer Dashboard
2. Кликните кнопку ‘Add new item’

Image Added

3. Примите соглашение разработчика

Image Added


4. Выберите файл chrome-extension.zip и кликните кнопку ‘Upload’ на странице ‘Upload’

Image Added


5. После загрузки расширения будет открыта страница для редактирования опций
Выберите необходимые опции и кликните кнопку ‘Save draft and return to dashboard’ внизу страницы.

Image Added


Image Added


6. Расширение появится в панели разработчика
Для публикации расширения кликните ссылку ‘Publish’.

Image Added


Опубликованное расширение будет иметь статус ‘Published’ как на изображении ниже.

Image Added


Для дополнительной информации см. Chrome Web Store Publishing Tutorial

Пример клиента

Скачайте исходный код WCS API отсюда.
Клиент для демонстрации экрана Screen-sharing.html находится в директории examples/demo/streaming/screen-sharing/.
Скрипт клиента: screen-sharing.js

Встроенная установка расширения

Встроенная установка позволяет инициировать установку расширения для демонстрации экрана кликом на ссылке на странице клиента.
Для работы встроенной установки расширение должно быть адаптировано, опубликовано и одобрено.

Выполните действия, описанные ниже, чтобы использовать клиент со своими расширениями.

Опции расширения

1. При публикации выберите опцию ‘Inline Install’

Image Added


2. Подтвердите и привяжите к расширению сайт со свойм доменом

  • Кликните ‘Add a New Site’

Image Added


  • В новой вкладке браузера будет открыта страница Google Search Console

Введите URL со своим доменом.

Image Added


  • Будет открыта страница с инструкцией для подтверждения сайта

Выполните требуемые шаги и кликните кнопку ‘Verify’.

Image Added


  • Если проверка пройдена, будет открыта страницa с подтверждением успешной проверки

Image Added

- Подтвержденый сайт появится в списке в опциях расширения; далее расширение может быть проассоциировано с этим сайтом

Image Added

Настройка клиента

Отредактируйте Screen-sharing.html и Screen-sharing.js

  • В Screen-sharing.html chrome-webstore-item должен указывать на ваше расширение в интернет-магазине Chrome
  • В Screen-sharing.js замените значение переменной chromeScreenSharingExtensionId на ID вашего расширения

Чтобы узнать ID расширения, кликните ‘More info’ для этого расширения в Chrome Developer Dashboard.

Image Added

Параметры источника медиа

Для конфигурации параметров источника медиа экрана могут быть использованы параметры объекта Configuration, передаваемые методу init() при инициализации экземпляра Flashphoner API.

Code Block
languagejs
var f = Flashphoner.getInstance();
var configuration = new Configuration();
....
configuration.screenSharingVideoWidth = 1920;
configuration.screenSharingVideoHeight = 1080;
configuration.screenSharingVideoFps = 10;
f.init(configuration);

Список параметров

Параметр

Описание

screenSharingVideoWidth

Ширина источника медиа экрана

screenSharingVideoHeight

Высота источника медиа экрана

screenSharingVideoFps

Частота кадров источника медиа экран

Данные параметры задают предельные значения разрешения и количество кадров в секунду (FPS). Например, screenSharingVideoWidth = 1080 означает, что ширина исходного видео не может быть более 1080 пикселей, но может быть меньше (напр., в случае передачи потока с изображением окна приложения с шириной 720 пикселей.) 

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

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

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

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

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

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

Симптомы: при создании нескольких потоков, захваченных с экрана, из одной вкладки браузера Chrome, и последующей остановке одного из них, останавливаются все потоки.
Решение: кешировать дорожки по источнику видео, и останавливать их всместе с последним потоком, использующим этот источник, например

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