Our software requires a license key. How to specify your license key for Nginx is explained on this page. For more info, see License Key.



The Rocky Linux build environment is setup as follows:


yum groupinstall "Development Tools"

yum install \
  zlib-devel \
  glib2-devel \

Next to the build environment, libfmp4 and the headers for libfmp4 need to be installed as well (for how to use the package manager to install a certain version, please see the generic installation documentation, How to Install):


yum install mp4split
yum install mp4split-devel

Then download Nginx and the Nginx webserver module and unpack the module tarball:



cd ~
curl$nginx_version.tar.gz -O
curl$usp_version.tar.gz -O

tar -zxvf nginx_mod_smooth_streaming-$usp_version.tar.gz

Edit the Makefile in the Nginx webserver module directory and set the NGINX_VERSION line to the Nginx version you downloaded (you can also pass this on the command line to as, e.g. make NGINX_VERSION=THEVERSION).

Then use make to build and install:



cd ~/nginx_mod_smooth_streaming-$usp_version
sudo make install


The Ubuntu build environment is setup as follows:


sudo apt-get install build-essential \
  g++ \
  make \
  autoconf \
  automake \

The Nginx webserver is built as on Rocky Linux, with the difference that the 'devel' package does not need to be installed: on Debian/Ubuntu headers are installed by default.

Unpack the tarball and run make/make install as the Rocky Linux section outlines.


As we are using the dynamic module we need to tell Nginx to load it before it can be used. Add the following to the nginx configuration file /usr/local/nginx/conf/nginx.conf in the 'main' context:

load_module "modules/";

The next step is to have file requests ending in '.ism' (VOD) handled by the usp_handle_ism command. Add the following lines in your server { ... } section:

location ~ \.[is]sm?/.*$ {

The above location will match on any directory including a .ism file. It is also possible to map ingest to only a certain location on the filesystem:

server {
  listen 80;

  location ~ /channels/.*\.[is]sm?/.*$ {
    root /var/www;

The filesystem layout is the following (so '/var/www' is the root of the server):


If you also want to make progressive downloads available then you have to serve files ending in '.mp4' with the webserver module:

location ~ \.(mp4)$ {

Nginx License Key

For Nginx, the usp_license_key server directive must be used which is placed in the http section of nginx.conf (before any server block):

http {
  usp_license_key /path/to/usp-license.key;

  # rest of config


Prevent the download of media files

In order to prevent the download of (source) mediafiles, add the following to your webserver config:

location ~ \.(ismv|isma|ismt)$ {
  deny all;

When the source content is MP4 then the rule can be adapted to mp4 as well. The same applies to CMAF as source (cmfv, cmfa and cmft).

Prevent the download of server manifests

In order to protect your server manifests (VOD and Live) you have to disable access to ism and isml files. This can be done with the so-called LocationMatch directive similar to preventing access to media:

# never serve files with the extension .ism or .isml (case insensitive)
location ~ \.isml?/?$ {
  deny all;


The options apply to the Server Block directive.

Options related to content generation:

Option Description
usp_license_key Context: http.
usp_handle_ism Context: Location (see above).
usp_iss_pass_through Context: location. Pass through MP4 fragments directly to Smooth Streaming (see IIS passthrough).
usp_prefer_static Context: location. Pass through MP4 fragments directly to Smooth Streaming (see IIS passthrough).
usp_skip_rewrite Context: location. Skip the internal rewrite rules (see below).
usp_handle_f4f Add to enable mod_f4fhttp functionality (See Ingest F4M (deprecated)).
usp_disable_mmap Add to disable use of memory mapped I/O.
usp_dynamic_time_shift_buffer_depth Set to 'on' to update the @timeShiftBufferDepth attribute dynamically (see below).

Option related to content location:

Option Description
ism_proxy_pass Context: location. Pass .ism to proxy (a virtual path and URL), see Dynamic Manifests

Options related to secure AWS S3 access:

Option Description
s3_secret_key The AWS secret key, see Using Webserver Directives for S3 authentication.
s3_access_key The AWS access key, see Using Webserver Directives for S3 authentication.
s3_region The AWS region of the bucket, see Using Webserver Directives for S3 authentication.

The directive 'usp_skip_rewrite controls whether the internal rewrite rules are skipped. By default this is off. This is an advanced setting and generally not recommended to turn on.

location ^~ /example/ {

Status code mapping can be done with Lua in Nginx:

header_filter_by_lua "
  if ngx.status == FMP4_FRAGMENT_MISSING then
    ngx.status = 204

The usp_dynamic_time_shift_buffer_depth option changes how the @timeShiftBufferDepth attribute is set in the MPEG-DASH manifest: the @timeShiftBufferDepth attribute is updated dynamically according to the available time window and capped at the dvr_window_length.


The 'usp_dynamic_time_shift_buffer_depth' option is deprecated.



For Nginx the directive looks like the following:

location ^~ /example/ {
  root /var/www/usp_test;

Both usp_iss_pass_through and usp_prefer_static are used in the location context. Multiple locations can be used a single virtual host, so this option can be -used on a per location basis.

Dynamic manifests

For Nginx the ism_proxy_pass configuration key is specified in a location:

location ^~ /video/proxy/ {
  ism_proxy_pass http://other-server/;


Please note that when using Nginx, the 'other-server' may not be Nginx as well: Nginx will 'hang' waiting for the request to itself to finish - which never will happen. See What is the preferred webserver for media delivery? for further background.

Live API

Configuration when using Nginx:

location ~ \.isml {
  root /path/to/www/live;

By adding or usp_handle_api you can toggle the API on or off.

Live State and Statistics

API configuration for Nginx:

location ~ \.isml?\/(state|statistics|archive) {
  if ($remote_addr !~ "^(|$") {
    return 403;

AWS S3 Access

Content in S3 cn be accessed securely by signing the request as outlined in Using S3 with Authentication. For Nginx this looks like the following:

location ^~ /your-location-name/ {
  s3_secret_key YOUR_SECRET_KEY;
  s3_access_key YOUR_ACCESS_KEY;
  s3_region your-region;

Alternatively, signing S3 requests can be separated from the origin by using a separate Nginx instance as a proxy which in turn sign downstream requests to S3 using nginx-aws-auth.