Server-less Just-in-Time Packaging with AWS Fargate and Unified Origin by Unified Streaming
In this blog article Jonas Rydholm Birmé describes how he created a server-less just-in-time packaging origin, using AWS ECS Fargate tasks running Unified Origin as just-in-time packager and with content stored on an AWS S3 bucket.
The process to enable video files for web streaming is called packaging, and it can either be done in advance and the package is uploaded to web servers (pre-packaging) or the packaging process is performed on the web server (just-in-time). One of the benefits with just-in-time packaging is that you can support multiple packaging formats and future formats without having to repackage your entire library when, or if, a new format is mandated. In comparison with pre-packaging it requires more compute-power at the web server (origin). This imposes a challenge when it comes to scaling the origin for peak load and risk to add unnecessary costs during hours with low load.
In this blog article I will describe how I created an elastic and auto-scaling just-in-time packaging origin, using AWS ECS Fargate tasks running Unified Streaming Platform (USP) as just-in-time packager with content stored on an AWS S3 bucket. I will first focus on the basic setup and then discuss some optimizations that can be done to reduce latency etc.
Amazon ECS and AWS Fargate
Amazon Elastic Container Service (Amazon ECS) is a container management service that manages Docker containers on a cluster. The cluster can be hosted on a server-less infrastructure managed by Amazon or if you need to be more in control you can host your own cluster of Amazon Elastic Computing Cloud (Amazon EC2) instances. To launch the Docker container on the Amazon managed infrastructure you choose the Launch type called Fargate. When a task is running using the Fargate launch type you specify CPU and memory requirements of your Docker container.
Unified Origin for VOD
One part of the Unified Streaming Platform is the Unified Origin software which is a software plugin for Apache, Nginx, Microsoft IIS and Lighttpd that can package on-the-fly to all major streaming formats. Unified Origin for VOD can on-the-fly package from Apple HLS, MP4 and fMP4 to Apple HLS, Microsoft Smooth Streaming, Adobe HDS and MPEG-DASH. A server-manifest on the Origin server is used to generate the client-manifest file in respective streaming format.
In this example we will use fragmented MP4s stored on an S3 bucket as the source to package on-the-fly.
Building the Docker Container Images
First, let us build the Docker container images that we will need. We need one container for the actual Unified Origin, one container for the content preparation and a container for the transcoding an example content.
The Unified Origin container we build based on this Dockerfile.
An image that is basically just based on the Docker container image provided by Unified Streaming.
Then we need a container to run a command line tool called mp4split, provided by Unified Streaming, that is used for example to create the server-manifest file. We also base this container image on the one provided by Unified Streaming but with a slightly modified entrypoint script.
And the mp4split-entrypoint.sh contains the following.
The last container is optional but we use it here to transcode an example content. It is a container based on the toolbelt that we provide containing the source code and a compiled version of ffmpeg.
Preparing Example Content
As an example content we have a commercial that we can use but we need to transcode it to different sizes and resolutions. We use our transcode container image for this.
We now have three files vinn-2500.mp4, vinn-1400.mp4 and vinn-800.mp4. We then use the mp4split command to create fragmented MP4s and a server manifest.
Next step is to create the server manifest that the Unified Origin uses to package on-the-fly.
The final step in preparing the example content is to upload the server manifest and the fragmented MP4s (ismv) to the S3 bucket.
Now when we have prepared the Docker container images and some example content let us move on to the main part which is to run the Unified Origin on Amazon ECS. First we will create the network infrastructure that we will need (VPC), then upload the container image to the ECS Container Registry, create an ECS cluster, setup an application load balancer, create an ECS task definition and setup an ECS service.
As we don’t want the clients to directly access the Unified Origin tasks we can place these in a private subnet. The private subnet needs to have access to Internet to be able to access the S3 bucket and the ECS Docker container registry. In addition we then create a public subnet where we place a NAT gateway as default route (0.0.0.0/0) for the private subnets. As the purpose with this setup is to be able to scale up and down the number of Unified Origin tasks we need a load balancer to distribute the requests to the tasks. We create an Application Load Balancer (ALB) and place it in the public subnets. We don’t need any listeners or targets for the ALB as that will ECS take care of later so the first thing is to remove these.
We create a Docker container repository that we for example call usp-origin and obtain the Docker login command by running:
If everything succeeds you will find your image in your Docker Repository.
We create an ECS cluster based on the Networking Only template (powered by Fargate) that we call usp-origin-cluster and we choose not to create a VPC as we have already done that.
Once we have created the cluster we will define the Task.
A task definition contains the specification for the Docker containers to run and this is where you configure the size (CPU and memory) of a task. Using Fargate and the server-less approach it is basically only the Docker container definition and the task size that you need to specify. Placement strategies and networking is taken care of by Fargate.
We specify a Docker host to container port mapping 80 to 80 and specify the following environment variables:
- REMOTE_STORAGE_URL= https://s3.eu-west-1.amazonaws.com/usp-store/
The rest of the settings is left with defaults.
The final step is to create the Service. We choose the Fargate launch type, the task definition created above, the VPC and private subnets we created and disable Auto-assign of a public IP. We use the Application Load Balancer that we created.
Once the Service is active it will run as many task as we specify (desired count) and then we can configure the auto scaling policies we want to use.
You can try it out in our HLS/MPEG-DASH/MSS HTML player at http://player.eyevinn.technology and the different formats:
- HLS: https://usp-ecs.lab.eyevinn.technology/content/vinn.ism/master.m3u8
- MPEG-DASH: https://usp-ecs.lab.eyevinn.technology/content/vinn.ism/master.mpd
One of the purposes with having the just-in-time packaging platform scalable and elastic is that the amount of load the CDN puts on the platform is higher during peak hours with many viewers. And lower during off hours.
ECS supports two type of scaling policies :
- Target Tracking Scaling Policies — Increase or decrease the number of tasks based on target value for a specific metric.
- Step Scaling Policies — Increase or decrease the number of tasks based on a set of scaling adjustments that can vary based on the size of the alarm breach.
Now when we have this all setup we can start to tweak and adjust the auto scaling policy to what suits your business and viewer patterns.
In this setup we don’t have any storage on the ECS task to have a fully stateless Unified Origin task and everything is stored on S3 which is a remote HTTP storage. This configuration results in an overhead between the Unified Origin and the remote HTTP storage . To mitigate this we can use a local cache on the Unified Origin that caches requests to, in this case, S3.
The Remote Storage Cache could be running as a separate Docker container within the same task. This ensures that the Origin and cache will be running on the same machine. I will leave this as an exercise for the reader to configure.
It is also common to have a cache layer between the CDN and the Unified Origin acting as a shield for the origin.
Thank you for reading and I would also give a big thanks to Unified Streaming for help and support during this setup. If you want to know more about Unified Streaming and their products you can contact them on email@example.com. You can also find me on Twitter (@JonasBirme) if you have any questions or comments and want to know more.