Skip to content

Рекомендации по созданию клиентского приложения

Вы можете использовать Flussonic в качестве сигнального сервера при разработке веб-сайта или приложения для обмена видео и/или аудио через WebRTC. Например, с помощью Flussonic вы можете создать приложение для видеоконференций (соединение «многие-ко-многим»), веб-сайт для проведения вебинаров или мастер-классов (соединение «один-ко-многим») и т.п. Ниже вы найдете рекомендации по использованию инструментов Flussonic в своем проекте.

Не забудьте настроить Flussonic на прием публикаций из вашего приложения, а также ознакомьтесь со способами воспроизведения потоков из Flussonic по WebRTC.

Для создания кода используйте библиотеку Flussonic WebRTC player. Ее можно установить одним из описанных ниже способов.

Инструкция по установке, описание классов библиотеки и код примера доступны на npm.

Установка с помощью NPM и webpack

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

npm install --save @flussonic/flussonic-webrtc-player

и импортировать его в ваше приложение:

import {
  PUBLISHER_EVENTS,
  PLAYER_EVENTS,
  Player,
  Publisher,
} from "@flussonic/flussonic-webrtc-player";

См. также демо-приложение ниже.

Установка без NPM и webpack

В секцию скриптов вашего HTML-файла добавьте:

<script src="https://cdn.jsdelivr.net/npm/@flussonic/flussonic-webrtc-player/dist/index.min.js"></script>

Полный пример кода страницы с плеером приведен ниже.

Пример плеера — с Webpack и без Webpack

Демо-приложение, использующее Webpack для импорта компонентов:

  • Пример приложения с Webpack и нашим плеером WebRTC.

    Это пример с компонентами, которые импортируются с помощью Webpack в приложение. Приложение можно скачать и изучить, как реализован плеер.

    Пример плеера WebRTC на JavaScript, который получает компоненты через <script>:

  • Код библиотеки Flussonic WebRTC Player для реализации плеера есть в CDN https://www.jsdelivr.com, откуда его нужно импортировать в свою веб-страницу. Для этого добавьте в секцию скриптов вашего HTML-файла строку: <script src="https://cdn.jsdelivr.net/npm/@flussonic/flussonic-webrtc-player/dist/index.min.js"></script>.

Полный пример страницы с плеером на JavaScript (похожий код есть в составе демо-приложения):

