...
Code Block |
---|
|
location ~* ^.+.(ts)$ {
proxy_pass https://localhost:8445;
proxy_http_version 1.1;
proxy_set_header Host $server_name:$server_port;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache proxy_cache;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 2m;
}
location ~* ^.+.(m3u8)$ {
proxy_pass https://localhost:8445;
proxy_http_version 1.1;
proxy_set_header Host $server_name:$server_port;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache off;
expires -1;
} |
Returning of static HTML pages on HLS port
Another way to workaround cross domain requests restrictions in browser is to return a static content, player page for example, on the same port that returns HLS content. To enable this feature, the following parameter should be set in flashphoner.properties file
Code Block |
---|
|
hls_static_enabled=true |
...
Passing a custom parameters when requesting a playlist
A custom parameters should be passed when requesting a playlist if reverse proxy authentication is set up:
Code Block |
---|
|
hls_static_dir=client2/examples/demo/streaming/hls_static |
...
https://wcs:8445/test/test.m3u8?key1=value1&key2=value2 |
The feature is supported since build 5.2.1959. The parameters passed will be returned in every playlist for every segment, this allows to authorize a viewer correctly on proxy server.
There will be an additional parameter sessionId
in playlists, for example
Code Block |
---|
|
hlsav_statictest_dir=/var/www/html/hls_static |
If static content returning is enabled, browser will display the HLS player page by URL https://host:8445/hls-player.html. If this feature is disabled, server will return 404 Not found error by such URL.
Preloader for HLS stream playback
When first HLS subscribes connects to a stream on WCS server, especilally to CDN stream, it may take a time to split a stream to HLS segmets and to form a playlist. As a result, Safari browser on iOS devices may not be able to play HLS stream on the first attempt. To successfully play HLS stream in this case, the HLS preloader was added since build 5.2.371. The default preloader looks like this:
Image Removed
Since build 5.2.408 preloaders are divided by stream aspect ratio: 16:9, 4:3, 2:1
Default preloader segments are placed to /usr/local/FlashphonerWebCallserver/hls/.preloader
folder when server is started
Code Block |
---|
|
tree /usr/local/FlashphonerWebCallServer/hls/.preloader
/usr/local/FlashphonerWebCallServer/hls/.preloader
├── 16x9
│ ├── index0.ts
│ ├── index10.ts
│ ├── index11.ts
│ ├── index12.ts
│ ├── index13.ts
│ ├── index14.ts
│ ├── index15.ts
│ ├── index16.ts
│ ├── o/av_test_o.m3u8?sessionId=11&key1=value1&key2=value2 |
This is the internal WCS parameter to identify the subscriber for statistical purposes.
Returning of static HTML pages on HLS port
Another way to workaround cross domain requests restrictions in browser is to return a static content, player page for example, on the same port that returns HLS content. To enable this feature, the following parameter should be set in flashphoner.properties file
Code Block |
---|
|
hls_static_enabled=true |
The player page should be in directory defined by the following parameter
Code Block |
---|
|
hls_static_dir=client2/examples/demo/streaming/hls_static |
In this case (by default) the path to the player page files is set relative to WCS installation directory. A full path may also be set, for example
Code Block |
---|
|
hls_static_dir=/var/www/html/hls_static |
If static content returning is enabled, browser will display the HLS player page by URL https://host:8445/hls-player.html. If this feature is disabled, server will return 404 Not found error by such URL.
Preloader for HLS stream playback
When first HLS subscribes connects to a stream on WCS server, especilally to CDN stream, it may take a time to split a stream to HLS segmets and to form a playlist. As a result, Safari browser on iOS devices may not be able to play HLS stream on the first attempt. To successfully play HLS stream in this case, the HLS preloader was added since build 5.2.371. The default preloader looks like this:
Image Added
Since build 5.2.408 preloaders are divided by stream aspect ratio: 16:9, 4:3, 2:1
Default preloader segments are placed to /usr/local/FlashphonerWebCallserver/hls/.preloader
folder when server is started
Code Block |
---|
|
tree /usr/local/FlashphonerWebCallServer/hls/.preloader
/usr/local/FlashphonerWebCallServer/hls/.preloader
├── 16x9
│ ├── index0.ts
│ ├── index10.ts
│ ├── index11.ts
│ ├── index12.ts
│ ├── index13.ts
│ ├── index14.ts
│ ├── index15.ts
│ ├── index16.ts
│ ├── index17.ts
│ ├── index18.ts
│ ├── index19.ts
│ ├── index1.ts
│ ├── index2.ts
│ ├── index3.ts
│ ├── index4.ts
│ ├── index5.ts
│ ├── index6.ts
│ ├── index7.ts
│ ├── index8.ts
│ └── index9.ts
├── 2x1
│ ├── index0.ts
│ ├── index10.ts
│ ├── index11.ts
│ ├── index12.ts
│ ├── index13.ts
│ ├── index14.ts
│ ├── index15.ts
│ ├── index16.ts
│ ├── index17.ts
│ ├── index18.ts
│ ├── index19.ts
│ ├── index1.ts
│ ├── index2.ts
│ ├── index3.ts
│ ├── index4.ts
│ ├── index5.ts
│ ├── index6.ts
│ ├── index7.ts
│ ├── index8.ts
│ └── index9.ts
└── 4x3
├── index0.ts
├── index10.ts
├── index11.ts
├── index12.ts
├── index13.ts
├── index14.ts
├── index15.ts
├── index16.ts
├── index17.ts
├── index18.ts
├── index19.ts
├── index1.ts
├── index2.ts
├── index3.ts
├── index4.ts
├── index5.ts
├── index6.ts
├── index7.ts
├── index8.ts
└── index9.ts |
...
REST query | Body example | Response example | Response state | Desctiption |
---|
/hls/startup | Code Block |
---|
| {
"name":"test"
} |
|
| 200 - OK 404 - Stream not found 500 - Internal error
| Start HLS agent for the stream
|
/hls/find_all | Code Block |
---|
| {
"offset":0,
"size":10
} |
| Code Block |
---|
| [{
"id": "test",
"streamName": "test",
"status": "ACTIVE",
"waitingSize": 0,
"profiles": [
"a_test",
"v_test"
],
"subscribers": 1,
"playlist": "...",
"createdDate": 1697605114475,
"logs": []
}] |
| 200 – OK 404 – Not found | Find all streams having HLS agents |
/hls/terminate | Code Block |
---|
| {
"name":"test"
} |
|
| 200 – OK 404 – Not found | Stop or restart HLS agent for the stream |
/hls/profiles | Code Block |
---|
| {
"hlsId":"test",
"profileName":"v_test" } |
| Code Block |
---|
| {
"name": "v_test",
"stream": {
"appKey": "defaultApp",
"sessionId": "test-HLS",
"mediaSessionId": "81b8b278-612e-4b72-9153-454be9df0a34-test-HLS",
"name": "test",
"published": false,
"hasVideo": false,
"hasAudio": true,
"status": "PLAYING",
"sdp": "...",
"videoCodec": "H264",
"record": false,
"width": 1280,
"height": 720,
"bitrate": 0,
"minBitrate": 0,
"maxBitrate": 0,
"quality": 0,
"parentMediaSessionId": "f3401d2e-7e9a-4e18-a353-d323c947ac94",
"history": false,
"gop": 0,
"fps": 0,
"audioBitrate": 0,
"codecImpl": "",
"transport": "UDP",
"cvoExtension": true,
"createDate": 1697605114875,
"mediaType": "play",
"audioState": {
"muted": false
},
"videoState": {
"muted": false
},
"mediaProvider": "HLS"
},
"keyFrameReceived": true,
"videoProfile": {
"type": "video",
"width": 1280,
"height": 720,
"fps": 29,
"bitrate": 1720,
"codec": "",
"quality": 0,
"audioGroupId": "audio"
},
"metrics": {
"minFPS": 29.962547,
"avgFPS": 30.000088,
"maxFPS": 30.04292,
"countGaps": 0,
"resolutionChanges": 0,
"queueSize": 10,
"startPts": 375400,
"currentPts": 375400
},
"subscribers": 1
} |
| 200 – OK 400 – Bad request 404 – Not found | Get HLS profile statistics |
/hls/subscribers | Code Block |
---|
| {
"hlsId":"test"
} |
| Code Block |
---|
| [
{
"id": "192.168.0.83-59000-Mozilla/5.0 (X11; Linux x86_64) Chrome/118.0.0.0",
"ip": "192.168.0.83",
"port": 59000,
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/118.0.0.0",
"active": true,
"metrics": {
"profileTime": {
"test": 71,
"v_test": 541353
},
"requestsNumber": 5930,
"requestsStatuses": {
"200 OK": 5930
},
"profileSwitches": 1,
"maxResponseTime": 29,
"minResponseTime": 0,
"avgResponseTime": 0.4436762225969646
}
}
] |
| 200 – OK 400 – Bad request 404 – Not found | Get HLS subscribers statistics |
Parameters
...
Description
...
Example
...
name
...
Stream published name
...
test
...
Issues
1. If HLS agent for the stream is started by REST query /hls/startup, and there are no active HLS subscribers, agent will stop after the following timeout in seconds
Code Block |
---|
|
hls_manager_provider_timeout=300 |
By default, the timeout is 5 minutes. Also it concerns HLS agents which are started automatically for streams published using the following parameter
Code Block |
---|
|
hls_auto_start=true |
2. If HLS agent for the stream is stopped by REST query /hls/terminate, and there are active HLS subscribers, this agent will be restarted. In this case, active HLS subscribers must reconnect to the stream.
LL HLS stream issues displaying
...
/hls/connections | Code Block |
---|
| {
"offset":0,
"size":10
} |
| Code Block |
---|
| [
{
"ip": "192.168.0.83",
"port": 51708,
"userAgent": "Chrome/125.0.0.0 Safari/537.36"
}
] |
| 200 – OK 400 – Bad request 404 – Not found 500 - Internal server error | Get a list of HLS clients connected to the server |
/hls/enableRecording | Code Block |
---|
| {
"ids": [
"test",
"test-HLS-ABR-STREAM"
]
} |
|
| 200 – OK 400 – Bad request 404 – Not found 409 - Conflict 500 - Internal server error | Enable HLS stream debug segments recording |
/hls/disableRecording | |
...
...
...
...
...
|
| 200 – OK 400 – Bad request 404 – Not found | Disable HLS stream debug segments recording |
Parameters
Parameter name | Description | Example |
---|
name | Stream published name | test |
hlsId | Stream published name | test |
profileName | Quality profile name to get a statistics | v_test |
offset | Offset from HLS streams statistics list start | 0 |
size | Maximum HLS streams statistics list size | 10 |
ids | HLS streams list to enable/disable debug segment recording | [ "test", "test-HLS-ABR-STREAM" ] |
state | HLS stream state | ACTIVE |
logs | Messages about stream issues | [] |
Issues
1. If HLS agent for the stream is started by REST query /hls/startup, and there are no active HLS subscribers, agent will stop after the following timeout in seconds
Code Block |
---|
|
hls_manager_provider_timeout=300 |
By default, the timeout is 5 minutes. Also it concerns HLS agents which are started automatically for streams published using the following parameter
Code Block |
---|
|
hls_auto_start=true |
2. If HLS agent for the stream is stopped by REST query /hls/terminate, and there are active HLS subscribers, this agent will be restarted. In this case, active HLS subscribers must reconnect to the stream.
LL HLS stream issues displaying
Since build 5.2.1709 LL HLS stream issues are displaying in response on /hls/find_all
REST API query:
Code Block |
---|
|
{
"test": {
"handler": "com.flashphoner.server.client.handler.wcs4.WCS4Handler@74dbf27b",
"state": "ACTIVE",
"writer": "HLS-test",
"streamStatus": "PLAYING",
"writerStarted": "true",
"logs": [
"2023-07-18T10:22:52.457 WARNING: Playback speed changed to 0.779, segment 49, media type: video",
..."2023-07-18T10:22:56.614 WARNING: Gap{from=112000, to=114000, duration=2000}, media type: video",
]
}
} |
...
"2023-07-18T10:22:56.615 WARNING: Fps changed from 30 to 27, segment 50 , media type: video",
"2023-07-18T10:22:56.624 WARNING: Segment 51.1 have no data, pts 112400, duration 400, media type: video",
...
]
}
} |
By default, up to 50 last issues are displayed for every stream. This value may be changed with the following parameter
...
Where 8445 is HTTPS HLS port of WCS server
HLS ABR support
For a streams with video track (video only or audio+video) WCS supports HLS ABR in CDN (a qualities are encoded on a dedicated Transcoder node) and on a single node.
Warning |
---|
HLS ABR does not work for audio only streams, WCS will return 404 Not found in response to HLS ABR manifest request for a such stream! |
Legacy HLS ABR implementation in builds 5.2.484 - 5.2.582
Since build 5.2.484 HLS ABR playlists support was added. This feature can be enabled with the following parameter
Code Block |
---|
|
hls_master_playlist_enabled=true |
Master playlist file name can be set using the following parameter
Code Block |
---|
|
hls_manifest_file=index.m3u8 |
Browser should get master playlist by URL
Code Block |
---|
|
https://wcs_address:8445/streamName/index.m3u8 |
Where
- wcs_address - WCS server address
- streamName - stream name
- index.m3u8 - master playlist file name
When master playlist is requested for the stream, server checks if streams are published according to transcoding profiles listed in cdn_profiles.yml file, for example:
Code Block |
---|
|
profiles:
-720p:
video:
height: 720
bitrate: 1000
codec: h264
-480p:
video:
height: 480
bitrate: 1000
codec: h264
-240p:
video:
height: 240
bitrate: 400
codec: h264 |
All the streams published by profiles on server, will be added to master playlist, for example:
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-720p/streamName-720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=852x480,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-480p/streamName-480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=400000,RESOLUTION=426x240,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-240p/streamName-240p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
../streamName/streamName.m3u8 |
Then browser switches between HLS streams listed in master playlist depending on channel bandwidth.
Warning |
---|
When browser requests master playlist for the certain stream, transcoded stream must already be published on server and must be cut to HLS segments |
To provide HLS streams by profiles, the following should be done:
1. On a standalone server:
1.1. Periodically check if streams are transcoded to parameters set by profiles, and launch transcoding if necessary using REST API
Code Block |
---|
|
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-240p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-240p\",\"encoder\":{\"width\":320,\"height\":240}}" http://localhost:8081/rest-api/transcoder/startup
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-480p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-480p\",\"encoder\":{\"width\":640,\"height\":480}}" http://localhost:8081/rest-api/transcoder/startup
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-720p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-720p\",\"encoder\":{\"width\":1280,\"height\":720}}" http://localhost:8081/rest-api/transcoder/startup |
1.2. Periodically launch HLS cut for the streams, for example
Code Block |
---|
|
curl -s -X POST -d "{\"name\":\"test\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-240p\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-480p\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-720p\"}" http://localhost:8081/rest-api/hls/startup |
2. On an Edge server in CDN periodically request HLS streams by transcoding profiles, for example
Code Block |
---|
|
curl -s http://localhost:8082/test/test.m3u8
sleep 1
curl -s http://localhost:8082/test-240p/test-240p.m3u8
sleep 1
curl -s http://localhost:8082/test-480p/test-480p.m3u8
sleep 1
curl -s http://localhost:8082/test-720p/test-720p.m3u8
sleep 1 |
Actual HLS ABR implementation in build 5.2.585 and newer
Since build 5.2.585 HLS ABR implementation is significally changed. As usual, HLS ABR can be used in CDN only, but Edge server captures all the transcoded streams for ABR manifest stream variants within the same mediasession to syhchronize the stream variants. This requires to configure Tanscoder nodes and Edge nodes simultaneously, and adds some limits. Let's explore it below.
Transcoder node settings
To synchronize all the variants of the same stream, encoding should be aligned on Transcoder node
Code Block |
---|
|
transcoder_align_encoders=true |
Also, FPS filter should be enabled
Code Block |
---|
|
video_filter_enable_fps=true
video_filter_fps=25 |
All stream variants key frames (GOPs) should be synchronized. For example, we will send key frame every 2 seconds for 25 fps stream
Code Block |
---|
|
video_filter_fps_gop_synchronization=50 |
HLS Edge node settings
HLS preloader and streams resizing should be disabled on HLS Edge node
Code Block |
---|
|
hls_preloader_enabled=false
hls_player_width=0
hls_player_height=0 |
The transcoding profiles should be set as follows in cdn_profiles.yml file
Code Block |
---|
|
profiles:
-240p:
audio:
codec : mpeg4-generic
rate : 48000
video:
height : 240
bitrate : 300
gop : 50
codec : h264
-480p:
video:
height : 480
bitrate : 600
gop : 50
codec : h264
-720p:
video:
height : 720
bitrate : 1000
gop : 50
codec : h264 |
Note that audio parameters can be set for the first profile only because those parameters should be identical for all the profiles, and will be applyed according to the first profile.
Then HLS ABR should be enabled
Code Block |
---|
|
hls_abr_enabled=true |
Usage
Client should request ABR manifest giving a stream name with a special suffix
Code Block |
---|
|
https://server:8445/test_0-HLS-ABR-STREAM/test_0-HLS-ABR-STREAM.m3u8 |
The suffix can be set with the following parameter
Code Block |
---|
|
hls_abr_stream_name_suffix=-HLS-ABR-STREAM |
The playlist contains links to stream variants playlists, a client can switch between then
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=614400,RESOLUTION=852x480,CODECS="avc1.42e01f,mp4a.40.2"
-480p/-480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1024000,RESOLUTION=1278x720,CODECS="avc1.42e01f,mp4a.40.2"
-720p/-720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=307200,RESOLUTION=426x240,CODECS="avc1.42e01f,mp4a.40.2"
-240p/-240p.m3u8 |
If stream name contains no suffix, HLS will be played without ABR support.
Transcoding to higher resolutions prevention
If stream transcoding to higher resolutions is disabled on HLS ABR Edge server
Code Block |
---|
|
cdn_strict_transcoding_boundaries=true |
then stream variants conforming to higher resolution profiles will not be cut for the stream, and will not be vailable to a player.
Known limits
1. HLS Edge can be used for HLS streaming only, client sessions of another kinds will not work.
2. Stream recording, snapshots, mixing, stream capturing from another server and other captured stream management functions will not work.
HLS ABR on a single node
In most cases, it's more convenient to use CDN to play HLS ABR, because this is more scalable solution at server performance point. However, since build 5.2.1582 it is possible to transcode a stream to a certain HLS ABR qualities on a single server
Code Block |
---|
|
hls_abr_enabled=true
hls_abr_with_cdn=false |
...
Displaying a list of HLS clients connected to the server
Since build 5.2.1968 it is possible to display a list of HLS clients connected to the server. The list is returned in response to the /hls/connections
query:
Code Block |
---|
|
[
{
"ip": "192.168.0.83",
"port": 51708,
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
}
] |
Where:
- ip - client address
- port - client source port
- userAgent -
User-Agent
header sent by the client
For HTTPS clients all the tabs of the same browser window on the same PC will be displayed at one position because HTTP/2 uses the same TCP connection for all HTTPS connections.
A clients count in the list will be the same as the statistics page value
Code Block |
---|
|
curl -s 'http://wcs:8081/?action=stat¶ms=connections_hls' |
HLS stream segments recording to disk for debugging purposes
Since build 5.2.1913 it is possible to record a segments and a playlists for a certain HLS stream played by subscribers for debugging purposes. Segments will be recorded to the folder set by the following parameter
Code Block |
---|
|
hls_debug_dir=hls-debug |
Segments recording for a certain stream may be started with REST API query /hls/enableRecording
Code Block |
---|
|
POST /rest-api/hls/enableRecording HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"ids": [
"test",
"test-HLS-ABR-STREAM"
]
} |
Use the REST API query /hls/disableRecording
to stop the recording
Code Block |
---|
|
POST /rest-api/hls/disableRecording HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"ids": [
"test",
"test-HLS-ABR-STREAM"
]
} |
Use a various media parsing and playing tools like ffmpeg, ffprobe etc to work with a segments recorded. Also, the debud stream recording may be played from the server using the URL with -DEBUG
suffix
Code Block |
---|
|
https://wcs:8445/test-DEBUG/test-DEBUG.m3u8 |
If the stream with a certain name was recorded, and then a new stream was published with the same name, a new recording will overwrite the previous one.
HLS ABR support
For a streams with video track (video only or audio+video) WCS supports HLS ABR in CDN (a qualities are encoded on a dedicated Transcoder node) and on a single node.
Warning |
---|
HLS ABR does not work for audio only streams, WCS will return 404 Not found in response to HLS ABR manifest request for a such stream! |
Legacy HLS ABR implementation in builds 5.2.484 - 5.2.582
Since build 5.2.484 HLS ABR playlists support was added. This feature can be enabled with the following parameter
Code Block |
---|
|
hls_master_playlist_enabled=true |
Master playlist file name can be set using the following parameter
Code Block |
---|
|
hls_manifest_file=index.m3u8 |
Browser should get master playlist by URL
Code Block |
---|
|
https://wcs_address:8445/streamName/index.m3u8 |
Where
- wcs_address - WCS server address
- streamName - stream name
- index.m3u8 - master playlist file name
When master playlist is requested for the stream, server checks if streams are published according to transcoding profiles listed in cdn_profiles.yml file, for example:
Code Block |
---|
|
profiles:
-720p:
video:
height: 720
bitrate: 1000
codec: h264
-480p:
video:
height: 480
bitrate: 1000
codec: h264
-240p:
video:
height: 240
bitrate: 400
codec: h264 |
All the streams published by profiles on server, will be added to master playlist, for example:
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-720p/streamName-720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=852x480,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-480p/streamName-480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=400000,RESOLUTION=426x240,CODECS="avc1.42e01f,mp4a.40.2"
../streamName-240p/streamName-240p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
../streamName/streamName.m3u8 |
Then browser switches between HLS streams listed in master playlist depending on channel bandwidth.
Warning |
---|
When browser requests master playlist for the certain stream, transcoded stream must already be published on server and must be cut to HLS segments |
To provide HLS streams by profiles, the following should be done:
1. On a standalone server:
1.1. Periodically check if streams are transcoded to parameters set by profiles, and launch transcoding if necessary using REST API
Code Block |
---|
|
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-240p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-240p\",\"encoder\":{\"width\":320,\"height\":240}}" http://localhost:8081/rest-api/transcoder/startup
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-480p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-480p\",\"encoder\":{\"width\":640,\"height\":480}}" http://localhost:8081/rest-api/transcoder/startup
curl -s -X POST -d "{\"uri\":\"transcoder://tcode_test-720p\",\"remoteStreamName\":\"test\",\"localStreamName\":\"test-720p\",\"encoder\":{\"width\":1280,\"height\":720}}" http://localhost:8081/rest-api/transcoder/startup |
1.2. Periodically launch HLS cut for the streams, for example
Code Block |
---|
|
curl -s -X POST -d "{\"name\":\"test\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-240p\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-480p\"}" http://localhost:8081/rest-api/hls/startup
sleep 1
curl -s -X POST -d "{\"name\":\"test-720p\"}" http://localhost:8081/rest-api/hls/startup |
2. On an Edge server in CDN periodically request HLS streams by transcoding profiles, for example
Code Block |
---|
|
curl -s http://localhost:8082/test/test.m3u8
sleep 1
curl -s http://localhost:8082/test-240p/test-240p.m3u8
sleep 1
curl -s http://localhost:8082/test-480p/test-480p.m3u8
sleep 1
curl -s http://localhost:8082/test-720p/test-720p.m3u8
sleep 1 |
Actual HLS ABR implementation in build 5.2.585 and newer
Since build 5.2.585 HLS ABR implementation is significally changed. As usual, HLS ABR can be used in CDN only, but Edge server captures all the transcoded streams for ABR manifest stream variants within the same mediasession to syhchronize the stream variants. This requires to configure Tanscoder nodes and Edge nodes simultaneously, and adds some limits. Let's explore it below.
Transcoder node settings
To synchronize all the variants of the same stream, encoding should be aligned on Transcoder node
Code Block |
---|
|
transcoder_align_encoders=true |
Also, FPS filter should be enabled
Code Block |
---|
|
video_filter_enable_fps=true
video_filter_fps=25 |
All stream variants key frames (GOPs) should be synchronized. For example, we will send key frame every 2 seconds for 25 fps stream
Code Block |
---|
|
video_filter_fps_gop_synchronization=50 |
HLS Edge node settings
HLS preloader and streams resizing should be disabled on HLS Edge node
Code Block |
---|
|
hls_preloader_enabled=false
hls_player_width=0
hls_player_height=0 |
FPS equalizing The transcoding profiles should also be enabledbe set as follows in cdn_profiles.yml file
Code Block |
---|
|
transcoder_align_encoders=true
video_filter_enable_fps=true
video_filter_fps=30
video_filter_fps_gop_synchronization=60 |
HLS ABR transcoding quality profiles should be set in /usr/local/FlashphonerWebCallServer/conf/hls_abr_profiles.yml
file
Code Block |
---|
|
profiles:
-180p:
audio:
profiles:
-240p:
audio:
codec : mpeg4-generic
rate : 48000
video:
height : 180240
bitrate : 300
gop : 50
codec : h264
-480p:
video:
codecImplheight : OPENH264480
bitrate : 600
gop : 6050
codec fps : 30
h264
-240p720p:
audiovideo:
height codec : mpeg4-generic720
bitrate rate : 480001000
video:
height : 240
bitrate : 500gop : 50
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
-480p:
audio:
codec : mpeg4-generic
rate : 48000
video:
height : 480
bitrate : 1000
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
-720p:
audio:
codec : mpeg4-generic
rate : 48000
video:
height : 720
bitrate : 1500
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30 |
...
Note that audio parameters can be set for the first profile only because those parameters should be identical for all the profiles, and will be applyed according to the first profile.
Then HLS ABR should be enabled
Code Block |
---|
|
hls_abr_enabled=true |
Usage
Client should request ABR manifest giving a stream name with a special suffix
Code Block |
---|
|
https://server:8445/test_0-HLS-ABR-STREAM/test_0-HLS-ABR-STREAM.m3u8 |
The suffix can be set with the following parameter
Code Block |
---|
|
hls_abr_stream_name_suffix=-HLS-ABR-STREAM |
The playlist contains links to stream variants playlists, a client can switch between then
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=614400,RESOLUTION=852x480,CODECS="avc1.42e01f,mp4a.40.2"
-480p/-480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1024000,RESOLUTION=1278x720,CODECS="avc1.42e01f,mp4a.40.2"
-720p/-720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=307200,RESOLUTION=426x240,CODECS="avc1.42e01f,mp4a.40.2"
-240p/-240p.m3u8 |
If stream name contains no suffix, HLS will be played without ABR support.
Transcoding to higher resolutions prevention
If stream transcoding to higher resolutions is disabled on HLS ABR Edge server
Code Block |
---|
|
hlscdn_ll_enabled=true
hls_new_http_stack=true |
Warning |
---|
When using HLS ABR on a single server, any published stream will be transcoded to a number of qualities. This requires a lot of server CPU cores and RAM. |
Transcoding to higher resolutions prevention
Since build 5.2.1611, if a stream published has a less picture height than some profiles listed in hls_abr_profiles.yml
, then all the variants with higher resolutions will not be encoded and will not be included to manfest. For example, the manifest will look as follows when original stream has 960x540 resolution:
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=300000,RESOLUTION=320x180,CODECS="avc1.42e01f,mp4a.40.2"
180/180.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=500000,RESOLUTION=428x240,CODECS="avc1.42e01f,mp4a.40.2"
240/240.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=848x480,CODECS="avc1.42e01f,mp4a.40.2"
480/480.m3u8 |
because there will not be upscale to 1280x720.
If the stream resolution is lower than a minimal profile, this stream will be transcoded to the minimal available profile, and the only variant will be included to manifest
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=300000,RESOLUTION=320x180,CODECS="avc1.42e01f,mp4a.40.2"
180/180.m3u8 |
If there is a profile without both width and height parameters, the stream will be transcoded to its original resolution with GOP and FPS defined in the profile, and this variant will always be included to manifest:
Code Block |
---|
strict_transcoding_boundaries=true |
then stream variants conforming to higher resolution profiles will not be cut for the stream, and will not be vailable to a player.
Known limits
1. HLS Edge can be used for HLS streaming only, client sessions of another kinds will not work.
2. Stream recording, snapshots, mixing, stream capturing from another server and other captured stream management functions will not work.
HLS ABR on a single node
In most cases, it's more convenient to use CDN to play HLS ABR, because this is more scalable solution at server performance point. However, since build 5.2.1582 it is possible to transcode a stream to a certain HLS ABR qualities on a single server
Code Block |
---|
|
hls_abr_enabled=true
hls_abr_with_cdn=false |
In this case, HLS preloader and default transcoding must be disabled because a stream will be transcoded by defined profiles
Code Block |
---|
|
hls_preloader_enabled=false
hls_player_width=0
hls_player_height=0 |
FPS equalizing should also be enabled
Code Block |
---|
|
transcoder_align_encoders=true
video_filter_enable_fps=true
video_filter_fps=30
video_filter_fps_gop_synchronization=60 |
HLS ABR transcoding quality profiles should be set in /usr/local/FlashphonerWebCallServer/conf/hls_abr_profiles.yml
file
Code Block |
---|
|
profiles:
original-180p:
videoaudio:
codec : h264 mpeg4-generic
rate : 48000
video:
codecImplheight : OPENH264180
gopbitrate : 60300
fpscodec : 30 |
Qualities order in HLS ABR manifest
Before build 5.2.1606, HLS ABR manifest qualities are sorted in profile names alphabetical order, for example, such cdn_profiles.yml
or hls_abr_profiles.yml
Code Block |
---|
|
profiles:
360:
video:h264
codecImpl : OPENH264
heightgop : 36060
bitratefps : 100030
codec : h264-240p:
codecImpl : OPENH264audio:
gopcodec : 60mpeg4-generic
fpsrate : 3048000
720:
video:
height : 720240
bitrate : 2000500
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
-480p:
audio:
codec : mpeg4-generic
1080: rate : 48000
video:
height : 1080
bitrate : 2500
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30 |
...
480
bitrate : 1000
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
-720p:
audio:
codec : mpeg4-generic
rate : 48000
video:
height : 720
bitrate : 1500
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30 |
Low Latency HLS is also supported for HLS ABR
Code Block |
---|
|
hls_ll_enabled=true
hls_new_http_stack=true |
Warning |
---|
When using HLS ABR on a single server, any published stream will be transcoded to a number of qualities. This requires a lot of server CPU cores and RAM. |
Transcoding to higher resolutions prevention
Since build 5.2.1611, if a stream published has a less picture height than some profiles listed in hls_abr_profiles.yml
, then all the variants with higher resolutions will not be encoded and will not be included to manfest. For example, the manifest will look as follows when original stream has 960x540 resolution:
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=300000,RESOLUTION=320x180,CODECS="avc1.42e01f,mp4a.40.2"
180/180.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=500000,RESOLUTION=428x240,CODECS="avc1.42e01f,mp4a.40.2"
240/240.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=848x480,CODECS="avc1.42e01f,mp4a.40.2"
480/480.m3u8 |
because there will not be upscale to 1280x720.
If the stream resolution is lower than a minimal profile, this stream will be transcoded to the minimal available profile, and the only variant will be included to manifest
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=300000,RESOLUTION=320x180,CODECS="avc1.42e01f,mp4a.40.2"
180/180.m3u8 |
If there is a profile without both width and height parameters, the stream will be transcoded to its original resolution with GOP and FPS defined in the profile, and this variant will always be included to manifest:
Code Block |
---|
|
profiles:
original:
video:
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30 |
Qualities order in HLS ABR manifest
Before build 5.2.1606, HLS ABR manifest qualities are sorted in profile names alphabetical order, for example, such cdn_profiles.yml
or hls_abr_profiles.yml
Code Block |
---|
|
profiles:
360:
video:
height : 360
bitrate : 1000
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
720:
video:
height : 720
bitrate : 2000
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30
1080:
video:
height : 1080
bitrate : 2500
codec : h264
codecImpl : OPENH264
gop : 60
fps : 30 |
give the following manifest
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1920x1080,CODECS="avc1.42e01f,mp4a.40.2"
1080/1080.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8 |
Since build 5.2.1606, manifest qualities order equals to profiles order in cdn_profiles.yml
or hls_abr_profiles.yml
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1920x1080,CODECS="avc1.42e01f,mp4a.40.2"
1080/1080.m3u8 |
If there are two profiles with the same name in the setup, server will use only the last profile with the same name.
Force transcoding of a maximum ABR quality only if there are B-frames in a source stream
To reduce a server load while video encoding, since WCS build 5.2.1840 it is possible to transcode a maximum ABR quality (which is usually the original stream resolution and bitrate) only if there are B-frames in a source stream. The feature may be enabled by the following parameter
Code Block |
---|
|
h264_b_frames_force_transcoding=true |
In this case the server will detect B-frames in a stream analizing a certain frames count (10 by default)
Code Block |
---|
|
frame_cnt_to_determine_their_type=10 |
If there are B-frames in the stream, the maximum ABR quality will be transcoded and will be available for playback in the HLS manifest
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1920x1080,CODECS="avc1.42e01f,mp4a.40.2"
1080/1080.m3u8 |
If there are no B-frames in the stream, the maximum ABR quality will not be transcoded
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=25000001000000,RESOLUTION=1920x1080640x360,CODECS="avc1.42e01f,mp4a.40.2"
1080360/1080360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=10000002000000,RESOLUTION=640x3601280x720,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8 |
...
The original quality should be requested separately from a playing client.
Since build 5.2.1916, the feature is available for HLS ABR in CDN. To activate it, all the CDN servers should be updated to build 5.2.1916 or newer, and the following parameters should be set on Edge server
Code Block |
---|
|
cdn_strict_transcoding_boundaries=true
h264_b_frames_force_transcoding=true |
Maximum playlist size
Maximum playlist size in segments is defined by the following parameter
Code Block |
---|
|
hls_list_size=8 |
By default, HLS playlist size is 8 segments. Note that HLS cut is just started, a segments quantity in the first playlists will be less than value set.
HLS segments storage
Using disk
In builds before 5.2.1713HLS segments are written to server hard drive to the /usr/local/FlashphonerWebCallServer/hls
folder by default. Starting from build 5.2.687, the folder for saving segments can be changed using the following parameter
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1920x1080,CODECS="avc1.42e01f,mp4a.40.2"
1080/1080.m3u8 |
If there are two profiles with the same name in the setup, server will use only the last profile with the same name.
Force transcoding of a maximum ABR quality only if there are B-frames in a source stream
...
hls_dir=/usr/local/FlashphonerWebCallServer/hls |
(Preloader folder is configured separately with parameter hls_preloader_dir.)
The number of stored segments corresponds to the specified playlist size. The less segments number, the less playback latency. However subscribers with poor channel could request HLS segments which are already gone from playlist and disk if playlist is short. To fix it, since build 5.2.581 the certain number of segments can be stored on disk after they gone from playlist. This feature can be enabled by the following parameter
Code Block |
---|
|
h264hls_bhold_framessegments_forcebefore_transcodingdelete=true |
In this case the server will detect B-frames in a stream analizing a certain frames count (10 by default)By default, 5 last segments will be stored
Code Block |
---|
|
framehls_cnthold_to_determine_their_type=10 |
...
For example, if playlist contains 3 segments
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8-VERSION:8
#EXT-X-TARGETDURATION:11
#EXT-X-STREAMMEDIA-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8SEQUENCE:15
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1920x1080,CODECS="avc1.42e01f,mp4a.40.2"
1080/1080.m3u8 |
If there are no B-frames in the stream, the maximum ABR quality will not be transcoded
Code Block |
---|
|
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42e01f,mp4a.40.2"
360/360.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720,CODECS="avc1.42e01f,mp4a.40.2"
720/720.m3u8 |
The original quality should be requested separately from a playing client.
...
DISCONTINUITY-SEQUENCE:1
#EXTINF:3.415,
test_017.ts
#EXTINF:10.417,
test_018.ts
#EXTINF:9.084,
test_019.ts |
3 current segments and 5 previous segments will be stored on disk
Code Block |
---|
|
test_012.ts
test_013.ts
test_014.ts
test_015.ts
test_016.ts
test_017.ts
test_018.ts
test_019.ts |
Using memory
Under high load, for example on HLS streaming dedicated server, segments reading from hard drive to send them to subscribers can increase the latency. In this case, HLS segments storing in memory should be enabled
Code Block |
---|
|
cdnhls_strictstore_transcoding_boundaries=true
h264_b_frames_force_transcoding=true |
Maximum playlist size
Maximum playlist size in segments is defined by the following parameter
Code Block |
---|
|
hls_list_size=8 |
By default, HLS playlist size is 8 segments. Note that HLS cut is just started, a segments quantity in the first playlists will be less than value set.
HLS segments storage
Using disk
...
Segments will be read from memory to send them to subscribers. Note this will require more Java heap memory.
Since build 5.2.1713 HLS segments are stored in memory by default.
Debug logs for HLS session
For an error report, debug logging can be enabled for HLS sessions using CLI
Code Block |
---|
|
update node-setting --value true hls_enable_session_debug |
Note that config flashphoner.properties will be overwritten after the command.
Low Latency HLS support
Since WCS build 5.2.1181, Low Latency HLS (LL HLS) is supported. The feature may be enabled with the following parameters
Code Block |
---|
|
hls_dir=/usr/local/FlashphonerWebCallServer/hls |
(Preloader folder is configured separately with parameter hls_preloader_dir.)
...
hls_ll_enabled=true
hls_new_http_stack=true |
In this case, players supporting LL HLS (HLS.JS for example) will play additional HLS segments reducing playback latency comparing with players which do not play those segments (VideoJS for example).
It is necessary to provide a stable FPS and keyframe interval for a published stream to play it as LL HLS correctly. Therefore, it is recommended to publish the source strem as RTMP with the following example parameters
Image Added
Image Added
Recommended settings for LL HLS playback
Since build 5.2.1345, the recommended settings to play Low latency HLS are follow:
Code Block |
---|
|
hls_ll_enabled=true
hls_auto_start=true
hls_hold_segments_before_delete=true |
...
_preloader_enabled=false
hls_player_width=848
hls_player_height=480
video_filter_enable_fps=true
video_filter_fps=30
video_encoder_h264_gop=60 |
Since build 5.2.1965, the following parameter is enough to play LL HLS, a defaults may be used for other settings
Code Block |
---|
|
hls_holdll_segments_sizeenabled=5 |
For example, if playlist contains 3 segments
Code Block |
---|
|
#EXTM3U
#EXT-X-VERSION:8
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:15
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXTINF:3.415,
test_017.ts
#EXTINF:10.417,
test_018.ts
#EXTINF:9.084,
test_019.ts |
...
Using HTTP/2 and HTTP/1
According to specification, LL HLS must be played using HTTP/2, i.e. via secure connection
Code Block |
---|
|
test_012.ts
test_013.ts
test_014.ts
test_015.ts
test_016.ts
test_017.ts
test_018.ts
test_019.ts |
Using memory
...
https://wsc:8445/test/test.m3u8 |
It is also possible to use HTTP/1 via unsecure connection with WCS
Code Block |
---|
|
http://wsc:8082/test/test.m3u8 |
Note that LL HLS via HTTP/1 works in main browsers except Safari, and this feature is not recommended to use in production.
LL HLS segments folder
By default, LL HLS segments are written to streams subdolder to the folder
Code Block |
---|
|
hls_store_segment_in_memory=true |
Segments will be read from memory to send them to subscribers. Note this will require more Java heap memory.
Since build 5.2.1713 HLS segments are stored in memory by default.
Debug logs for HLS session
...
ll_hls_dir=/usr/local/FlashphonerWebCallServer/ll-hls |
If folder has changed
Code Block |
---|
|
ll_hls_dir=/opt/ll-hls |
it is necessary to set file access permissions using the command
Code Block |
---|
|
update node-setting --value true hls_enable_session_debug |
Note that config flashphoner.properties will be overwritten after the command.
Low Latency HLS support
...
/usr/local/FlashphonerWebCallServer/bin/webcallserver set-permissions |
and restart WCS to apply the changes.
Maximum LL HLS playlist size
Maximum LL HLS playlist size in segments is defined by the following parameter
Code Block |
---|
|
ll_hls_list_size=12 |
By default, LL HLS playlist size is 12 full segments. Note that LL HLS cut is just started, a full segments quantity in the first playlists will be less than value set.
LL HLS preloader
Since build 5.2.1181, Low Latency HLS (LL HLS) is supported. The feature may be enabled with the following parameters1729, a special preloader can be used for LL HLS as like as usual HLS
Code Block |
---|
|
hls_llpreloader_enabled=true
hls_new_http_stack=true |
In this case, players supporting LL HLS (HLS.JS for example) will play additional HLS segments reducing playback latency comparing with players which do not play those segments (VideoJS for example).
It is necessary to provide a stable FPS and keyframe interval for a published stream to play it as LL HLS correctly. Therefore, it is recommended to publish the source strem as RTMP with the following example parameters
Image Removed
Image Removed
Recommended settings for LL HLS playback
Since build 5.2.1345, the recommended settings to play Low latency HLS are follow:LL HLS preloader files are placed by default to the folder
Code Block |
---|
|
ll_hls_preloader_dir=/usr/local/FlashphonerWebCallServer/ll-hls/.preloader |
The folder can be changed, for example
Code Block |
---|
|
hls_ll_enabled=true
hls_auto_start=true
hls_preloader_enabled=false
hls_player_width=848
hls_player_height=480
video_filter_enable_fps=true
video_filter_fps=30
video_encoder_h264_gop=60 |
Using HTTP/2 and HTTP/1
...
Default LL HLS preloader consists of the following files, one per each standard video streams aspect ratio
Code Block |
---|
|
https://wsc:8445/test/test.m3u8 |
...
If stream aspect ration is unknown, 16:9 preloader file will be used. If there are no preloader files at all, LL HLS stream cut will start without a preloader like
Code Block |
---|
|
http://wsc:8082/test/test.m3u8 |
Note that LL HLS via HTTP/1 works in main browsers except Safari, and this feature is not recommended to use in production.
LL HLS segments folder
By default, LL HLS segments are written to streams subdolder to the folder
Code Block |
---|
|
ll_hls_dir=/usr/local/FlashphonerWebCallServer/ll-hls |
If folder has changed
Code Block |
---|
|
ll_hls_dir=/opt/ll-hls |
...
hls_preloader_enabled=false |
Custom LL HLS preloader setup
A custom LL HLS preloader can be set up if necessary. The media files in three standard aspects 16:9, 4:3 и 2:1 should be prepared according to the following requirements:
- MP4 container, video codec H264, audio codec AAC
- the files should allow instant playback (MP4
moov
atom must precede mdat
one) - the files should not containt B frames
- the file duration should be near 1 minute
- the file should have a smooth FPS
- keyframe interval should be near 2 seconds
Suppose a source files are prepared in a proper aspects in OBS Studio or in a video editor. Use the following command example to convert a preloader files to conform the requirements above:
Code Block |
---|
|
/usr/local/FlashphonerWebCallServer/bin/webcallserver set-permissions |
and restart WCS to apply the changes.
Maximum LL HLS playlist size
Maximum LL HLS playlist size in segments is defined by the following parameter
Code Block |
---|
|
ll_hls_list_size=12 |
By default, LL HLS playlist size is 12 full segments. Note that LL HLS cut is just started, a full segments quantity in the first playlists will be less than value set.
LL HLS preloader
Since build 5.2.1729, a special preloader can be used for LL HLS as like as usual HLS
Code Block |
---|
|
hls_preloader_enabled=true |
LL HLS preloader files are placed by default to the folder
Code Block |
---|
|
ll_hls_preloader_dir=/usr/local/FlashphonerWebCallServer/ll-hls/.preloader |
...
ffmpeg -i 16x9-source.mp4 -bf 0 -acodec aac -vcodec h264 -preset ultrafast -g 60 -strict -2 -r 30 -ar 48000 -movflags faststart -ss 00:00:00 -t 00:01:00 16x9.mp4 |
Then the default preloader files should be replaced by custom preloader files, and WCS should be restarted.
To restore default preloader it is enough to remove custom preloader files and restart WCS.
A settings applied both for LL and non-LL HLS
Since build 5.2.1965 all the settings with hls_
prefix are applied both to LL and non-LL HLS.
The following parameters are applied to LL HLS only and not applied to non-LL HLS
Parameter | Description | Default value |
---|
ll_hls_max_number_of_parent_segments_containing_partials | A maximum partial segments number per one parent segment | 5 |
ll_hls_part_hold_back_count | PART-HOLD-BACK attribute value in playlist | 6 |
ll_hls_partial_time_max | A maximum partial segment size in milliseconds | 400 |
m4s container support
Since build 5.2.1626 m4s container is supported for HLS segments cut, and since build 5.2.1632 the container is enabled by default for HLS ABR too
Code Block |
---|
|
ll_hls_preloaderfragmented_dir=/opt/preloader |
...
Since build 5.2.1724, m4s container is supported for HLS ABR in CDN.
You can switch back to the ts container if necessary
Code Block |
---|
|
16x9.mp4
2x1.mp4
4x3.mp4 |
...
ll_hls_fragmented_mp4=false |
Using a common network stack for HLS and Low Latency HLS
Since build 5.2.1749 the parameter allowing an unified network stack usage both for HLS and Low latency HLS is added. The parameter is enabled by default:
Code Block |
---|
|
hlsuse_preloadernew_enabled=false |
Custom LL HLS preloader setup
A custom LL HLS preloader can be set up if necessary. The media files in three standard aspects 16:9, 4:3 и 2:1 should be prepared according to the following requirements:
- MP4 container, video codec H264, audio codec AAC
- the files should allow instant playback (MP4
moov
atom must precede mdat
one) - the files should not containt B frames
- the file duration should be near 1 minute
- the file should have a smooth FPS
- keyframe interval should be near 2 seconds
Suppose a source files are prepared in a proper aspects in OBS Studio or in a video editor. Use the following command example to convert a preloader files to conform the requirements above:
Code Block |
---|
|
ffmpeg -i 16x9-source.mp4 -bf 0 -acodec aac -vcodec h264 -preset ultrafast -g 60 -strict -2 -r 30 -ar 48000 -movflags faststart -ss 00:00:00 -t 00:01:00 16x9.mp4 |
Then the default preloader files should be replaced by custom preloader files, and WCS should be restarted.
To restore default preloader it is enough to remove custom preloader files and restart WCS.
m4s container support
Since build 5.2.1626 m4s container is supported for HLS segments cut, and since build 5.2.1632 the container is enabled by default for HLS ABR too
Code Block |
---|
|
ll_hls_fragmented_mp4=true |
Since build 5.2.1724, m4s container is supported for HLS ABR in CDN.
You can switch back to the ts container if necessary
Code Block |
---|
|
ll_hls_fragmented_mp4=false |
Using a common network stack for HLS and Low Latency HLS
Since build 5.2.1749 the parameter allowing an unified network stack usage both for HLS and Low latency HLS is added. The parameter is enabled by default:
Code Block |
---|
|
use_new_hls=true |
In this case:
- m4s container is used by default to record an HLS segments
- parameters with
hls
prefix are applied both to HLS and LL HLS - parameters with
ll_hls
prefox are applied to LL HLS and to m4s container
Warning |
---|
Since build 5.2.1793, the parameter is removed. The unified network stack is always used to deliver both HLS and LL HLS segments. |
Manifest URL setup
...
In this case:
- m4s container is used by default to record an HLS segments
- parameters with
hls
prefix are applied both to HLS and LL HLS - parameters with
ll_hls
prefox are applied to LL HLS and to m4s container
Warning |
---|
Since build 5.2.1793, the parameter is removed. The unified network stack is always used to deliver both HLS and LL HLS segments. |
Manifest URL setup
Since build 5.2.1852, an URL templates to request a stream main playlist (manifest) may be customized. By default, the following templates are used:
Code Block |
---|
|
hls_path_template={streamName}/{streamName}.m3u8
hls_abr_path_template={streamName}{abrSuffix}/{streamName}{abrSuffix}.m3u8 |
Where:
- streamName - stream published name
- abrSuffix - HLS ABR stream suffix set by
hls_abr_stream_name_suffix
parameter
In this case, the following URLs should be used to get HLS manifest
Code Block |
---|
|
https://wcs:8445/stream/stream.m3u8 |
and to get HLS ABR manifest
Code Block |
---|
|
https://wcs:8445/stream-HLS-ABR-STREAM/stream-HLS-ABR-STREAM.m3u8 |
For example, if a fixed manifest name different for HLS ABR and non-ABR streams is preferred to use, then the following templates should be set
Code Block |
---|
|
hls_path_template={streamName}/playlist.m3u8
hls_abr_path_template={streamName}/playlist{abrSuffix}.m3u8 |
In this case, the following URLs should be used to get HLS manifest
Code Block |
---|
|
https://wcs:8445/stream/playlist.m3u8 |
and to get HLS ABR manifest
Code Block |
---|
|
https://wcs:8445/stream/playlist-HLS-ABR-STREAM.m3u8 |
HLS provider shutdown when source stream is stopped
Since build 5.2.1920 it is possible to control HLS provider shutdown when a source stream publishing on the server is stopped. By default, the HLS provider is stopped with a delay
Code Block |
---|
|
hls_delayed_shutdown=true |
The delay depends on playlist size
Code Block |
---|
|
hls_list_size=8 |
Thus, a subscribers playing the HLS stream may play a rest of playlist if the source stream is stopped.
The delayed shutdown may be disabled if needed
Code Block |
---|
|
hls_pathdelayed_template={streamName}/{streamName}.m3u8
hls_abr_path_template={streamName}{abrSuffix}/{streamName}{abrSuffix}.m3u8 |
Where:
- streamName - stream published name
- abrSuffix - HLS ABR stream suffix set by
hls_abr_stream_name_suffix
parameter
...
In this case HLS provider will be stopped right after the source stream is stopped.
HLS segments size control
By default HLS segments will be cut either by key frame receiving or by reaching the size set by the following parameter (2000 ms by default)
Code Block |
---|
|
https://wcs:8445/stream/stream.m3u8 |
and to get HLS ABR manifest
Code Block |
---|
|
https://wcs:8445/stream-HLS-ABR-STREAM/stream-HLS-ABR-STREAM.m3u8 |
...
Since build 5.2.1974 it is possible to enable HLS segments cutting by key frame receiving only
Code Block |
---|
|
hls_path_template={streamName}/playlist.m3u8
hls_abr_path_template={streamName}/playlist{abrSuffix}.m3u8always_start_segment_with_key_frame=true |
In this case , the following URLs should be used to get HLS manifesta segment size may exceed hls_time_min
value, bur a minimal segment size may be less. The following parameter is used to strictly limit the minimal segments size
Code Block |
---|
|
https://wcs:8445/stream/playlist.m3u8 |
and to get HLS ABR manifest
Code Block |
---|
|
https://wcs:8445/stream/playlist-HLS-ABR-STREAM.m3u8hls_keep_min_segment_duration=true |
In this case a segment size will not be less than hls_time_min
.
Known issues
1. Non-recoverable freeze of HLS stream played in iOS Safari through a CDN
...
Solution: since build 5.2.1690, use m4s container for audio only streams
13. Encoder resources leak may appear under a high load when using HLS ABR
Symptoms: when HLS ABR is used and server CPU load is high (for instance, an encoding profiles number for all the streams published exceeds CPU capabilities), encoding resources may not be freed after publishing is stopped, and this may be visible on server statistics page, for example
Code Block |
---|
|
streams_hls=0
...
native_resources.video_encoders=5 |
Solution: update WCS to build 5.2.1947 and set the following parameter
Code Block |
---|
|
handler_async_disconnect=false |