Stream switching and ABR
Multi stream configuration, integrated ABR and stream switching features
The nanoStream H5Live Player Version 4.3 is introducing new features related to stream switching and integrated adaptive bitrate playback enabling automatic and application/viewer controlled stream switching either separately or in combination. One potential combined use case is a video quality selection offering options auto, high, medium, low to the viewer.
To start using the stream switching feature make sure you're using the minimum required nanoStream H5Live Player version 4.3 !
Configuration changes
Stream configuration
Whether you want to configure a single stream or multiple streams you need to configure them inside the config.source.entries
object during the initial setup
call.
You can find more information on how to configure the player in our API documentation.
ABR stream group configuration
Please find more information about stream group configuration here.
Single Stream configuration
The old pattern to configure a single stream is deprecated with this version! Please follow this new example to configure a single stream.
Example OLD single stream configuration (DEPRECATED)
var config = {
"source" : {
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYYY"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
}
},
"playback": {
...
},
"style": {
...
}
};
Example single stream configuration
var config = {
"source" : {
"entries": [
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYYY"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
}
]
},
"playback": {
...
},
"style": {
...
}
};
Multi stream configuration
You can configure a list of multiple streams inside the config.source.entries
object.
Depending on the intended use case these can be:
multi-bitrate renditions of the same content
multiple streams of different content.
The nanoStream transcoding service allows a single stream to be delivered in different multi-bitrate qualities eg. high (original) transcoded in medium and low quality.
The entries need to be ordered by bitrate with index zero holding the highest bitrate.
The initial stream/rendition can be selected by assigning config.source.startIndex
to the index of an entry.
Multi stream configuration is required for both the integrated ABR and also the switchStream feature!
Example multi stream configuration (with ABR)
var config = {
"source" : {
"entries": [ // array of 'entry' objects
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY0"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
},
{
"index": 1,
"label": "medium",
"tag": "this is a medium quality stream",
"info": {
"bitrate": 800,
"width": 864,
"height": 480,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY1"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
},
{
"index": 2,
"label": "low",
"tag": "this is a low quality stream",
"info": {
"bitrate": 400,
"width": 426,
"height": 240,
"framerate": 15
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY2"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
}
],
"options": {
"adaption": {
"rule": "deviationOfMean2" // enable ABR
},
"switch": {
'method': 'server',
'pauseOnError': false,
'forcePlay': true,
'fastStart': false,
'timeout': 10,
}
},
"startIndex": 2 // lowest
},
"playback": {
...
},
"style": {
...
}
};
In case you either provide an invalid startIndex
or don't provide one at all the player starts the stream with index 0.
The player will set the default adaption rule none if no adaption rule is passed. You can still switch between your pre-configured entries manually with the switchStream API.
Example multi stream configuration (with ABR) and playback security
var config = {
"source" : {
"entries": [ // array of 'entry' objects
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-splay.nanocosmos.de/splay",
"streamname": "XXXXX-YYYY0"
},
"server": {
"websocket": "wss://bintu-h5live-secure.nanocosmos.de:443/h5live/authstream/stream.mp4",
"hls": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/playlist.m3u8",
"progressive": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/stream.mp4"
},
"token": "",
// security for streamname XXXXX-YYYY0 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {}
},
{
"index": 1,
"label": "medium",
"tag": "this is a medium quality stream",
"info": {
"bitrate": 800,
"width": 864,
"height": 480,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-splay.nanocosmos.de/splay",
"streamname": "XXXXX-YYYY1"
},
"server": {
"websocket": "wss://bintu-h5live-secure.nanocosmos.de:443/h5live/authstream/stream.mp4",
"hls": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/playlist.m3u8",
"progressive": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/stream.mp4"
},
"token": "",
// security for streamname XXXXX-YYYY1 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {}
},
{
"index": 2,
"label": "low",
"tag": "this is a low quality stream",
"info": {
"bitrate": 400,
"width": 426,
"height": 240,
"framerate": 15
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-splay.nanocosmos.de/splay",
"streamname": "XXXXX-YYYY2"
},
"server": {
"websocket": "wss://bintu-h5live-secure.nanocosmos.de:443/h5live/authstream/stream.mp4",
"hls": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/playlist.m3u8",
"progressive": "https://bintu-h5live-secure.nanocosmos.de:443/h5live/authhttp/stream.mp4"
},
"token": "",
// security for streamname XXXXX-YYYY2 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {}
}
],
"options": {
"adaption": {
"rule": "deviationOfMean2" // enable ABR
},
"switch": {
'method': 'server',
'pauseOnError': false,
'forcePlay': true,
'fastStart': false,
'timeout': 10,
}
},
"startIndex": 2 // lowest
},
"playback": {
...
},
"style": {
...
}
};
Example bintu multi stream configuration (with ABR)
var config = {
"source" : {
"entries": [ // array of 'entry' objects
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY0"
}
},
{
"index": 1,
"label": "medium",
"tag": "this is a medium quality stream",
"info": {
"bitrate": 800,
"width": 864,
"height": 480,
"framerate": 30
},
"hls": "",
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY1"
}
},
{
"index": 2,
"label": "low",
"tag": "this is a low quality stream",
"info": {
"bitrate": 400,
"width": 426,
"height": 240,
"framerate": 15
},
"hls": "",
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY2"
}
}
],
"options": {
"adaption": {
"rule": "deviationOfMean2" // enable ABR
},
"switch": {
'method': 'server',
'pauseOnError': false,
'forcePlay': true,
'fastStart': false,
'timeout': 10,
}
},
"startIndex": 2 // lowest
},
"playback": {
...
},
"style": {
...
}
};
Example bintu multi stream configuration (with ABR) and playback security
var config = {
"source" : {
"entries": [ // array of 'entry' objects
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"h5live": {
// security for bintu streamid XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY0 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY0"
}
},
{
"index": 1,
"label": "medium",
"tag": "this is a medium quality stream",
"info": {
"bitrate": 800,
"width": 864,
"height": 480,
"framerate": 30
},
"hls": "",
"h5live": {
// security for bintu streamid XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY1 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY1"
}
},
{
"index": 2,
"label": "low",
"tag": "this is a low quality stream",
"info": {
"bitrate": 400,
"width": 426,
"height": 240,
"framerate": 15
},
"hls": "",
"h5live": {
// security for bintu streamid XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY2 here
"security": {
"token": "TOKEN_HERE",
"expires": "EXPIRES_HERE",
"options": "OPTIONS_HERE",
"tag": "TAG_HERE"
}
},
"bintu": {
"streamid": "XXXXXXXX-XXXX-XXXX-XXXX-YYYYYYYYYYY2"
}
}
],
"options": {
"adaption": {
"rule": "deviationOfMean2" // enable ABR
},
"switch": {
'method': 'server',
'pauseOnError': false,
'forcePlay': true,
'fastStart': false,
'timeout': 10,
}
},
"startIndex": 2 // lowest
},
"playback": {
...
},
"style": {
...
}
};
Switch options
There are multiple possible switch options that can be set directly over the config.source.options.switch
object.
Possible options:
method
:- The preferred switching method
- Possible values are 'server' (default) and 'client'
pauseOnError
:- If set the player stops in case an error occurs during the process of stream switching
- Possible values are false (default) and true
forcePlay
:- If set the player starts the playback even though the player is in
paused
state - Possible values are false and true (default)
- If set the player starts the playback even though the player is in
timeout
:- The maximal time to wait in seconds before running into a timeout
- If the time limit is reached the error 4006 will be thrown inside the
onSwitchStreamFail
event - The default value is 10 seconds and the possible range is between 5 and 30 seconds
tag
:- This custom field can be any string you like and will be returned in all of the switchStream completion events. (
onSwitchStreamSuccess
,onSwitchStreamFail
andonSwitchStreamAbort
)
- This custom field can be any string you like and will be returned in all of the switchStream completion events. (
You can find more specific information on the possible options here.
Automatic bitrate adaption (ABR)
The nanoStream H5Live Player automatic bitrate adaption (ABR) feature decides which quality to play, to accommodate your users' network situation and avoid bufferings and frame drops.
How to use
The following steps are required to setup the nanoStream H5Live Player with automatic bitrate adaption:
- Configuration of two or more streams in
config.source.entries
- ordered by bitrate with index zero holding the highest bitrate
- The order is determined by the
index
property, not by the position in the list - Selecting the initial stream/rendition by assigning the index to
config.source.startIndex
- Assigning an adaption rule other than
none
toconfig.source.options.adaption.rule
- Currently available adaption rules are:
none
- Manual switchingdeviationOfMean
- Buffer based bitrate adaption ruledeviationOfMean2
- Enhanced buffer based bitrate adaption rule (added in v4.5)
To choose the right quality to start with highly depends on the available qualities and the use case.
A very common way is to not start with the highest (eg. medium/low) quality. Therefore there is an intial switch up mechanism that switches to a higher quality until the matching quality for the present bandwidth is found.
This happens only on the initialization of the player and won't happen if you chose to start with the highest quality (index 0) by default.
Advanced ABR settings
Quality Omission
The ABR Stream Omission allows users to:
- Specify an arbitrary subset of streams to be omitted from automatic bitrate adaptation
- Maintain full flexibility in manual stream selection
- Provide precise control over stream quality ranges
Potential use case:
- omit high or low quality depending on expected bandwith conditions e.g. mobile vs desktop
Configuration:
source.options.adaption.omitRenditions
- Type: Array of strings or numbers
- Possible Values:
- Quality strings
"high"
"medium-high"
"medium"
"medium-low"
"low"
- Numeric Indices:
- integer between
0
(typically corresponds to highest quality) andconfig.source.entries.length - 1
- integer between
- Quality strings
Index Mapping:
- The stream index mapping ensures consistent and predictable stream selection across different stream configurations
Number of Streams | high | medium-high | medium | medium-low | low |
---|---|---|---|---|---|
2 | 0 | 0 | 1 | 1 | 1 |
3 | 0 | 1 | 1 | 1 | 2 |
4 | 0 | 1 | 2 | 2 | 3 |
5 | 0 | 1 | 2 | 3 | 4 |
Examples:
- qualities
var config = {
"source": {
"group": {
"id": 'xxxxxxxx-zzzz-yyy-aaaa-aaabbbcccddd',
"startQuality": 'low'
},
"options": {
"adaption": {
// Omit highest quality from ABR
"omitRenditions": ["high"]
}
}
}
};
- indexes
var config = {
"source": {
"entries": [
...
],
"options": {
"adaption": {
"rule": "deviationOfMean2"
// Omit highest rendition (highest quality, "high")
"omitRenditions": [0]
}
},
"startIndex" : 2
}
};
Quality Down Switch Adjustment
The downStep
parameter specifies the minimum number of quality steps included in an ABR (Adaptive Bitrate) down switch, applicable only when the adaption.rule
is set to 'deviationOfMean'
or 'deviationOfMean2'
.
Configuration:
source.options.adaption.downStep
- Type: Number
- Possible Values:
- integer between
1
(default) andconfig.source.entries.length - 1
- integer between
Example multi stream configuration (with ABR)
var config = {
"source" : {
"entries": [ // array of 'entry' objects
{
"index": 0,
"label": "high",
"tag": "this is a high quality stream",
"info": {
"bitrate": 1200,
"width": 1280,
"height": 720,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY0"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
},
{
"index": 1,
"label": "medium",
"tag": "this is a medium quality stream",
"info": {
"bitrate": 800,
"width": 864,
"height": 480,
"framerate": 30
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY1"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
},
{
"index": 2,
"label": "low",
"tag": "this is a low quality stream",
"info": {
"bitrate": 400,
"width": 426,
"height": 240,
"framerate": 15
},
"hls": "",
"h5live": {
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": "XXXXX-YYYY2"
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
},
"token": "",
"security": {}
},
"bintu": {}
}
],
"options": {
"adaption": {
"rule": "deviationOfMean2" // enable ABR
},
"switch": {
'method': 'server',
'pauseOnError': false,
'forcePlay': true,
'fastStart': false,
'timeout': 10,
}
},
"startIndex": 2 // lowest
},
"playback": {
...
},
"style": {
...
}
};
In case you either provide an invalid startIndex
or don't provide one at all the player starts the stream with index 0.
The player will set the default adaption rule none if no adaption rule is passed. You can still switch between your pre-configured entries manually with the switchStream API.
switchStream API
The switchStream
feature enables the application/viewer to perform stream switches on the pre-configured stream list by referencing the index property of the target stream entry.
You can find more information on the switchStream API in our API documentation.
How to use
- Configuration of two or more streams in
config.source.entries
- Selecting the initial stream by assigning the index to
config.source.startIndex
- Assigning the adaption rule
none
toconfig.source.options.adaption.rule
- Applying switches by calling
switchStream(index)
with the index of the target stream entry - Listening to related event notifications
- onSwitchStreamInit
- onSwitchStreamSuccess
- onSwitchStreamAbort
- onSwitchStreamFail
Manual switching via switchStream API will disable any further ABR controlled behavior. Use the setAdaption API to again reinitialize the automatic adaption. You can read more on how to combine automatic and manual switching here.
Example switchStream call:
player.switchStream(1).then(function (config) {
console.log('switch stream initialized with config: ' + JSON.stringify(config));
}, function (error) {
console.log(error);
});
The switchStream API returns a promise that is rejected if the provided index
parameter is out of range.
switchStream events
With the release of the switchStream
API there are also 4 new events you should listen to:
Start Event
- onSwitchStreamInit: This event signals an initialized switch stream request. This is only a start event that will be followed by one of the completion events.
Completion Events
- onSwitchStreamSuccess: This event signals a successful switch stream request and fires if the stream was switched.
- onSwitchStreamFail: This event signals a failed switch stream request. Fired if an error occurs during the stream switch.
- onSwitchStreamAbort: This event signals an aborted switch stream request. Possible reasons are an equal source ('equalsource'), a superseding ('superseded') or the time difference between two following
switchStream
calls that is too small ('frequency').
...there will be an onStreamInfo
event indicating that the first image of the new stream is getting played out.
Difference switchStream API / updateSource API
The switchStream API allows to only choose between the pre-configured stream list (config.source.entries
) by referencing the index of the entry while the updateSource API replaces the entire source (config.source
) with a new source.
Click here to get more information on the updateSource API
setAdaption API
The setAdaption
feature enables the application/viewer to change the adaption rule eg. from manually controlled to automatic switching behavior.
Currently available adaption rules are:
none
- Manual switchingdeviationOfMean
- Buffer based bitrate adaption ruledeviationOfMean2
- Enhanced buffer based bitrate adaption rule (added in v4.5)
You can find more information on the setAdaption API in our API documentation.
Example to set automatic adaption
// Player instance of NanoPlayer
var adaption = {
"rule": "deviationOfMean2"
}
player.setAdaption(adaption);
Combined ABR and manual switching
In case the nanoStream H5Live Player is configured to use ABR and a manual switch gets initialized via the switchStream API the automatic adaption is stopped. From this moment on the switching behavior is manually controlled.
To again reinitialize the automatic adaption use the setAdaption API with the name of the rule you want to set (eg. deviationOfMean2
).