Documentation

Working with Novage Peer-to-peer media loader

Introduction

Novage P2P Media Loader is an open-source JavaScript library that uses modern browser technologies — HTML5 video and WebRTC — to enable peer-to-peer (P2P) media delivery. In this guide we will review how to use Novage P2P Media Loader with Radiant Media Player for both HLS and MPEG-DASH streaming. This can be used for live and on-demand media streaming and can increase viewer experience, reduce bandwidth cost and help preserve the environment.

Radiant Media Player does not provide server-side production-ready support for using Novage P2P Media Loader. By default P2P Media Loader uses publicly available servers. Those servers can be used for testing and development but are not suitable for production environment. You will need to set up a STUN server (like coturn) and WebTorrent tracker (see this guide) for production usage

Scope of support

Novage P2P Media Loader support in Radiant Media Player is available for the following environments:

  • Chrome on desktops and Android 6+
  • Firefox on desktops and Android 6+
  • Safari on macOS
  • Safari on iPadOS (iPad)
  • Safari on iOS (iOS version 17.1+ required)
  • Edge on Windows
  • WebView for iOS and iPadOS
  • WebView for Android

All Radiant Media Player features can be used in conjunction with Novage P2P Media Loader technology. Where Novage P2P Media Loader support is not available (e.g. older iOS) the player will gracefully fallback to "classic" HLS or MPEG-DASH delivery (e.g. not WebRTC-accelerated).

Usage example

We will now prepare our player code. To help you out, we have made this as straight-forward as possible to use Novage P2P Media Loader with Radiant Media Player.

Player code example for HLS streaming

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
  <title>TODO supply a title</title>
  <!-- Import map for P2P Media Loader modules -->
  <script type="importmap">
      {
        "imports": {
          "p2p-media-loader-core": "https://cdn.jsdelivr.net/npm/p2p-media-loader-core@^2/dist/p2p-media-loader-core.es.min.js",
          "p2p-media-loader-hlsjs": "https://cdn.jsdelivr.net/npm/p2p-media-loader-hlsjs@^2/dist/p2p-media-loader-hlsjs.es.min.js"
        }
      }
  </script>
  <!-- Import Radiant Media Player as a module -->
  <script type="importmap">
      {
        "imports": {
          "rmp": "https://cdn.radiantmediatechs.com/rmp/10.7.0/js/rmp.min.mjs"
        }
      }
  </script>
</head>
<body>
  <!-- Player container element -->
  <div id="rmp"></div>
  <!-- Set up player configuration options -->
  <script type="module">
    import { HlsJsP2PEngine } from 'p2p-media-loader-hlsjs';
    import RadiantMP from 'rmp';
    const src = {
      hls: 'https://your-hls-url.m3u8'
    };
    const settings = {
      licenseKey: 'your-license-key',
      src,
      width: 640,
      height: 360,
      autoplay: true,
      // Radiant Media Player settings for best P2P assisted streaming
      hlsJSMaxBufferAhead: 60,
      hlsJSMaxBufferBehind: Infinity,
      // Passing P2P Media Loader settings
      p2pMediaLoaderEngine: HlsJsP2PEngine,
      p2pMediaLoaderConfig: {
        core: {
          swarmId: 'https://your-hls-url.m3u8'
          // Other P2P engine config parameters go here
        },
        onHlsJsCreated(hls) {
          // This can be useful for development and debugging
          hls.p2pEngine.addEventListener('onPeerConnect', (params) => {
            console.log('Peer connected:', params.peerId);
          });
          hls.p2pEngine.addEventListener('onSegmentLoaded', (details) => {
            console.log('Segment Loaded:', details);
          });
          hls.p2pEngine.addEventListener('onChunkDownloaded', (bytesLength, downloadSource, peerId) => {
            console.log(`Downloaded ${bytesLength} bytes from ${downloadSource} ${peerId ? 'from peer ' + peerId : 'from server'}`);
          });
        }
      }
    };
    const elementID = 'rmp';
    const rmp = new RadiantMP(elementID);
    async function initRmpPlayer() {
      try {
        await rmp.init(settings);
      } catch (error) {
        console.error('Radiant Media Player failed to initialize', error);
      }
    }
    initRmpPlayer();

  </script>
</body>
</html>

Player code example for MPEG-DASH streaming

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
  <title>TODO supply a title</title>
  <!-- Import map for P2P Media Loader modules -->
  <script type="importmap">
      {
        "imports": {
          "p2p-media-loader-core": "https://cdn.jsdelivr.net/npm/p2p-media-loader-core@^2/dist/p2p-media-loader-core.es.min.js",
          "p2p-media-loader-shaka": "https://cdn.jsdelivr.net/npm/p2p-media-loader-shaka@^2/dist/p2p-media-loader-shaka.es.min.js"
        }
      }
  </script>
  <!-- Import Radiant Media Player as a module -->
  <script type="importmap">
      {
        "imports": {
          "rmp": "https://cdn.radiantmediatechs.com/rmp/10.7.0/js/rmp.min.mjs"
        }
      }
  </script>
</head>
<body>
  <!-- Player container element -->
  <div id="rmp"></div>
  <!-- Set up player configuration options -->
  <script type="module">
    import { ShakaP2PEngine } from 'p2p-media-loader-shaka';
    import RadiantMP from 'rmp';
    const src = {
      dash: 'https://your-mpeg-dash-url.mpd'
    };
    const settings = {
      licenseKey: 'your-license-key',
      src,
      width: 640,
      height: 360,
      autoplay: true,
      // Radiant Media Player settings for best P2P assisted streaming
      shakaMaxBufferAhead: 60,
      shakaMaxBufferBehind: Infinity,
      // Passing P2P Media Loader settings
      p2pMediaLoaderEngine: ShakaP2PEngine,
      p2pMediaLoaderConfig: {
        core: {
          swarmId: 'https://your-mpeg-dash-url.mpd'
          // Other P2P engine config parameters go here
        }
      }
    };
    const elementID = 'rmp';
    const rmp = new RadiantMP(elementID);
    async function initRmpPlayer() {
      try {
        await rmp.init(settings);
        rmp.on('shakap2pengineavailable', (engine) => {
          const shakaP2PEngine = engine.data;
          console.log('Shaka P2P Engine is available:', shakaP2PEngine);
          shakaP2PEngine.addEventListener('onPeerConnect', (params) => {
            console.log('Peer connected:', params.peerId);
          });
          shakaP2PEngine.addEventListener('onSegmentLoaded', (details) => {
            console.log('Segment Loaded:', details);
          });
          shakaP2PEngine.addEventListener('onChunkDownloaded', (bytesLength, downloadSource, peerId) => {
            console.log(`Downloaded ${bytesLength} bytes from ${downloadSource} ${peerId ? 'from peer ' + peerId : 'from server'}`);
          });
        });
      } catch (error) {
        console.error('Radiant Media Player failed to initialize', error);
      }
    }
    initRmpPlayer();

  </script>
</body>
</html>
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.

©2015-2025 Radiant Media Player. All Rights Reserved.