Недавно мы писали статью о том, как сделать расширение скриншаринга для браузера Google Chrome. В результате мы создали собственное расширение для скриншаринга, опубликовали его в Chrome Store и протестировали трансляцию экрана через Web Call Server в режиме один-ко-многим.

В этой статье мы проделаем тоже самое с браузером Firefox. Подход остается прежним и снова потребуется упаковка и публикация расширения, на этот раз в Mozilla Add-ons. В результате мы сможем делать скринкасты видеопотоков из FF без установки внешнего дополнительного ПО.

Подготовка кода расширения для FF

На текущий момент есть два способа подготовить расширение для Firefox

 

Первый способ позволяет подготовить расширение для браузеров Firefox, начиная с 45 версии. Второй заключается в сборке xpi — файла и подходит для браузеров Firefox, начиная с 38 версии.

Mozilla грозится объявить способ создания на JPM устаревшим. Тем не менее мы опишем этот способ, т.к. мы имели возможность его протестировать и он работает. Вы можете также обратиться к документации WebExtension чтобы собрать ваше расширение более новым способом. Скорее всего процесс упаковки и публикации будет очень похож на тот, что описан в этой статье.

Создаем аккаунт (если нет) на сайте Firefox Accounts и переходим в Mozilla Add-ons

Mozilla-Add-ons

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

Исходный код расширения FF

Далее открываем конфиг package.json и редактируем его для использования с собственным доменом.

Исходный конфиг выглядит так:

{
  "title": "Flashphoner Screen Sharing",
  "name": "flashphoner-screen-sharing-extension",
  "id": "@flashphoner-screen-sharing-extension",
  "version": "0.0.4",
  "description": "Enable screen sharing for flashphoner.com",
  "main": "index.js",
  "author": "Flashphoner",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  },
  "homepage": "https://flashphoner.com",
  "license": "MIT"
}

Вам нужно вписать сюда собственные данные, например так:

{
  "title": "My Screen Sharing Extension",
  "name": "my-screen-sharing",
  "id": "@my-screen-sharing",
  "version": "0.0.1",
  "description": "Enable screen sharing for mymegacat.com",
  "main": "index.js",
  "author": "Me",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  },
  "homepage": "https://mymegacat.com",
  "license": "MIT"
}

Обратите внимание, что в качестве примера мы вписали сайт mymegacat.com — это предполагаемый домен вашего сайта, со страниц которого будут идти трансляции экрана (скринкасты).

 

Упаковка расширения для скриншаринга

Далее нужно упаковать код расширения в .xpi — файл. В этом нам поможет JPM. Упаковку будем делать на Windows.

1. Скачиваем и устанавливаем Node.js + npm с сайта https://nodejs.org. Установка Node.js может потребовать перезагрузки системы.

installing-Node.js

2. Убеждаемся что NPM был установлен корректно.

npm -v

packing-screensharing-extension

3. Устанавливаем JPM

npm install jpm –global

install-JPM

4.Проверяем что JPM установлен

jpm

JPM-is-installed

5. Создаем XPI-файл с помощью JPM. Для этого переходим в ранее скачанную папку firefox-extension и выполняем команду

jpm xpi

create-XPI-file

Готово.

В результате мы получили XPI-файл расширения, готовый для публикации в Mozilla Add-ons.

 

Публикация расширения в Mozilla Add-ons

  1. Начинаем с того, что логинимся в Mozilla Add-ons и переходим в меню Tools / Submit a New Add-on 

    publishing-extension-Mozilla-Add-ons

  2. Загружаем наш XPI-файл. 

    upload-XPI-file

  3. После загрузки ваше расширение пройдет валидацию и можно нажимать Continue

    screensharing-extension

  4. Управлять вашими расширениями вы можете из меню Tools / Manage My Submissions 

    tools -manage-my-submissions

 

Более подробно о распространении и подписи ваших расширений можно почитать здесь.

 

Делаем HTML-страницу для скринкастинга из Firefox

Скринкастинг в Firefox работает по технологии WebRTC, также как и в Google Chrome. В качестве WebRTC — платформы, транслирующей видеопотоки, захваченные с экрана, мы будем использовать Web Call Server 5 и скрипт flashphoner.js, который представляет API для работы с сервером и входит в сборку Web SDK.

