HTTP Webserver Details

Custom HTTP Status codes (Apache)

For live presentations a request for a media fragment may result in one of the following errors (depending on the time of the media and the current state of the available DVR window):

Error Description
Fragment Not Found The requested fragment is older than the first fragment available in the DVR window.
Fragment Missing The requested fragment is missing from the DVR window.
Fragment Not Available The requested fragment is newer than the last fragment available in the DVR window.

You can customize the following status codes returned by the webserver module for live presentations. Note that this is customized per playout format.

Configuration key HTTP status code
Fmp4IssFragmentNotFound 404
Fmp4IssFragmentMissing 412
Fmp4IssFragmentNotAvailable 412
Fmp4HdsFragmentNotFound 404
Fmp4HdsFragmentMissing 503
Fmp4HdsFragmentNotAvailable 503
Fmp4HlsFragmentNotFound 404
Fmp4HlsFragmentMissing 404
Fmp4HlsFragmentNotAvailable 404
Fmp4MpdFragmentNotFound 410
Fmp4MpdFragmentMissing 404
Fmp4MpdFragmentNotAvailable 404

The customization in Apache is specified on a per-directory (including sub directories) basis using the Directory tag. An example Apache configuration (using the defaults):

<Directory "/var/www/live/usp_test/video/errors_rewrite">
  Fmp4IssFragmentNotFound 404
  Fmp4IssFragmentMissing 412
  Fmp4IssFragmentNotAvailable 412

HTTP Response Headers

Changed in version 1.10.4.

USP distinguishes two cases: VOD and live. Unified Origin only sets any response headers when they are applicable and there is no (feasible) way to set them with regular means (like mod_headers). For instance, only the live origin knows when a fragment is going to expire based on real-time information and DVR window settings. But for VOD contents, where no intrinsic expiration constraints exist, we do not insert default values allowing Cache-Control and/or Expires headers to be customized in webserver configuration or left unspecified (depending on CDN or player requirements).

Last Modified Time

For VOD the Last-Modified header is always set to the last modified time of the server manifest file (.ism). Note that this applies to the manifest/playlist files as well as any fragments/segments.

For live the Last-Modified time is set to:

  • the modification time of the server manifest (.isml) for client manifest, master playlist and initialization segments
  • the time of ingest of the fragment with the highest timestamp for media playlists
  • the time of ingest of the fragment (for fragments)


Changed in version 1.10.4.

Both VOD and live have an ETag value that is a hash of URL's response content. Depending on the request, the hashed data comprises the manifests or generated MP4 data, but excludes the (static) elementary stream (media data). The ETag changes only when the payload changes (for example as a result real-time changes, dynamic filtering or playout control) and If-None-Match yields 304 only if nothing changed.

Expires and Cache-Control: max-age="..."

Changed in version 1.10.4.

Changed in version 1.10.16.

For VOD no Cache-Control or Expires headers are set.

For live the Cache-Control and Expires are set to:

  • dynamic manifests like HLS media playlists expire when a new segment is expected to be ingested (the sum of the last fragment's ingest time and its duration)
  • fragments are set to expire when they leave the DVR window, with a minimum of 1 second from request time
  • fragments near the live edge expire when new revisions become available as a result of timing information in successive 'lookahead_fragments'
  • for static manifests like HLS master playlist and contents outside the DVR window no Cache-Control or Expires headers are set

Note that requests beyond the DVR window (but still within the archive) would technically have negative max-age, since they have already expired, but in this case, Cache-Control or Expires headers are set 1 second ahead of request time. Although this obfuscates the origin's intentional header logic and complicates customizing (default) expiration values, it mitigates unintentional flushing and no longer requires in depth understanding of the HTTP headers and how to set up modules in Apache / Nginx configuration.

More info on Cache-Control headers: RFC 7234.


New in version 1.10.17.

The Sunset header applies to Live streaming scenarios only. It is added to media segments and it signals when a media segment will no longer be available.

A publishing point with constrained archive length (see: --archive_length) will periodically purge old archive segments to free up disk storage. The advertised sunset time for a requested media segment reflects the anticipated time at which the archive segment containing the media will be removed (assuming the encoder continues to push contents).

When a stream is closed (because a End of Stream was sent to each track), no Sunset header is written anymore (because media segments will no longer be removed from live archive).

More info on Sunset header: RFC 8594.

Starting and stopping Apache

There are a couple of ways to stop, start or restart Apache, which are described here.

Please note that a restart (signal: HUP) will stop all connections, incoming and outgoing.

A 'graceful restart' (signal: USR1) will not, so outgoing streams continue. However, a Live ingest (the encoder POSTing to the publishing point) will stop, even with a graceful restart. There is no way to reset Apache and keep the ingest intact.


Please note that logrotate will reset all connections, as it does a restart of Apache. This might cause a problem with a Live ingest.

There are two ways to address this:

  • turn off log rotation for the ingest (the encoder POST will only log when it ends, so the logging is minimal anyway)
  • use rotatelogs.