Streaming Video in Unreal Engine 4 — Part 2 — Hosting on AWS EC2 and S3

Luke Brady
9 min readApr 29, 2020

--

Streaming Video in Unreal Engine 4 — Part 1: https://medium.com/@lukebrady105/streaming-video-in-unreal-engine-4-part-1-d4fa0c924aa

Now that we have a basic scene that can stream video from a remote source, it is time to set up infrastructure to host our own videos in AWS S3 and deploy a dedicated server so that clients can connect and experience the video playback together in real-time.

To follow along with this tutorial, you will need the following:

  1. An AWS Account: https://aws.amazon.com/free
  2. An IAM user with access to create S3 buckets and EC2 instance. You will also need an access key and secret key.
  3. Terraform 0.12: https://www.terraform.io/downloads.html
  4. Packer: https://www.packer.io/downloads.html
  5. Video Files (I will be using stock video files from Pexels): https://www.pexels.com/video/video-of-motor-bikers-on-the-road-1333384/ and https://www.pexels.com/video/penguin-underwater-1674470/ (I only use the first video in this tutorial, but I will use both in Part 3)
  6. I will also be building and packaging an Unreal Engine 4 dedicated server. If you are unfamiliar with building and packaging a dedicated server, please refer to this tutorial: https://medium.com/@lukebrady105/building-and-hosting-an-unreal-engine-dedicated-server-with-aws-and-docker-75317780c567
  7. All of the code for this tutorial can be found here: https://github.com/CodeAndCoffeeBlog/streaming-video-in-ue4-part-2

Now grab your favorite cup of coffee and let’s begin!

Infrastructure — Creating the S3 Bucket

The infrastructure code for this tutorial is relatively simple. We will set up an AWS S3 bucket to host our video files and create an EC2 instance to run the dedicated server. All of the infrastructure code is written in Terraform and Packer, and tfvars files are provided.

We will first create the media bucket that will be used to host our video files. The script block below will create a new S3 bucket with server side encryption and versioning enabled.