<!DOCTYPE html>
<html>
  <head>


        <style>
      .app {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: calc(100vh - 16px);
      }
      .container {
        margin-bottom: 32px;
      }
      .video-container {
        display: flex;
      }
      .controls {
      }
      .config {
      }
      #player {
        width: 640px; height: 480px; border-radius: 1px
      }
      .button {
        height: 20px;
        width: 96px;
      }
      .preview {
        position: absolute;
        right: 0;
        bottom: 0;
        z-index: 100;
      }

      .preview-text {
        position: absolute;
        left: 0;
        top: 0;
        padding: 8px;
        background: black;
        color: white;
        z-index: 10;
      }

      #preview-video {
        width: 320px;
        height: auto;
        max-width: 320px;
        max-height: 240px;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/@flussonic/flussonic-webrtc-player/dist/index.js"></script>
  </head>
  <body>
    <div class="app">
    <div class="preview">
        <div class="preview-text">preview</div>
        <video id="preview-video" controls="false" muted autoplay playsinline />
    </div>
      <div class="video-container">
        <video
                id="player"
                controls
                muted
                autoplay
                playsinline
        >
        </video>
        <pre id="debug"></pre>
      </div>

    <div class="container">
      <div class="config" id="config">
        <span id="hostContainer">
          <label for="host">Host: </label><input name="host" id="host" value="" />
        </span>
        <span id="nameContainer">
          <label for="name">Stream: </label><input name="name" id="name" value="" />
        </span>
      </div>
      <div class="controls" id="controls">
        <select id="quality">
          <option value="4:3:240">4:3 320x240</option>
          <option value="4:3:360">4:3 480x360</option>
          <option value="4:3:480">4:3 640x480</option>
          <option value="16:9:360" selected>16:9 640x360</option>
          <option value="16:9:540">16:9 960x540</option>
          <option value="16:9:720">16:9 1280x720 HD</option>
        </select>
        <button id="publish" class="button">Publish</button>
        <button id="play" class="button">Play</button>
        <button id="stop" class="button">Stop all</button>
      </div>
      <div class="errorMessageContainer" id="errorMessageContainer"></div>
    </div>

  <script>
    let wrtcPlayer = null;
    let publisher = null;

    const { Player, Publisher, PUBLISHER_EVENTS, PLAYER_EVENTS } = this.FlussonicWebRTC; 

    const getHostElement = () => document.getElementById('host');
    const getHostContainerElement = () => document.getElementById('hostContainer');
    const getNameElement = () => document.getElementById('name');
    const getNameContainerElement = () => document.getElementById('nameContainer');
    const getPlayerElement = () => document.getElementById('player');
    const getPlayElement = () => document.getElementById('play');
    const getPublishElement = () => document.getElementById('publish');
    const getStopElement = () => document.getElementById('stop');
    const getQualityElement = () => document.getElementById('stop');

    const getStreamUrl = (
      hostElement = getHostElement(),
      nameElement = getNameElement(),
    ) =>
      `${hostElement && hostElement.value}/${nameElement && nameElement.value}`;
    const getPublisherOpts = () => {
      const [, , height] = document.getElementById('quality').value.split(/:/);
      return {
        preview: document.getElementById('preview-video'),
        constraints: {
          // video: {
          //   height: { exact: height }
          // },
          video: true,
          audio: true,
        },
        canvasCallback: (canvasElement) => {
            window.myCanvasElement = canvasElement;
        },
      };
    };

    const getPlayer = (
      playerElement = getPlayerElement(),
      streamUrl = getStreamUrl(),
      playerOpts = {
        retryMax: 10,
        retryDelay: 1000,
      },
      shouldLog = true,
      log = (...defaultMessages) => (...passedMessages) =>
        console.log(...[...defaultMessages, ...passedMessages]),
    ) => {
      const player = new Player(playerElement, streamUrl, playerOpts, true);
      player.on(PLAYER_EVENTS.PLAY, log('Started playing', streamUrl));
      player.on(PLAYER_EVENTS.DEBUG, log('Debugging play'));
      return player;
    };

    const stopPublishing = () => {
      if (publisher) {
        publisher.stop && publisher.stop();
        publisher = null;
      }
    };

    const stopPlaying = () => {
      if (wrtcPlayer) {
        wrtcPlayer.destroy && wrtcPlayer.destroy();
        wrtcPlayer = null;
      }
    };

    const stop = () => {
      stopPublishing();
      stopPlaying();

      getPublishElement().innerText = 'Publish';
      getPlayElement().innerText = 'Play';
    };

    const play = () => {
      wrtcPlayer = getPlayer();
      getPlayElement().innerText = 'Playing...';
      wrtcPlayer.play();
    };

    const publish = () => {
      if (publisher) publisher.stop();

      publisher = new Publisher(getStreamUrl(), getPublisherOpts(), true);
      publisher.on(PUBLISHER_EVENTS.STREAMING, streaming);
      publisher.start();
    };

    const setDefaultValues = () => {
        getHostElement().value = config.host;
        getNameElement().value = config.name;
    };

    const setEventListeners = () => {
      // Set event listeners
      getPublishElement().addEventListener('click', publish);
      getPlayElement().addEventListener('click', play);
      getStopElement().addEventListener('click', stop);
      getQualityElement().onchange = publish;
    };

    const main = () => {
      setDefaultValues();
      setEventListeners();
    };

    const streaming = () => {
        getPublishElement().innerText = 'Publishing...';
        getPublishElement().disabled = true;

        // drawing on publishing canvas
        if (window.myCanvasElement) {
          const ctx = window.myCanvasElement.getContext('2d', { alpha: false });
          ctx.filter = 'sepia(0.75)'; // Testing filters
          ctx.font = '128px sans-serif';
          ctx.fillStyle = 'white';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'center';
          (function loop() {
            ctx.fillText(
              `It's publishing to Flussonic!`,
              window.myCanvasElement.width / 2,
              window.myCanvasElement.height / 2,
              window.myCanvasElement.width - 100,
            );
            setTimeout(requestAnimationFrame(loop), 1000 / 30); // drawing at 30fps
          })();
      }
    };

    window.addEventListener('load', main);
  </script>
    </body>
</html>

Скопируйте этот код в файл, например index.html, и откройте в браузере, чтобы проверить работу.