Skip to main content

API & Config

P2pEngineHls API

var engine = new P2pEngineHls(p2pConfig);

Create a new P2pEngineHls instance.

If p2pConfig is specified, then the default options (shown below) will be overridden.

FieldTypeDefaultDescription
hlsjsInstanceHlsjsnullIf the instance of hlsjs is not passed in, the hlsjs based engine will not be enabled.
proxyOnlybooleanfalseForce to enable ServiceWorker based engine.
logLevelstring|boolean'error'Print log level(warn, error, none,false=none, true=warn).
tokenstringundefinedToken is used to summarize and display multi domain name data on the console. In addition, token is required while customizing channelId.
livebooleantruetell engine whether in live or VOD mode.
trackerZonestring'eu'The country code name of the tracker server address('eu', 'hk', 'us').
memoryCacheLimitObject{"pc": 400 1024 1024, "mobile": 100 1024 1024}The max size of binary data that can be stored in the memory cache.
p2pEnabledbooleantrueEnable or disable p2p engine.
webRTCConfigObject{}A Configuration dictionary providing options to configure WebRTC connections.
useHttpRangebooleantrueUse HTTP ranges requests where it is possible. Allows to continue (and not start over) aborted P2P downloads over HTTP.
sharePlaylistbooleanfalseAllow the P2P transmission of m3u8 file.
showSloganbooleanfalseDisplay slogan of cdnbye on console.
strictSegmentIdbooleanfalseUse segment url based segment id instead of sequence number based one.
geoIpPreflightbooleantrueMake a preflight request to online Geo IP database provider to get ASN and geo-related information.
swAutoRegisterbooleantrueWhether to automatically register serviceworker after initializing the engine based on serviceworker.
swFilestring'./sw.js'The file name and path of ServiceWorker.
swScopestring'./'The default scope is the location of the ServiceWorker file, and extends to all directories below. So if sw.js is located in the root directory, the ServiceWorker will control requests from all files at this domain.
mediaElemHTMLMediaElement|stringundefinedSpecify the ID or element object of the media tag, default value is the first video or audio element in the document tree.
useDiskCachebooleantrueUse IndexedDB to cache data for VOD streaming.
diskCacheLimitObject{"pc": 1500 1024 1024, "mobile": 1000 1024 1024}The max size of binary data that can be stored in the disk cache.
prefetchOnlybooleanfalseOnly use prefetch strategy in p2p downloading.

P2pEngineHls Properties and Methods

P2pEngineHls.version (static)

Get the version of SDK.

P2pEngineHls.protocolVersion (static)

Get the version of P2P protocol.

P2pEngineHls.HlsjsEngine (static)

Get the constructor of Hlsjs based P2pEngine.

P2pEngineHls.ServiceWorkerEngine (static)

Get the constructor of ServiceWorker based P2pEngine.

P2pEngineHls.tryRegisterServiceWorker(config) (static)

Static method to register ServiceWorker, if config is specified, then the default options (shown below) will be overridden.

FieldTypeDefaultDescription
swFilestring'./sw.js'The file name and path of ServiceWorker.
swScopestring'./'The default scope is the location of the ServiceWorker file.

P2pEngineHls.getBrowser() (static)

Get the name of the browser. The possible values are as follows:

  • Chrome
  • Firefox
  • Mac-Safari
  • iOS-Safari
  • X5
  • Unknown

P2pEngineHls.isSupported() (static method)

Returns true if both WebRTC Data Channel and one of MSE or SeviceWorker are supported.

P2pEngineHls.isMSESupported() (static)

Returns true if MEDIA SOURCE EXTENSIONS(MSE) is supported by the browser.

P2pEngineHls.isSeviceWorkerSupported() (static)

Returns true if ServiceWorker is supported by the browser.

engine.realEngine

Gets the currently working engine instance.

engine.engineName

Get the name of the currently working engine instance. The possible values are as follows:

  • HlsjsP2pEngine
  • HlsSwP2pEngine

engine.enableP2P()

Start p2p.

engine.disableP2P()

Stop p2p, free used resources.

engine.destroy()

Stop p2p and free used resources.

engine.registerServiceWorker()

Register ServiceWorker and return a promise.

engine.unregisterServiceWorker()