resource "aws_s3_bucket" "media_bucket" {
bucket = var.bucket_name
region = var.aws_region
tags = {
Name = var.bucket_name
CreatedBy = "CodeAndCoffee"
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

versioning {
enabled = true
}
}

Let’s run a Terraform plan and apply to create the bucket in AWS S3. We will be using a targeted Terraform plan and apply so that we only create the S3 bucket. We will create an EC2 instance later, but for now we only need the media bucket to upload our video files.

terraform plan -target aws_s3_bucket.media_bucket -var-file=var.tfvars -out plan
terraform apply plan

Here you can see the output of the Terraform apply and the S3 bucket that Terraform created.

I created my bucket in us-east-1 because it is the region closest to me. You can change the region that the bucket gets created in the var.tfvars file. You will also need to change the bucket_name variable to a new unique name due to S3’s global namespace.

Upload Video Files to S3

Now that we have our bucket created, let’s upload some video files. For this tutorial, I am going to upload two .mp4 files I downloaded from Pexels.

To upload the video files select Upload and then select the video files that will be uploaded, then click Upload.

After the video files have been uploaded, we will make them public so that our client can stream the files using the S3 bucket URL. For a production setup you would not open your video file to the world, but for the sake of simplicity we will just open the video file to the internet. To make the video files public, right click on the file and select Make public.

After confirming that the video file should be made public, click the video file. You will see that the video file has an Object URL. This is the URL that is used to access the video in the S3 bucket. Go ahead and click on the Object URL and see the video that you uploaded start to play in your browser.

The video is playing from the S3 bucket.

Streaming the Video File from S3

Now that we have a video file we can stream from S3, it is time to update the StreamMediaSource we created in Part 1 of this tutorial with the URL of the video file in the S3 bucket.

Double click on the StreamMediaSource and paste the S3 Object URL into the Stream Url field.

Click save and close the window. You can now play the game and see that the video we uploaded to S3 has started playing on the screen within the scene.

Now that we have our video streaming from AWS, it is time to package the dedicated server with our updates. For this tutorial, I will package a server for both Windows and Linux so that I can test the server on my Windows workstation and then deploy the Linux server on an EC2 instance in AWS.

Packaging the Dedicated Server

Please refer to my previous tutorial on building an Unreal Engine dedicated server if you happen to get stuck on any of the steps below. https://medium.com/@lukebrady105/building-and-hosting-an-unreal-engine-dedicated-server-with-aws-and-docker-75317780c567

To package a dedicated server for Windows, click File and change the Build Target to the server. Then click File -> Package Project -> Windows -> Windows (64-bit). Select the Binaries\Win64 directory for the server binary output.

After the Windows server is packaged, click File -> Package Project -> Linux -> Linux -> Linux to package the Linux server. I created a Binaries/Linux folder for the Linux server.

Now that we have the dedicated servers packaged, it is time to connect multiple clients to the server. Before deploying to AWS, I always test the server locally. To test, start up the Windows dedicated server by double clicking on the <Yourgame>Server.exe file. You can also start the dedicated server from your favorite shell. After starting the server, you will see that it is listening on port 7777. We will edit our client’s level blueprint to connect to 127.0.0.1:7777 when the game begins. To do this, open the entryMap’s level Blueprint by double clicking the entryMap and selecting Blueprints -> Open Level Blueprint. Connect the Event BeginPlay node to an Open Level node. Change the Level Name parameter to 127.0.0.1:7777. Now Compile and Save the changes and exit out of the Blueprint editor.

Click the drop down arrow next to the Play button and change the number of Players to 3. This will give you a feel for multiple client connecting to a dedicated server. Now click Play. You should see three client windows open up and load the level sent by the server. Each client will stream the video from S3 and play within the scene.

Multiple clients are connected to the game server and can enjoy the video stream together in real-time.

Infrastructure — Deploying the Linux Dedicated Server

Now we have our Linux dedicated server packaged, it is time to deploy to AWS EC2 so that game clients around the world can connect and experience the video stream together in real-time. For this section I will re-use the Packer and Terraform code I wrote for the Unreal Engine 4 dedicated server tutorial https://medium.com/@lukebrady105/building-and-hosting-an-unreal-engine-dedicated-server-with-aws-and-docker-75317780c567. This code takes the packaged dedicated server and creates an AMI that we can use to create an EC2 instance running the dedicated server in a Docker container. Before we created the AMI, we need to tar the Linux dedicated server. You can create a server directory in the code repository and run the following command to tar the dedicated server. I am using the MinGW bash shell that comes packaged with Git for Windows. Here is the link if you are interested: https://git-scm.com/download/win.

cd %ProjectPath%/Binaries
tar -czvf unreal-dedicated.tar.gz Linux/
mv unreal-dedicated %RepositoryPath%/server/

Now that the dedicated server is packaged, we can build our dedicated server AMI with Packer. To build the AMI, run the following command.

packer build -var-file packer/variables.json packer/docker_instance.json

The Packer code will install Docker, upload the dedicated server archive, create a Docker container for the dedicated server, and then remove all of the files that were uploaded for AMI creation. Creating this AMI will make spinning up an EC2 instance with the Linux dedicated server extremely easy. Now it is time to build the dedicated server instance with the AMI we just created.

resource "aws_instance" "ue4_dedicated" {
instance_type = "t2.small"
ami = data.aws_ami.ue4_dedicated_ami.id
vpc_security_group_ids = [
aws_security_group.udp_7777.id
]
tags = {
Name = "ue4-dedicated-server"
}
user_data = file("scripts/userdata.sh")
}

We will use Terraform to create a new EC2 instance running our dedicated server. The Terraform code also creates a security group that allows 7777/UDP so that clients can connect to the server.

terraform plan -var-file=var.tfvars -out plan
terraform apply plan

After the Terraform apply has completed, you will see the EC2 instance’s public IP as output.

Now that we have a dedicated server running on AWS EC2, we will be able to connect the game client and stream the video from S3.

Connecting Clients to Experience the Video Stream in Real-Time

To connect our game client to the instance running in AWS, we will need to edit the entryLevel Blueprint like we did earlier in this tutorial. We will change the Open Level node to connect to the public IP of our EC2 instance. To change this value, click the Blueprints drop down and select Open Level Blueprint.

Next, update the Open Level node from 127.0.0.1:7777 to the public IP of your EC2 instance. In my case it will be 18.232.67.174:7777. Now compile and exit the window.

Now for the moment of truth, connecting our client to the EC2 instance and streaming the video file from S3. To do this, we will quickly package the game client the same way we packaged the dedicated server. Click File -> Package Project -> Build Target and choose the game target. Now click File -> Package Project -> Windows -> Windows (64-Bit).

After the game client has been packaged, go to your project’s directory and launch the game client by double clicking Binaries/Win64/WindowsNoEditor/YourGame.exe.

The game client will launch and connect to the dedicated server. Your player character will spawn in the level and the video stream will begin.

Great work! You now have a working game that connects to a dedicated server on AWS EC2 and streams a video file from S3.

I hope you enjoyed and learned something new from this tutorial. Please feel free to leave me feedback so that I can improve the quality of these tutorials.

Have a wonderful day!

--

--

Luke Brady

A blog fueled by code, coffee, and a healthy dose of video games. Follow me on Twitter: @LukeBrady105