Skip to main content

React Native SDK advanced usage

This guide follows the native SDK workflow: live/VOD, direct files, per-session options, preload, runtime controls, monitoring, and platform policy. Examples use the client from Quick integration; player variables belong to your application.

Live and VOD integration policy​

The SDK detects live/VOD automatically; both use the same quick integration. Player feedback is optional and helps P2P scheduling.

Live​

Report the continuous playable buffer ahead of the current position to tune P2P prefetch. For example, position 60 s with buffer ending at 70 s means 10,000 ms. Live start position and target latency remain player settings.

await session.updateBufferedDurationMs(bufferedDurationMs);

VOD​

Also report playback position so the SDK can prefer already-connected peers with nearby progress and the requested segment. Update position immediately after a completed seek.

await session.updateCurrentPositionMs(positionMs);
await session.updateBufferedDurationMs(bufferedDurationMs);

Use non-negative milliseconds; do not count across buffer gaps. Send valid player state about once per second. Stop and drain updates before closing the session.

Complete player feedback example

Convert your player callbacks to these millisecond inputs. Serialize asynchronous updates and handle bridge errors.

async function syncPlaybackState(
positionMs: number, bufferedDurationMs: number, isLive: boolean,
) {
if (!isLive && Number.isFinite(positionMs) && positionMs >= 0) {
await session.updateCurrentPositionMs(positionMs);
}
if (Number.isFinite(bufferedDurationMs) && bufferedDurationMs >= 0) {
await session.updateBufferedDurationMs(bufferedDurationMs);
}
}

Direct MP4 / MP3 playback​

MP4 and MP3 use direct file URLs. Keep a stable contentId and set mimeType explicitly when the URL has no extension:

const session = await client.createPlaybackSession({
url: 'https://cdn.example.com/video/trailer.mp4',
contentId: 'trailer-2026',
mimeType: 'mp4',
});

Pass session.playbackUrl to a player that supports the format. For MP3, replace the URL and MIME hint with an MP3 URL and mp3. Acceleration requires single-range HTTP requests and a valid Content-Range response from the origin. If the origin does not support that, P2P acceleration is not enabled; playback and seeking still depend on the origin and player. The SDK does not decode media or bypass DRM.

Per-playback configuration and origin authorization​

Configure the client once, then provide per-media options when creating each session:

ScopeOptionPurpose
ClientkeySDK Key for the target application/platform
Clientp2pEnabledInitial P2P preference, subject to console policy
SessionurlOriginal media URL; required
SessioncontentIdStable identity of the same content
SessionmimeTypem3u8, mpd, mp4, or mp3
SessionoriginHeadersHeaders sent only to your media origin

Pass a stable contentId for a short-lived signed URL. Set mimeType when the URL has no extension, and pass origin authorization through originHeaders:

const session = await client.createPlaybackSession({
url: signedUrl,
contentId: 'movie-2026-001',
mimeType: 'mp4',
originHeaders: { Authorization: `Bearer ${originToken}` },
});

These headers are used for the origin request and are not sent to peers. Renew signatures in the application layer, keep the same contentId, and keep SDK keys, origin tokens, and full signed URLs out of logs.

Preload and content switching​

Explicit preload is an optional HLS/DASH warmup: it fetches the manifest and first media segment in the background, not the entire video. It may also start Tracker/Peer connections early, but a successful queue operation does not guarantee that peers or media are ready. An unplayed candidate session does not upload media to peers. MP4/MP3 direct files do not use this explicit preload path.

Keep the candidate session and reuse its playback URL when selected. Before closing a session, stop and drain its player-state updates and remove its event subscriptions; do not continue callbacks against a closed session. Preload does not prepare a decoder or render a frame.

Use one session per player. For a content list, prepare the next item before the user switches to it:

Prepare candidate content​

const next = await client.createPlaybackSession({
url: nextItem.url,
contentId: nextItem.id,
mimeType: 'm3u8',
});

const queued = await next.preload();
if (queued) {
// Pass next.playbackUrl to the player only when the item becomes active.
}

preload() returning true means that warmup was queued; it does not mean that the first frame is ready. Close discarded sessions promptly so they do not keep connections open.

Switch to the candidate​

When switching to the prepared item, detach the old media from the player, close the old session, then use next.playbackUrl and retain next as the active session. Preload does not drive a player, and a queued request does not guarantee that a peer is ready. Warmup can consume network traffic.

Cancel candidate content​

If the candidate is discarded, close it instead:

await next.close();

Runtime controls​

P2P toggles​

For a rollout or investigation, disable P2P only for the active session:

await session.setP2pEnabled(false);
await session.setP2pEnabled(true);

