Setting up JW Player with AWS-hosted video assets enables scalable and secure delivery of on-demand video. This guide outlines a production-grade integration that includes S3 storage, CloudFront delivery, JW Player embedding, automated transcoding, DRM, quality switching, responsive UI, and access control.

Overview of Architecture

This architecture leverages AWS services and the JW Player Web SDK to enable video storage, transcoding, and streaming. Key components include Amazon S3 for storage, CloudFront for global delivery, AWS MediaConvert for transcoding, and JW Player for video playback.

Banner for Video Player
  • Amazon S3: Stores video files, including MP4, HLS segments, and thumbnails. S3 offers highly scalable and durable object storage.
  • Amazon CloudFront: Serves as the CDN (Content Delivery Network) for global video delivery, reducing latency and improving load times.
  • AWS MediaConvert: Transcodes videos into formats like HTTP Live Streaming or Dynamic Adaptive Streaming over HTTP for adaptive bitrate streaming.
  • JW Player Web SDK: Embeds the video player on your site or app, enabling rich video playback with support for features like analytics, DRM, and quality switching.
  • Access Control: CloudFront signed URLs provide secure, time-limited access to video content, ensuring only authorized users can view it.

Uploading Video to Amazon S3

Uploading video content to Amazon S3 makes it available for streaming via CloudFront. S3 acts as the origin storage for video files, whether they are raw MP4 files or segmented HLS content. After uploading, CloudFront can serve these videos to end users with minimal latency.

Step 1: Create the S3 Bucket

Create a new S3 bucket where your video files will be stored. S3 buckets are used to organize and store data. By creating a new bucket, you can isolate video content for your streaming purposes. Run the following command to create the bucket:

code
aws s3 mb s3://my-video-bucket

Step 2: Upload Raw Video Files

Once the bucket is created, you can upload your video files. This example uses a basic MP4 file as input. The aws s3 cp command allows you to copy files from your local machine to the specified S3 bucket. Use the following command to upload a raw MP4 file:

code
aws s3 cp ./originals/sample.mp4 s3://my-video-bucket/uploads/sample.mp4

Step 3: Set Public Read Access (Only for Public Content)

If your content is intended to be publicly accessible, you can set the appropriate permissions using the aws s3api put-object-acl command. This will make the video publicly accessible via CloudFront. However, configure signed URLs to control access if the video should be restricted. To set public read access on the uploaded video, run:

code
aws s3api put-object-acl --bucket my-video-bucket --key uploads/sample.mp4 --acl public-read

Thumbnail Generation (Preview Images)

Generating video thumbnails is a crucial step for providing visual previews before the video starts playing. Thumbnails serve as static images that give users a preview of the video content, making it easier to engage with the video. FFmpeg is a powerful tool for generating these thumbnails.

Step 1: Generate Thumbnail

FFmpeg allows you to extract a frame from a specific timestamp in a video and save it as an image file. This command helps you generate a quality thumbnail from a specified time in the video, which can be displayed as a preview. The command to generate a thumbnail from the third second of the video is:

code
ffmpeg -i sample.mp4 -ss 00:00:03 -vframes 1 -vf scale=640:-1 thumbnail.jpg

Step 2: Upload Thumbnail to S3

Once the thumbnail is generated, it needs to be uploaded to your storage system, typically Amazon S3, for use in your video player. Uploading the thumbnail allows it to be accessed alongside the corresponding video file. Use the following AWS CLI command to upload the thumbnail image to your S3 bucket:

code
aws s3 cp thumbnail.jpg s3://my-video-bucket/thumbnails/sample.jpg

Transcoding with AWS MediaConvert

Adaptive bitrate streaming is essential for delivering high-quality video content to users across varying network conditions. AWS MediaConvert simplifies this process by transcoding video files into formats. This process involves converting the video file into smaller segments and generating a playlist.

Step 1: MediaConvert Job Configuration (HLS)

Before starting the transcoding process, you need to create a MediaConvert job configuration file. This configuration file specifies the input video file, the desired output format (HLS in this case), and where the transcoded files should be stored.

