Skip to content

SDK reference

The MeshedFlow browser SDK is an hls.js loader. You install it, pass it to hls.js as the loader, and put its options under loaderConfig. Beta adapters bring the same pipeline to Shaka Player and dash.js.

Install from npm for bundler workflows, or load the SDK as an ES module straight from the CDN — both ship the same build.

Terminal window
npm install @meshedflow/sdk hls.js
import { MeshedFlowLoader } from '@meshedflow/sdk';

hls.js is a normal dependency — install it from npm or a CDN as usual.

The npm package is licensed for use with the MeshedFlow service (see the LICENSE file in the package). The beta player adapters are available as subpath imports: @meshedflow/sdk/adapters/shaka and @meshedflow/sdk/adapters/dashjs.

MeshedFlowLoader implements the hls.js loader interface. hls.js constructs one per request, drives its load() / abort() / destroy() lifecycle, and hands the delivered bytes to the player through the normal callback — so from your player’s point of view nothing changes except where the bytes come from.

player.js
import Hls from 'hls.js';
import { MeshedFlowLoader } from 'https://meshedflow.com/sdk/dist/sdk.mjs';
const hls = new Hls({
loader: MeshedFlowLoader,
loaderConfig: {
signalingUrl: 'wss://signal.meshedflow.com:8445/ws',
streamId: 'cust_20260808_eb8790f7:live-demo',
authToken: '<your-sdk-token>',
},
});

These are the options most integrations touch. signalingUrl and streamId are required; everything else has a default. Types and defaults below are taken verbatim from the SDK’s MeshedFlowLoaderConfig interface.

