Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 12 Next »

Overview

HTTP Live Streaming (HLS) is a technology to play streaming video via the HTTP protocol developed by Apple. An HLS video stream is encoded to H.264 and AAC and is played on any compatible device, browser or player.

Web Call Server converts to HLS video received from other supported sources of broadcasting such as web cameras and professional video capturing device, SIP calls and so on.

Supported platforms and browsers


Chrome

Firefox

Safari 11

Edge

Windows

+

+


+

Mac OS

+

+

+


Android

+

+



iOS

+

+

+


Supported codecs

  • Video: H.264
  • Audio: AAC

Operation flowchart

 


  1. The browser connects to the server via the Websocket protocol and sends the publish command.
  2. The browser captures the microphone and the camera and sends the WebRTC stream to the server.
  3. The second browser establishes a connection via HTTP.
  4. The second browser receives the HLS stream and plays this stream on the page.

Quick manual on testing

Publishing of a video stream on the server and playing it via HLS in a browser

1. For the test we use:

2. Open the Two Way Streaming web application. Click Connect, then Publish. Copy the identifier of the stream:

3. open the HLS Player Minimal web application. In the Stream field paste the identifier of the stream and click Play. The stream starts playing:

Call flow

Below is the call flow when using the HLS Player Minimal example to play a stream via HLS

hls-player.html

hls-player.js

1. Querying the server and playing.

code

   var player = videojs('remoteVideo');

Configuring the HLS URL.

code

        player.src({
            src: $("#urlServer").val() + "/" + streamName + "/" + streamName + ".m3u8",
            type: "application/vnd.apple.mpegurl"
        });

Starting the playback.

code

        player.play();

2. Receiving the HLS stream from the server

HLS playback authentication using REST hook

A client authentication for HLS playback can be setup if necessary. To do this, the following parameter should be set in flashphoner.properties file

hls_auth_enabled=true

At client side, the parameter must be added to HLS URL to pass to WCS server a token obtained for example from backend server. The name of the parameter is defined with the following setting

client_acl_property_name=aclAuth

In this case, stream URL should be formed as follows

        var src = $("#urlServer").val() + "/" + streamName + "/" + streamName + ".m3u8";
        var token = $("#token").val();
        if (token.length > 0) {
            src += "?aclAuth=" +token;
        }

REST hook /playHLS must be implemented on backend server. WCS server will send query to backend with token received from client

URL:http://localhost:8081/apps/EchoApp/playHLS
OBJECT:
{
  "nodeId" : "NTk1tLorQ00llGbPJuFexrKceubGCR0k@192.168.1.5",
  "appKey" : "defaultApp",
  "sessionId" : "/192.168.1.100:59473/192.168.1.5:8445",
  "mediaSessionId" : "60709c5b-6950-40c3-8a3d-37ea0827ae32-727473703a2f2f73747238312e63726561636173742e636f6d2f6772616e646c696c6c6574762f6c6f77-HLS",
  "name" : "test",
  "mediaProvider" : "HLS",
  "custom" : {
    "token" : "12345789"
  }
}

Backend server should return 200 OK if token is checked successfully, and 403 Forbidden if token is wrong. In its turn, client will receive either HLS stream or 401 Unauthorized.

The parameter

hls_auth_token_cache=10

defines token caching interval in seconds (10 seconds by default). /playHLS queries with certain token will not be sent to backend until the token is in cache i.e. either there is stream subscriber with tis token or caching interval is not expired. If caching interval parameter is set to 0

hls_auth_token_cache=0

/playHLS queries are sent to backend on every HTTP GET request from client.

HLS authentication setting can be changed without server restart. In this case hls_auth_enabled affects existing subscribers and hls_auth_token_cache affects new subscribers only.

Adding cross-domain access control HTTP headers for HLS playback

By default, the followin access control headers are added to 200 OK response to HTTP GET request:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000

If necessary, for example, if HLS content and HLS player page are in different domains, custom access control headers can be added using the following parameter  in flashphoner.properties file:

hls_access_control_headers=Access-Control-Allow-Origin: *;Access-Control-Allow-Methods: GET, HEAD;Access-Control-Max-Age: 3000;Access-Control-Expose-Headers: Accept-Ranges, Content-Range, Content-Encoding, Content-Length

In this case, the headers listed in the parameter will be added to 200 OK response:

Using nginx as reverse proxy for HLS playback

In some cases nginx web server can be used as reverse proxy for HLS playback from WCS server. Usually, it may require if HTTP headers adding does not help to workaround cross domain request restrictions in some browsers.

For example, if browser requires HLS player page and HLS stream to be in the same domain your.domain and on the same port 443 (HTTPS), nginx should be set up as follows:

    # HTTP requests are redirected from port  80 to 443
    server {
        listen 80;
        server_name docs.flashphoner.com;
	    return 301 https://$server_name$request_uri;
    }

    # Server listens HTTPS port 443
    server {	
		listen 443 ssl;
		ssl_certificate /etc/letsencrypt/live/your.domain/fullchain.pem;
		ssl_certificate_key /etc/letsencrypt/live/your.domain/privkey.pem;
		server_name your.domain;
		server_tokens off;
		client_max_body_size 500m;
		proxy_read_timeout 10m;
		
        root         /usr/share/nginx/html;


        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        # Example web applications will be available by URL https://your.domain/client2
        location /client2/ {
            alias /usr/local/FlashphonerWebCallServer/client2/;
        }

        # HLS playlists and segments are proxying to your.domain on port 443. for example https://your.domain/test.m3u8
		location ~* ^.+.(m3u8|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";
		}

    }