Код скринкастинга будет содержать:

  • screen-sharing-ff.html
  • screen-sharing-ff.js
  • flashphoner.js
  • flashphoner_screen_sharing-0.0.9-an+fx.xpi

 

Вам нужно использовать ваш XPI файл расширения, который был ранее создан с помощью JPM.

Код HTML страницы достаточно простой из 20 строк:



    Screen Sharing
    
        



Screen Sharing

Capture

Preview

Страница использует два скрипта: screen-sharing-ff.js и flashphoner.js

На загрузку страницы вызывается функция инициализации init_page()

Кнопка installExtensionButton служит для быстрой установки расширения.

Div — блок localVideo используется для отображения видео, захваченного с экрана локально.

Div — блок remoteVideo используется для отображения видео трансляции, которое пришло с сервера. Например, если мы хотим оставить только плеер на отдельной странице, мы можем использовать только один Div — блок remoteVideo. В данном же примере мы располагаем плеер и стример на одной странице для ускорения тестирования.

И наконец, кнопка publishBtn начинает трансляцию.

Ниже показано как выглядит HTML-страница скринкастинга в действии в браузере Mozilla Firefox 51.0.1

HTML-page-with-screencasting

Теперь обратимся к скрипту screen-sharing-ff.js и поймем что происходит там

var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
var localVideo;
var remoteVideo;

function init_page() {
    //init api
    try {
        Flashphoner.init();
    } catch (e) {
        //can't init
        return;
    }
    var interval = setInterval(function() {
        if (Flashphoner.firefoxScreenSharingExtensionInstalled) {
            document.getElementById("installExtensionButton").disabled = true;
            clearInterval(interval);
            localVideo = document.getElementById("localVideo");
            remoteVideo = document.getElementById("remoteVideo");
        }else{
            document.getElementById("installExtensionButton").disabled = false;
        }
    }, 500);
}

function connectAndShareScreen() {
    var url = "wss://wcs5-eu.flashphoner.com:8443";
    console.log("Create new session with url " + url);
    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);
    }).on(SESSION_STATUS.FAILED, function () {
        setStatus(SESSION_STATUS.FAILED);
    });

}

function startStreaming(session) {
    var streamName = "test123";
    var constraints = {
        video: {
            width: 320,
            height: 240,
            frameRate: 10,
            type: "screen"
        }
    };
    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) {
            //enable stop button
        }).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();
            }
        }).play();
    }).on(STREAM_STATUS.UNPUBLISHED, function () {
        setStatus(STREAM_STATUS.UNPUBLISHED);
        //enable start button
    }).on(STREAM_STATUS.FAILED, function () {
        setStatus(STREAM_STATUS.FAILED);
    }).publish();
}

//show connection or local stream status
function setStatus(status) {
    var statusField = document.getElementById("status");
    statusField.innerHTML = status;
}

//install extension
function installExtension() {
    var params = {
        "Flashphoner Screen Sharing": { URL: "../../dependencies/screen-sharing/firefox-extension/flashphoner_screen_sharing-0.0.9-an+fx.xpi",
            IconURL: "../../dependencies/screen-sharing/firefox-extension/icon.png",
            Hash: "sha1:96699c6536de455cdc5c7705f5b24fae28931605",
            toString: function () { return this.URL; }
        }
    };
    InstallTrigger.install(params);
}

Работа этого скрипта подробно описана в предыдущей статье про скринкастинг из браузера Google Chrome.

В связи с этим, сфокусируемся на отличиях, специфичных именно для Firefox, а их всего три:

  1. При инициализации мы ничего не передаем, в то время как для Chrome передавали ID расширения. Для FF он будет передан в другом месте.
    Flashphoner.init();
  2. Проверка установленного расширения тоже осуществляется немного иначе чем в Chrome. Проверяется флаг Flashphoner.firefoxScreenSharingExtensionInstalled.
    var interval = setInterval(function() {
            if (Flashphoner.firefoxScreenSharingExtensionInstalled) {
                document.getElementById("installExtensionButton").disabled = true;
                clearInterval(interval);
                localVideo = document.getElementById("localVideo");
                remoteVideo = document.getElementById("remoteVideo");
            }else{
                document.getElementById("installExtensionButton").disabled = false;
            }
        }, 500);
    
  3. Код установки расширения по кнопке installExtensionButton отличается от кода установки расширения в Chrome и использует файл расширения XPI напрямую, в то время как в Chrome мы ставили ссылку на Chrome Store. Обратите внимание, что в качестве названия вместо Flashphoner Screen Sharing должно быть указано название вашего расширения, указанное ранее в package.json на этапе упаковки расширения.
    function installExtension() {
        var params = {
            "Flashphoner Screen Sharing": { URL: "../../dependencies/screen-sharing/firefox-extension/flashphoner_screen_sharing-0.0.9-an+fx.xpi",
                IconURL: "../../dependencies/screen-sharing/firefox-extension/icon.png",
                Hash: "sha1:96699c6536de455cdc5c7705f5b24fae28931605",
                toString: function () { return this.URL; }
            }
        };
        InstallTrigger.install(params);
    }
    

 