Unregister ServiceWorker and return a promise.

P2pEngineHls Events

engine.on('peerId', function (peerId) {})

Emitted when the peer Id of this client is obtained from server.

engine.on('peers', function (peers) {})

Emitted when successfully connected with new peer.

engine.on('stats', function (stats) {})

Emitted when data is downloaded/uploaded.
stats.totalHTTPDownloaded: total data downloaded by HTTP(KB).
stats.totalP2PDownloaded: total data downloaded by P2P(KB).
stats.totalP2PUploaded: total data uploaded by P2P(KB).
stats.p2pDownloadSpeed: p2p download speed(KB/s).

engine.on('serverConnected', function (connected) {})

Emitted when websocket is opened/closed.

engine.on('exception', function (e) {})

Emitted when exception occured.
e.code: Exception identifier(TRACKER_EXPT SIGNAL_EXPT)
e.message: Exception message
e.stack: Exception stack

Get p2p information from p2pConfig

p2pConfig: {
getStats: function (totalP2PDownloaded, totalP2PUploaded, totalHTTPDownloaded, p2pDownloadSpeed) {
// get the downloading statistics
},
getPeerId: function (peerId) {
// get peer Id
},
getPeersInfo: function (peers) {
// get peers information
},
onHttpDownloaded: function (traffic) {
// listen to http downloaded traffic
},
onP2pDownloaded: function (traffic, speed) {
// listen to p2p downloaded traffic
},
onP2pUploaded: function (traffic) {
// listen to p2p uploaded traffic
},
}
note

The unit of download and upload is KB. The unit of download speed is KB/s.

New API for Hls.js

Hls.engineVersion (static method)

Show the current version of SDK.

Hls.WEBRTC_SUPPORT (static method)

Is WebRTC natively supported in the environment?

if (Hls.WEBRTC_SUPPORT) {
// WebRTC is supported
} else {
// Use a fallback
}

Hls.P2pEngine (static method)

Get P2pEngineHls class from Hls, which is equivalent to the directly introduced P2pEngineHls.

Create Hls Instance

var hls = new Hls({p2pConfig: [opts]});

Create a new Hls instance, where p2pConfig is equivalent to the p2pConfig passed to P2pEngineHls. At this time, there is no need to specify hlsjsInstance.

hls.p2pEngine

Get the instance of P2pEngineHls from Hls .

HlsProxy API

new HlsProxy(config);

Create a new HlsProxy instance.

If config is specified, then the default options (shown below) will be overridden.

FieldTypeDefaultDescription
httpHeadersForPlaylistfunction(url, headers, originalHeaders)nullSet http headers for m3u8 request, for example, httpHeadersForPlaylist: (url, headers) => { headers.set('token', 'xxx') }
httpHeadersForMediaFilefunction(url, headers, originalHeaders)nullSet http headers for ts request, for example, httpHeadersForMediaFile: (url, headers) => { headers.set('token', 'xxx') }
insertTimeOffsetTagbooleanfalseInsert "#ext-x-start: time-offset = [playlistTimeOffset]" in m3u8 file to force the player to start loading from the first ts of playlist, only works on live mode
playlistTimeOffsetnumber0.01The offset in seconds to start playing the video. If the value is negative, specifies the time from the end of the playlist. The offset must not be larger than the playlist duration, only works when insertTimeOffsetTag is true
allowedMediaFilesArray['ts', 'mp4', 'm4s', 'fmp4']Additional media file extension (eg. ['txt', 'png']) that need to be intercepted
mediaFileSeparatorString'.'Separator that used to identify media file suffix
allowedPlaylistSuffixArray['m3u8']Additional playlist file extension (eg. ['txt']) that need to be intercepted

HlsProxy.version (static)

Get the version of HlsProxy.

Advanced Usage

Dynamic M3u8 Path Support

The channelId is an identifier used by our backend to match peers that are watching the same content. It is an optional parameter, and by default, we generate channelId from the content URL by removing any query parameters and protocol from it. Some m3u8 urls play the same live/vod but have different paths on them. For example, example.com/clientId1/streamId.m3u8 and example.com/clientId2/streamId.m3u8. In this case, you can format a common channelId for them.