It also may be useful to cache HLS stream. In this case nginx should be additionally set up as follow:

1. In http section of /etc/nginx.conf settings file proxy cache parameters are set

    proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:1024m max_size=2048m inactive=10d;
    proxy_cache_min_uses 1;
    proxy_ignore_headers X-Accel-Expires;
    proxy_ignore_headers Expires;
    proxy_ignore_headers Cache-Control;

2. In server section of site settings file caching of HLS segments is set, playlist should not be cached:

		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

hls_static_enabled=true

The p;ayer page should be in directory defined by the following parameter

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

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:

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

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

The minimal preloader segment duration is 2 seconds by default, and can be set in milliseconds with the following parameter

hls_preloader_time_min=2000

Disabling HLS preloader

HLS preloader can be disabled if necessary, this feature is available since build 5.2.396. To disable HLS preloader, the following parameter is used

hls_preloader_enabled=false

Custom preloader configuration

To replace the default preloader to thecustom one, do the following:

1. Choose video clip (logo for example) in three aspect ratios: 16:9, 4:3, 2:1

2. Encode video to H264, add audio track to the clip, set GOP and remove B-frames using ffmpeg

ffmpeg -i clip16x9.mp4 -f lavfi -i anullsrc=channel_layout=mono:sample_rate=44100 -c:v h264 -g 30 -bf 0 -shortest 16x9/preloader16x9.mp4
ffmpeg -i clip4x3.mp4 -f lavfi -i anullsrc=channel_layout=mono:sample_rate=44100 -c:v h264 -g 30 -bf 0 -shortest 4x3/preloader4x3.mp4
ffmpeg -i clip2x1.mp4 -f lavfi -i anullsrc=channel_layout=mono:sample_rate=44100 -c:v h264 -g 30 -bf 0 -shortest 2x1/preloader2x1.mp4

3. Download and install HLS tools from Apple site

4. Prepare custom preloader HLS segments with desired duration, for example 2 seconds

cd 16x9
mediafilesegmenter -t 2 -B index -start-segments-with-iframe preloader16x9.mp4
tar -cvzf preloader.tar.gz index*.ts

This step should be repeated for all aspect ratios.

5. Make a folder for custom preloader

mkdir /opt/custom_preloader
mkdir /opt/custom_preloader/16x9
mkdir /opt/custom_preloader/4x3
mkdir /opt/custom_preloader/2x1

6. Unpack preloader segments from archive prepared on step 4

cd /opt/custom_preloader/16x9
tar -xvzf ~/preloader16x9.tar.gz

This step should also be repeated for all aspect ratios.

7. Set custom preloader folder and duration in server settings

hls_preloader_time_min=2000
hls_preloader_dir=/opt/custom_preloader

HLS subscription management using REST API

REST query should be HTTP/HTTPS POST request as follows:

  • HTTP: http://test.flashphoner.com:8081/rest-api/hls/startup
  • HTTPS: https://test.flashphoner.com:8444/rest-api/hls/startup

Where:

  • test.flashphoner.com - WCS server address
  • 8081 - WCS server standard REST / HTTP port
  • 8444 - standard HTTPS port
  • rest-api - mandatory URL part
  • /hls/startup - REST method used

REST queries and response sates

REST query

Body example

Response example

Response state

Desctiption

/hls/startup

{
  "name":"test"
}

200 - OK

404 - Stream not found

500 - Internal error


Start HLS agent for the stream


/hls/find_all


[
  "test"
]

200 – OK

404 – Not found

Find all streams having HLS agents

/hls/terminate

{
  "name":"test"
}

200 – OK

404 – Not found

Stop or restart HLS agent for the stream

Parameters

Parameter name

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

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

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.

Debug logs for HLS session

For an error report, debug logging can be enabled for HLS sessions using CLI

update node-setting --value true hls_enable_session_debug

Note that config flashphoner.properties will be overwritten after the command.

Known issues

1. Non-recoverable freeze of HLS stream played in iOS Safari through a CDN

Symptoms: one minute after publishing start image stops, sound continues to play

Solution:

b) enable transcoding on server using the following option in flashphoner.properties file

disable_streaming_proxy=true

b) if transcoding is undesirable, set the following option in flashphoner.properties file

hls_discontinuity_enabled=true

In this case, clicks are possible in audio, but video will not stop.

2. HLS segments writing stops when playing stream published in Firefox browser.

Symptoms: a few minutes after playback start HLS segments stop writing, in that case the stream directory in hls directory is not deleted, and messages in server log continue to appear

INFO HLSStreamManager - HLSStreamProviderKeepaliveThread-80 Remove hls channel

Publisher must publish stream again to recover.

Solution: use another browser to publish the stream which supposed to be played via HLS.

3. No video for the first subscriber when playing HLS in Safari on iOS 12.4

Symptoms: no video for the first subscriber when playing a stream as HLS in Safari on iOS 12.4, however video is played normally if there are other HLS-subscribers to the stream

Solution: set the minimum HLS playlist segments count not less than 2

hls_min_list_size=2

4. No video for any subscriber when playing RTMP stream as HLS in Safari on iOS 12.4 if the following parameter is set to

hls_auto_start=true

Symptoms: no video for any subscriber when playing RTMP stream as HLS in Safari on iOS 12.4

Soluition: use mono sound when a file with stereo sound track is published, for example, set the followint command line options for ffmpeg

-acodec aac -ac 1
  • No labels