When P2P, Tracker, or configuration is unavailable, keep playing session.playbackUrl. Do not replace the URL or stop the player because the peer count is zero, p2pUnavailable was emitted, or one request used CDN.

Events and monitoring​

Filter events by clientId or sessionId, and remove the subscription before closing the session:

const subscription = addMeshStreamEventListener((event) => {
if (event.type === 'p2pUnavailable') {
console.info('P2P unavailable:', event.reason);
}
if (event.type === 'statistics') {
console.info('peers=', event.statistics?.connectedPeers);
}
}, { clientId: client.clientId, sessionId: session.sessionId });

const status = await client.getStatus();
const stats = await session.getStats();
const diagnostics = await session.getDiagnostics();

subscription.remove();

Events include peerCountChanged, playbackPrepared, p2pReady, p2pUnavailable, statistics, cdnFallback, trackerError, and peerConnectError. cdnFallback reports a request that used CDN; it does not mean that the whole session switched to CDN.

FieldMeaning
httpDownloadedBytes downloaded through HTTP/CDN
p2pDownloadedBytes downloaded from peers
p2pUploadedBytes shared with peers
connectedPeersCurrent connected peer count
downloadOffloadRatioP2P download bytes / total HTTP and P2P download bytes; 0–1

Multiply downloadOffloadRatio by 100 for a percentage. It is a download-offload measure, not an upload ratio. With no downloaded bytes, the value is zero; one peer or one CDN fallback event does not establish an offload result. Inspect getDiagnostics() for connection timing and error details; optional fields may be absent.

Version diagnostics​

Record the JavaScript package version, native SDK version, and platform when reporting an issue:

const version = await MeshStream.getVersion();
// { packageVersion, nativeSdkVersion, platform }
Verify P2P delivery
  1. Start with one device: verify playback, seeking for VOD, and normal playback with P2P disabled.
  2. Run two devices on the same content with a consistent contentId. For VOD, use overlapping playback positions; for live, play the same channel. Keep the media bytes and timeline consistent; do not reuse an ID for different assets or personalized manifests.
  3. Check that player updates use milliseconds and continue after the manifest loads. At position 60 seconds with continuous buffer ending at 70 seconds, the buffer value is 10,000 ms; refresh VOD position after a completed seek.
  4. Observe changes in P2P downloaded bytes and offload ratio over a playback interval. A connected peer alone does not prove that media was downloaded through P2P. Results depend on overlapping available segments, network conditions, and platform policy.
  5. Disable P2P and verify that playback continues through CDN. Then stop state updates and event subscriptions before closing the session, and verify that switching content creates no calls against the closed session.

Network and platform policy​

Wi-Fi, cellular, Ethernet, account eligibility, and quota policy are evaluated by the native SDK and console policy. The local P2P switch cannot override a server-side restriction. Do not pass region, areaCode, or Tracker/ICE endpoints as client options. Use getStatus() to inspect effectiveP2pEnabled and reason; a peer count of zero alone does not indicate a playback failure.

The playback URL uses an HTTP loopback proxy even for HTTPS origins. Configure both Android and iOS as described in Installation and setup, and confirm that the policy applies to Release builds. Merge exceptions into the application network policy. Restrict public HTTP origin exceptions to required domains; prefer HTTPS.

Lifecycle and background playback​

When changing content or destroying a screen:

  1. Stop telemetry updates, await in-flight updates, and remove event subscriptions.
  2. Stop the player and release its current media reference.
  3. Close the current session and any unused preload candidates.
  4. Close the client only after no other active sessions need it.

Keep the player and session alive while authorized background or picture-in-picture playback continues. Configure background modes, audio sessions, and player capabilities in the host application. Navigating away from a page must follow your playback policy rather than automatically closing a background playback session. The SDK does not bypass operating-system limits or guarantee continuous background sharing.

await session.close();
await client.close();

Capability boundary​

The following table describes the current public React Native wrapper API. Use the wrapper options documented on this page rather than passing native-only properties:

CapabilityCurrent wrapper API
HLS / DASH / MP4 / MP3, origin headers, stable content IDsSupported through session options
Multiple sessions, preload, P2P toggle, player telemetry, statisticsSupported through the methods above
maxMemoryBytes, peer connection limits, request timeout, native log levelNo public wrapper options currently exposed
Apple setPictureInPictureActiveNo public wrapper method currently exposed; not implied by player PiP support
Decoder, ABR, DRM, player cache, OS background permissionsManaged by the player and application

P2P unavailability is not a media playback error. Keep using the valid session URL; base retries or termination on actual player errors and origin responses. Native initialization or bridge failures still need application error handling.

Installation and setup · Quick integration · Troubleshooting