Option Type Default Purpose
signalingUrl string — (required) WebSocket signaling endpoint the SDK connects to for peer discovery.
streamId string — (required) Stream identifier, formatted <customerId>:<name>. Scopes the session to your account.
authToken string "" JWT for peer authentication. Its customerId selects your signing allowlist and scopes your data.
originBaseUrl string "" Origin/API base URL when signaling is served from a dedicated edge port (e.g. https://example.com).
requireManifestSignature boolean true Require a valid origin signature before accepting a peer-delivered segment.
autoFetchManifestPublicKey boolean true Fetch /manifest/public-key from the signaling host when manifestPublicKey is unset.
httpFallback boolean true Fall back to CDN/HTTP when peers can’t deliver. Keep on for safe rollout.
maxPeers number 10 Maximum simultaneous peer connections (desktop default; mobile is capped lower internally).
receiveOnly boolean false Download from peers but never upload to them.
telemetry boolean true Send anonymous session telemetry. Only false disables it.
iceServers { urls: string | string[]; username?: string; credential?: string }[] Google + Cloudflare STUN ICE servers for WebRTC. TURN URLs are stripped unless allowByoTurn is true.
allowByoTurn boolean false Enterprise BYO-TURN: when false, TURN URLs are stripped from iceServers (STUN-only).
logLevel number 1 SDK log verbosity.

Instance methods on the loader. hls.js calls load() / abort() / destroy() for you; markPlaybackStart(), reportRebuffer(), getStats(), and refreshPeerMesh() are the ones you call from your application.

Method Signature Purpose
load load(context, config, callbacks) → { abort } hls.js loader entry point: loads one segment, peer-first with CDN fallback. Returns a per-request abort handle. Called by hls.js.
getStats getStats() → { offloadedBytes, totalBytes, cdnBytes, sharedBytes, offloadRatio } Current offload figures for this session. offloadRatio = offloadedBytes / totalBytes.
markPlaybackStart markPlaybackStart() → void Call when the player starts presenting frames. Enables the rebuffer counters so a stall-free session reports honest zeros.
reportRebuffer reportRebuffer(durationMs?) → void Call on every stall/rebuffer, with the stall duration in ms if known. The SDK never estimates stalls.
refreshPeerMesh refreshPeerMesh() → void Re-register with signaling and re-trigger peer matchmaking.
destroy destroy() → void Tear down signaling, peers, caches, and telemetry (final flush). Called by hls.js on teardown.
{
offloadedBytes: number; // bytes delivered by peers
totalBytes: number; // total delivered bytes (denominator)
cdnBytes: number; // bytes fetched from the CDN
sharedBytes: number; // bytes this viewer uploaded to peers
offloadRatio: number; // offloadedBytes / totalBytes, 0..1
}
player.js
import Hls from 'hls.js';
import { MeshedFlowLoader } from 'https://meshedflow.com/sdk/dist/sdk.mjs';
const video = document.getElementById('video');
const hls = new Hls({
loader: MeshedFlowLoader,
loaderConfig: {
signalingUrl: 'wss://signal.meshedflow.com:8445/ws',
streamId: 'cust_20260808_eb8790f7:live-demo',
authToken: '<your-sdk-token>',
// httpFallback, requireManifestSignature, autoFetchManifestPublicKey
// all default on — nothing else is required.
},
});
hls.attachMedia(video);
hls.loadSource('https://cdn.example.com/live-demo/master.m3u8');
// Keep a reference to the active loader instance.
let loader;
hls.on(Hls.Events.FRAG_LOADING, (_e, data) => {
loader = data.frag?.loader ?? loader;
});
// Report the two QoE signals the SDK can't observe on its own.
video.addEventListener('playing', () => loader?.markPlaybackStart(), { once: true });
video.addEventListener('waiting', () => {
const start = performance.now();
video.addEventListener('playing', () => {
loader?.reportRebuffer(performance.now() - start);
}, { once: true });
});
// Poll offload.
setInterval(() => {
const s = loader?.getStats();
if (s) console.log(`offload ${(s.offloadRatio * 100).toFixed(1)}%`);
}, 5000);

Two beta adapters put the same delivery pipeline the hls.js loader uses — peer-first fetch, automatic CDN fallback, signed-segment verification, and telemetry — behind Shaka Player and dash.js. They take the same config object as loaderConfig, and both return a handle with engine (for getStats()) and unregister().

Registers a networking scheme plugin for http/https at application priority. Segment requests (including byte-ranged ones) go through the mesh; everything else uses a plain fetch. Shaka’s abortable operations map onto the mesh fetch, so seeks and quality switches cancel cleanly.

shaka-player.js
import { registerMeshedFlowShakaSupport } from 'https://meshedflow.com/sdk/dist/adapters/shaka.mjs';
shaka.polyfill.installAll();
const video = document.getElementById('video');
const player = new shaka.Player();
await player.attach(video);
const handle = registerMeshedFlowShakaSupport(shaka, player, {
signalingUrl: 'wss://signal.meshedflow.com:8445/ws',
streamId: 'cust_20260808_eb8790f7:live-demo',
authToken: '<your-sdk-token>',
});
await player.load('https://cdn.example.com/live-demo/stream.mpd');
// Offload figures, same shape as the hls.js loader's getStats().
console.log(handle.engine.getStats());
// On teardown: restores Shaka's stock network plugins.
handle.unregister();

The third argument also accepts an existing MeshedFlowLoader (or the engine from another adapter), so a page that runs hls.js and Shaka side by side can share one signaling connection and peer mesh.

Uses the dash.js v5 request/response interceptor API (player.addRequestInterceptor / player.addResponseInterceptor). Media segment requests are served from the mesh — the interceptor hands dash.js the verified bytes through a local object URL, so the player’s own loader completes without touching the CDN. If the mesh can’t deliver, the request is passed through unchanged and dash.js fetches it from the CDN as usual. MPD and license requests are never intercepted.

dashjs-player.js
import { registerMeshedFlowDashSupport } from 'https://meshedflow.com/sdk/dist/adapters/dashjs.mjs';
const video = document.getElementById('video');
const player = dashjs.MediaPlayer().create();
const handle = registerMeshedFlowDashSupport(player, {
signalingUrl: 'wss://signal.meshedflow.com:8445/ws',
streamId: 'cust_20260808_eb8790f7:live-demo',
authToken: '<your-sdk-token>',
});
player.initialize(video, 'https://cdn.example.com/live-demo/stream.mpd', true);
console.log(handle.engine.getStats());
// On teardown: removes both interceptors.
handle.unregister();

The loader accepts more options for routing policy, manifest validation, NAT/ICE, remote config, and caching. Most integrators never set these — see More options for the full reference.