В результате, с учетом этих трех различий, мы получили рабочий скрипт screen-sharing-ff.js, который готов к установке расширения и скринкастингу в Firefox.

 

Подготовка к тестированию WebRTC скриншаринга в FF

Для того чтобы начать тестирование, вам потребуется залить все скрипты на ваш веб-хостинг:

  • screen-sharing-ff.html
  • screen-sharing-ff.js
  • flashphoner.js
  • flashphoner_screen_sharing-0.0.9-an+fx.xpi

 

В самих скриптах должен использоваться ваш XPI-файл

Везде — на хостинге и в скриптах должен использоваться ваш домен (помните, мы указывали mymegacat.com при упаковке расширения).

Сервер Web Call Server 5, который мы используем в качестве WebRTC-платформы для трансляции экрана, принимает соединения по протоколу Websockets и может быть установлен как на отдельном VPS / VDS, так и на одном сервере с вебсайтом.

Для коннекта к серверу вам потребуется Websocket-адрес в следующем виде:

wss://wcs5-eu.flashphoner.com:8443

В скрипте screen-sharing-ff.js этот адрес захардкожен. Это демо-сервер.
Вы можете установить свой сервер или запустить готовый образ на Amazon EC2.

 

Тестируем скринкастинг из FF и раздаем поток через сервер

  1. Открываем страницу screen-sharing-ff.html в браузере Firefox и нажимаем кнопку Install Now, которая активна пока не установлено расширение. 

    screen-sharing-ff.html

  2. Далее подтверждаем установку расширения и получаем сообщение об успешной установке. После этого кнопка Install Now уходит в disabled, т.к. наш скрипт screen-sharing-ff.js видит, что расширение уже установлено и в кнопке больше нет необходимости. 

    install-now-disabled

  3. Нажимаем кнопку Connect and share screen чтобы начать тестирование.

 

Firefox спросит нас какое именно окно мы намерены скринкастить, после чего отправит видеопоток на Web Call Server и отобразит захваченный поток в блоке localVideo HTML-страницы.

Под кнопкой отобразится статус PUBLISHING — видео захватывается с экрана и видеотрафик идет на сервер.

Через пару секунд видео, полученное с сервера начнет воспроизводиться в плеере — блоке remoteVideo. Это видео, которое прошло через сервер и вернулось на воспроизведение. Похожим образом можно проигрывать Live-видео на других страницах, тем самым получая one-to-many трансляцию или скринкастинг.

one-to-many-broadcasting-screencasting

 

Ссылки

Скриншаринг на сайте из браузера Google Chrome по WebRTC
Разработка и упаковка WebExtension для Firefox
Упаковка расширения для Firefox с помощью JPM
Firefox Accounts — получить аккаунт
Mozilla Add-ons — опубликовать свое расширение
Исходный код расширения для упаковки в JPM
Node.js — быстрая установка NPM и JPM
Информация о распространении и подписи расширений на сайте Mozilla
Web Call Server 5 — платформа для ретрансляции видеопотоков по WebRTC
Web SDK — набор скриптов API, содержащий flashphoner.js для работы с сервером
Установка WCS5 на свой сервер
Статья про запуск образа Web Call Server в облаке Amazon EC2
Скачать исходный код тестовой страницы screen-sharing-ff.html и screen-sharing-ff.js

 

Статьи по теме

Скриншаринг на сайте по WebRTC из браузера Chrome

 

Возможности продукта

Демонстрация и трансляция экрана браузера по технологии WebRTC (Screen Sharing)