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
Section titled “Install”Install from npm for bundler workflows, or load the SDK as an ES module straight from the CDN — both ship the same build.
npm install @meshedflow/sdk hls.jsimport { MeshedFlowLoader } from '@meshedflow/sdk';import { MeshedFlowLoader } from 'https://meshedflow.com/sdk/dist/sdk.mjs';<script type="module" src="https://meshedflow.com/sdk/dist/sdk.mjs"></script>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.
The loader
Section titled “The loader”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.
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>', },});Core options
Section titled “Core options”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. |
Methods
Section titled “Methods”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. |
getStats() return value
Section titled “getStats() return value”{ 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}Full hls.js integration
Section titled “Full hls.js integration”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);Player adapters (beta)
Section titled “Player adapters (beta)”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().
Shaka Player adapter (beta)
Section titled “Shaka Player adapter (beta)”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.
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.
dash.js adapter (beta)
Section titled “dash.js adapter (beta)”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.
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();More options
Section titled “More options”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.
Related
Section titled “Related”- Quickstart — the step-by-step wiring.
- HTTP API reference — the endpoints behind the SDK.
- Content signing & origins — how verification works.