Create the JSON Job Configuration File:

This JSON file will contain all the necessary configurations for transcoding the video. It defines the input file, the output settings, and the codec to be used. Example JSON configuration for HLS:

code
{
code
"Settings": {
code
"Inputs": [{
code
"FileInput": "s3://my-video-bucket/uploads/sample.mp4"
code
}],
code
"OutputGroups": [{
code
"Name": "HLS Group",
code
"OutputGroupSettings": {
code
"Type": "HLS_GROUP_SETTINGS",
code
"HlsGroupSettings": {
code
"Destination": "s3://my-video-bucket/hls/sample/"
code
}
code
},
code
"Outputs": [
code
{
code
"VideoDescription": {
code
"Width": 1280,
code
"Height": 720,
code
"CodecSettings": {
code
"Codec": "H_264"
code
}
code
},
code
"ContainerSettings": {
code
"Container": "M3U8"
code
}
code
}
code
]
code
}]
code
}
code
}

Explanation:

  • "Settings": {...}: Defines the main settings for the transcoding job, specifying input and output configurations.
  • "Inputs": [{ "FileInput": "s3://my-video-bucket/uploads/sample.mp4" }]: Specifies the source file (video) to be transcoded, stored in an S3 bucket.
  • "OutputGroups": [{ "Name": "HLS Group", "OutputGroupSettings": {...} }]: Defines the output group for the transcoded content, named "HLS Group", specifying settings related to HLS.
  • "HlsGroupSettings": { "Destination": "s3://my-video-bucket/hls/sample/" }: Specifies the destination in the S3 bucket where the transcoded HLS files will be stored.
  • "Container": "M3U8": Defines the container format for the HLS output as M3U8, which is used for HLS streaming.

Step 2: Submit the MediaConvert Job

Once the job configuration is ready, the next step is to submit the job to AWS MediaConvert for processing. This will trigger the transcoding process, where the video will be encoded into the HLS format.

Submit the Transcoding Job:

Use the AWS CLI to submit the job by pointing to the JSON configuration file you just created. The following command initiates the transcoding process:

aws mediaconvert create-job --region us-east-1 --endpoint-url https://abcd.mediaconvert.us-east-1.amazonaws.com --cli-input-json file://job.json

Transcoding Process:

After submitting the job, AWS MediaConvert processes the video and transcodes it into the HLS format, breaking the video into smaller segments. The output files (M3U8 playlist and .ts video segments) are then stored in the specified S3 location (s3://my-video-bucket/hls/sample/).

CloudFront Setup for Video Delivery

Amazon CloudFront is a Content Delivery Network that enhances video streaming by caching and distributing content across multiple locations worldwide. This reduces latency and improves load times for end users. By configuring CloudFront to deliver video content, you can optimize the streaming experience while ensuring that your content is efficiently distributed.

Step 1: Create CloudFront Distribution

The first step in using CloudFront for video delivery is to create a CloudFront distribution. A distribution is the setup that allows CloudFront to serve content from your origin. When creating the distribution, you'll specify the origin and configure the viewer certificate for secure delivery.

Creating the Distribution:

Use the AWS CLI to create the CloudFront distribution by specifying the origin domain, add the SSL certificate for HTTPS delivery, and set the default root object. By creating the distribution, CloudFront will start caching your video content and will serve it from edge locations.

code
aws cloudfront create-distribution --origin-domain-name my-video-bucket.s3.amazonaws.com --viewer-certificate ACMCertificateArn=your-certificate-arn --enabled --default-root-object video.mp4

Step 2: CloudFront Cache and CORS Setup

To further optimize the performance and security of video delivery, you need to configure Cache Time-to-Live and Cross-Origin Resource Sharing settings. To ensure proper caching and delivery, configure Cache TTL and CORS policy for video files:

Cache TTL (Time-to-Live)

TTL is a setting that determines how long CloudFront should cache your content at the edge before checking for updates. For video files, you can set a long TTL to reduce the load on your origin and improve delivery performance for end users. For example:

  • Cache TTL: Set to a value that reflects the frequency of video updates. For videos that rarely change, you can set a long TTL (e.g., 1 day) to ensure that content is cached at the edge for longer periods.
  • Cache Control Headers: Make sure your S3 objects have appropriate cache control headers to guide CloudFront"s caching behavior.

CORS Setup

Cross-Origin Resource Sharing is essential when your video player requests video content from a different domain. You need to configure CORS headers in CloudFront to allow video files to be served to your player from specific domains. To enable CORS for video delivery:

  1. Go to the CloudFront distribution settings.
  2. Under Cache Behavior Settings, configure the CORS policy.
  3. Set the AllowedOrigins to your player domain (e.g., https://www.yourwebsite.com), and allow GET and HEAD methods to ensure the video files can be accessed for playback.

Example:

code
{
code
"AllowedHeaders": ["*"],
code
"AllowedMethods": ["GET", "HEAD"],
code
"AllowedOrigins": ["https://www.yourplayerdomain.com"],
code
"MaxAgeSeconds": 3600
code
}

Explanation:

  • "AllowedHeaders": ["*"]: Allows any headers in the incoming request, enabling cross-origin requests with any header.
  • "AllowedMethods": ["GET", "HEAD"]: Specifies that only GET and HEAD methods are permitted for cross-origin requests.
  • "AllowedOrigins": ["https://www.yourplayerdomain.com"]: Restricts cross-origin requests to only the specified domain.
  • "MaxAgeSeconds": 3600: Sets the maximum time (1 hour) that the CORS preflight request is cached, improving performance by avoiding repeated checks.

JW Player Setup

Once the video content is uploaded to Amazon S3 and distributed globally through CloudFront, you can integrate JW Player into your web application to enable seamless video playback. JW Player is a widely used, embeddable video player that supports various video formats.

Step 1: Embed JW Player SDK

To begin, you need to include the JW Player SDK in your HTML. The SDK enables the use of JW Player"s features and functionality. To embed the SDK, insert the following script tag into the <head> or <body> section of your HTML:

code
<script src="https://cdn.jwplayer.com/libraries/your-library-id.js"></script> <div id="player"></div>

Step 2: Initialize JW Player with HLS Source

The next step is to initialize the player with the HLS video source. This involves passing the CloudFront URL of your video (in HLS Format) to the JW Player setup function. You can also configure various player settings like thumbnail images, captions, and DRM protection.

Example:

code
jwplayer("player").setup({
file: "https://d123abcxyz.cloudfront.net/hls/sample/master.m3u8",
image: "https://d123abcxyz.cloudfront.net/thumbnails/sample.jpg",
type: "hls",
width: "100%",
aspectratio: "16:9",
autostart: false,
playbackRateControls: true,
tracks: [
{
file: "https://.../captions.vtt",
label: "English",
kind: "captions",
default: true
}
],
drm: {
widevine: {
url: "https://your-widevine-license-url"
}
}
});

Error Handling

To handle errors in both JW Player and S3 uploads, you can set up listeners to capture and log any issues that occur during playback and file uploads. For JW Player, use the error event to capture playback errors and log the error details using console.error. Similarly, for S3 uploads in Node.js, use the AWS SDK's s3.upload() method, where you can capture errors like permission issues or network interruptions.

Example:

code
// JW Player Error Logging
jwplayer("player").on("error", (err) => {
console.error("JW Player error:", err.message);
});

// S3 Upload Error Handling (Node.js)
const AWS = require("aws-sdk");
const s3 = new AWS.S3();

s3.upload(params, function (err, data) {
if (err) {
console.error("S3 Upload Failed:", err);
} else {
console.log("Upload Success:", data.Location);
}
});

Explanation:

  • For JW Player, the error event captures playback issues, logging the error message to help diagnose problems like network failures or unsupported video formats.
  • For S3, the s3.upload() function captures upload errors and logs them for troubleshooting, while also confirming successful uploads with the file"s location.