// Set token in p2pConfig before setting channelId! Connectivity with other platform should have the same token and channelId.
p2pConfig: {
token: YOUR_TOKEN,
channelId: function (m3u8Url) {
const videoId = extractVideoIdFromUrl(m3u8Url); // make a channelId by removing the different part which is defined by yourself
return videoId;
}
// channelId: VIDEO_ID // for fixed channel id
}

Let's say your m3u8 is http://example.com/token123456/video1/playlist.m3u8, in which token123456 is the token varied by users, video1 is the ID of the video.

p2pConfig: {
token: YOUR_TOKEN,
channelId: function (m3u8Url) {
var parts = m3u8Url.split('/');
var videoId = parts[parts.length-2]+'/'+parts[parts.length-1];
return videoId;
}
}

The following is an example of the client behaviour with this channelId configured:

<!-- URL to be replaced -->
http://example.com/token123456/video1/playlist.m3u8

<!-- Resulting channelId -->
video1/playlist.m3u8
note

Interconnect with other platform should ensure that both have the same token and channelId.

P2P First Strategy

Since it takes time to establish a P2P connection, the first few pieces are downloaded using HTTP by default. Giving the peers extra time to download initial segments will increase the p2p ratio. However, it may cause delay. It is recommended to turn on the hot channel.

p2pConfig: {
waitForPeer: true,
waitForPeerTimeout: 4.0, // Http will be forcibly enabled if there is no peers on tracker or waitForPeerTimeout is timed out
sourceUrl: M3U8_URL, // the url of m3u8, like 'http://xxx.m3u8'
}

Allow Http Range Request

If http range request is activated, we are able to get chunks of data from peer and then complete the segments by getting other chunks from the CDN, thus, reducing your CDN bandwidth. To activate range requests, See Allow Http Range Request. Besides, the code below is needed:

p2pConfig: {
useHttpRange: true,
}

Bypass User-specific Segments

Sometimes we don't want some ts files to be shared, such as user-specific ts generated by SSAI (Server Side Ad Insertion). At this time, we can use the segmentBypass function to bypass it:

p2pConfig: {
segmentBypass: (url, tags) => {
return isSSAISegment(url)
},
}

Specify the Preferred Point in the Video to Start Playback.

The SDK can insert the EXT-X-START tag to start playing a live stream from the start point in time of playlist, however, it may bring more delay to the stream:

// sw.js
self.importScripts('https://cdn.jsdelivr.net/npm/@swarmcloud/hls/hls-proxy.js')
new HlsProxy({
insertTimeOffsetTag: true,
playlistTimeOffset: 0.01,
})

How to Support Other Url Suffix in sw.js

For sw.js, the default supported suffix of playlist is m3u8, the default supported suffix of media file is ts, mp4, m4s and fmp4, if other suffix type is needed, you can customize config:

self.importScripts('https://cdn.jsdelivr.net/npm/@@swarmcloud/hls/hls-proxy.js')
new HlsProxy({
allowedPlaylistSuffix: ['m3u8', 'html'], // if your playlist url is xxx.html
allowedMediaFiles: ['ts', 'mp4', 'm4s', 'fmp4', 'jpg'] // if your media file url is xxx.jpg
})

Use Your Own STUN or TURN Server

STUN (Session Traversal Utilities for NAT) allows clients to discover their public IP address and the type of NAT they are behind. This information is used to establish the media connection. Although there are default STUN servers in this SDK, you can replace them with your own via P2PConfig. TURN (Traversal Using Relays around NAT) server is used to relay traffic if direct connection fails. You can config your TURN server in the same way as STUN.

p2pConfig: {
webRTCConfig: {
iceServers: [
{ urls: YOUR_STUN_OR_TURN_SERVER }
]
}
}

How to Check Segment Validity

Sometimes we need to prevent a peer from sending a fake segment (such as the bittorrent with a hash function). CDNBye provides a validation callback with buffer of the downloaded segment, developer should implement the actual validator. For example, you can create a program that generates hashes for the segments and stores them in a specific file or injects into m3u8 playlist files the hashes information. If the callback returns false, then the segment is not valid.

p2pConfig: {
validateSegment: function (segId, buffer) {
var hash = hashFile.getHash(segId);
return hash === md5(buffer);
}
}