Virtual Channel configuration is performed by means of environmental variables. The .env file included in Virtual Channel's root folder lists all the available configuration options, with default values and a short explanation of their meaning.

Values set in the shell environment override those set in the .env file. This is the recommended method to customize the configuration based on your needs.


If you are just getting familiar with Virtual Channel, in a trusted test environment, you can skip this section for the moment. However, you must read it before using Virtual Channel in production or exposing the service on a public endpoint or in general in an environment where it could be exposed to untrusted clients.

API Key authorization

Virtual Channel's API endpoints access can be allowed to any client or can be restricted to just those providing an API Key in an authorization header. You can enable/disable this access restriction by acting on the two shell environmental variables:



In order to enable the insecure unrestricted API mode, your shell should have:

  • API_KEY: unset or empty

  • API_INSECURE: unset or True


make sure to notice what the above means: by default, if you don't set any of those variables, Virtual Channel API will start in insecure unrestricted mode!

In order to enable API Key authorization, set the following in your shell:

  • API_KEY set to the key you have generated (i.e export API_KEY=<my_key>)

  • API_INSECURE set to False (i.e export API_INSECURE=False)

Once API Key authorization is enabled, clients will need to add to their HTTP requests the additional header

USP-API-KEY: <my_key>

E.g. with cURL, a valid request, with authentication enabled, would be

curl -H "USP-API-KEY: <my_key>" "http://localhost:8000/version"


the root "/" endpoint, only used for healthchecks, is deliberately left open even when API Key authorization is enabled

RabbitMQ credentials

Virtual Channel internally uses RabbitMQ as a message broker and credentials are needed for Virtual Channel services to use it. Should you ever need to change the default credentials, you can do so by changing the default values or overriding the RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS environmental variables.

Notice that to make a change to any of the above effective, you will have to trigger a "clean" RabbitMQ start by removing all data from the redis_data docker volume. Be aware that by doing so you will also lose all your channels and transitions that you may have created thus far.

Enabling TLS / HTTPS

The default Virtual Channel Docker Compose file runs everything over HTTP, with the assumption that it will be running behind a CDN and/or load balancer which handles TLS.

The configuration to use HTTP is provided by the default docker compose override file docker-compose.override.yaml.

However, if you wish to use HTTPS instead there is an alternative configuration which can be used.

First, add your certificate(s) to the certs directory, this will make them available to the Traefik container which is the entry point for all traffic.

Then update the docker-compose.override.https.yaml configuration file, adjusting the TLS section to load your certificates.

    - certFile: /certs/replace_this_with_your_cert_filename.crt
      keyFile: /certs/replace_this_with_your_key_filename.key

For more advanced configuration options please see the Traefik documentation.

Once you have configured your certificates you can run the alternative Docker Compose configuration by referencing this YAML file instead of the default override file docker-compose.override.yaml.

docker compose -f docker-compose.yaml -f docker-compose.override.https.yaml up -d

This configuration will change the default HTTP ports 80 and 8000 to redirect to HTTPS ports 443 and 8443 respectively.

You can check your service is up and running correctly by running curl https://localhost:8443 which should return an I'm alive message.


Virtual Channel can be used with VOD media files from a local or networked filesystem, or HTTP object storage such as S3.

Local or network filesystem

Using local or network filesystem requires media files be accessible on the same path for both the VOD2Live worker that will process playlists and the Unified Origin that will stream out the channel.

To quickly get started with local media this can be done by placing it in the existing channels directory which is already a shared volume for the two containers. Media files can then be referenced with a relative path in the SMIL.

Locally mounted network filesystems can be used by just adding an additional bind mount to the origin and virtual-channel-worker-vod2live services in the docker-compose.yaml.

For example:

- type: bind
  source: /mnt/network-share
  target: /mnt/network-share

Media files can then be referenced with an absolute path in the SMIL.

For details of other methods of mounting shared volumes to Docker containers please refer to the official Docker documentation.

HTTP object storage (S3-compatible)

HTTP object storage that does not require signed requests works without any additional configuration required.

Authentication for S3-compatible storage is managed using environmental variables to handle access key, secret key and region. If you plan to use SMIL playlists referencing object storage which requires S3 authentication, you must set the following:

export S3_ACCESS_KEY=<your s3 access key>
export S3_SECRET_KEY=<your s3 secret key>
export S3_REGION=<the s3 region of your storage bucket>
export REMOTE_STORAGE_URL=<the s3 http bucket url>


Notice that Virtual Channel, at this stage, can only ever work with one S3 bucket at a time, which is set at startup time. This means that any VOD content referenced in your playlists must belong to the same S3 bucket (i.e. it is not possible to transition across two playlists referencing content on two or more different S3 buckets).

Remix Timeout

When channels and transitions are created, background async tasks take care of running remix and mp4split. If a SMIL playlist is very long or references media on a slow storage, the remix task can take a long time. Celery, which is the "engine" running those task, will perform a sanity check and will timeout any job taking longer than REMIX_TASK_TIMEOUT seconds.

The default value for this timeout has been picked to be long enough to handle the most common use cases, however if you are using a very long playlist or referencing media on a slow storage (or both!), then you may still encounter timeouts.


If you have a very long playlist (24h or more) and you encounter remix timeouts (or very long remix execution times), it is worth remembering that any long playlist can be broken up into transitions across shorter playlists. Generally this is a preferrable approach.

Should you need to, you can make the timeout longer by overriding the REMIX_TASK_TIMEOUT environmental variable.

Automatic transition deletion

Any transition requires some storage space for remix mp4s and ismls as well as entries in the internal database. When a transition is no longer needed, it should be deleted to avoid exhausting disk space in the long term.

Virtual Channel includes an housekeeping job that runs daily and deletes all unneeded transitions taking care of keeping the last DAYS_TO_KEEP_TRANSITIONS_FOR days of archive content operational.

In other words, for each channel the job retrieves a list of all transitions previous to <now> - <DAYS_TO_KEEP_TRANSITIONS_FOR days>. It then proceeds to remove them all but the latest. Keeping the latest transition is necessary because it references content that extends into the archive window that must be kept operational.

Notice that the job only removes transitions and never removes the related base channel.

You can change the number of days Virtual Channel keep transitions for with the DAYS_TO_KEEP_TRANSITIONS_FOR environmental variable. Remember in any case to keep it equal or longer than your archive length.