diff --git a/404.html b/404.html index 5b36682dd..e6e05d971 100644 --- a/404.html +++ b/404.html @@ -9,7 +9,7 @@ - +
diff --git a/account-sharing.html b/account-sharing.html index 15bf6a8db..cc91372a0 100644 --- a/account-sharing.html +++ b/account-sharing.html @@ -9,7 +9,7 @@ - + diff --git a/api.html b/api.html index e77d5c7f0..a086f843b 100644 --- a/api.html +++ b/api.html @@ -9,7 +9,7 @@ - + diff --git a/api/authentication.html b/api/authentication.html index 9e0eea71f..27c6076ed 100644 --- a/api/authentication.html +++ b/api/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/api/authentication/api-keys.html b/api/authentication/api-keys.html index 7c7c32c6b..82c306134 100644 --- a/api/authentication/api-keys.html +++ b/api/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/api/authentication/permissions.html b/api/authentication/permissions.html index ba6bd0c9b..ff3ca068f 100644 --- a/api/authentication/permissions.html +++ b/api/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/api/authentication/tokens.html b/api/authentication/tokens.html index 1def0fb37..ace936474 100644 --- a/api/authentication/tokens.html +++ b/api/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png b/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png new file mode 100644 index 000000000..6b04f7321 Binary files /dev/null and b/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png differ diff --git a/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png b/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png new file mode 100644 index 000000000..8397859b9 Binary files /dev/null and b/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png differ diff --git a/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png b/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png new file mode 100644 index 000000000..75ee32998 Binary files /dev/null and b/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png differ diff --git a/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png b/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png new file mode 100644 index 000000000..37f71ae37 Binary files /dev/null and b/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png differ diff --git a/assets/js/afdab408.63e2b33f.js b/assets/js/afdab408.63e2b33f.js new file mode 100644 index 000000000..9187f1ac1 --- /dev/null +++ b/assets/js/afdab408.63e2b33f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmomento_docs=self.webpackChunkmomento_docs||[]).push([[5697],{38663:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=i(74848),s=i(28453);const o={sidebar_position:2,sidebar_label:"Quick start guide",title:"How to configure a live origin with Momento",description:"Using Momento Storage as a live HLS origin for AWS MediaLive and CloudFront.",pagination_next:null,hide_title:!1,keywords:["momento","media storage","origin","encoding","streaming","live","elemental","tutorial","how to","guide","medialive","CloudFront"]},r="Creating a live video origin with Momento Media Storage, AWS MediaLive, and Amazon CloudFront",a={id:"media-storage/streaming/live-streaming/how-to-medialive-cloudfront",title:"How to configure a live origin with Momento",description:"Using Momento Storage as a live HLS origin for AWS MediaLive and CloudFront.",source:"@site/docs/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.md",sourceDirName:"media-storage/streaming/live-streaming",slug:"/media-storage/streaming/live-streaming/how-to-medialive-cloudfront",permalink:"/media-storage/streaming/live-streaming/how-to-medialive-cloudfront",draft:!1,unlisted:!1,editUrl:"https://github.com/momentohq/public-dev-docs/tree/main/docs/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,sidebar_label:"Quick start guide",title:"How to configure a live origin with Momento",description:"Using Momento Storage as a live HLS origin for AWS MediaLive and CloudFront.",pagination_next:null,hide_title:!1,keywords:["momento","media storage","origin","encoding","streaming","live","elemental","tutorial","how to","guide","medialive","CloudFront"]},sidebar:"mediastorageSidebar",previous:{title:"How it works",permalink:"/media-storage/streaming/live-streaming/how-it-works"}},l={},d=[{value:"Preparation",id:"preparation",level:2},{value:"1. Create a storage namespace in your Momento account",id:"1-create-a-storage-namespace-in-your-momento-account",level:2},{value:"2. Set up AWS MediaLive for live video encoding",id:"2-set-up-aws-medialive-for-live-video-encoding",level:2},{value:"Channel settings",id:"channel-settings",level:3},{value:"Input attachments",id:"input-attachments",level:3},{value:"Output groups",id:"output-groups",level:3},{value:"3. Optimize content delivery with Amazon CloudFront",id:"3-optimize-content-delivery-with-amazon-cloudfront",level:2},{value:"4. Starting the stream",id:"4-starting-the-stream",level:2},{value:"5. Watching the stream",id:"5-watching-the-stream",level:2},{value:"6. Troubleshooting",id:"6-troubleshooting",level:2},{value:"MediaLive and Momento",id:"medialive-and-momento",level:3},{value:"CloudFront",id:"cloudfront",level:3},{value:"That's it!",id:"thats-it",level:2}];function c(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"creating-a-live-video-origin-with-momento-media-storage-aws-medialive-and-amazon-cloudfront",children:"Creating a live video origin with Momento Media Storage, AWS MediaLive, and Amazon CloudFront"})}),"\n",(0,n.jsxs)(t.p,{children:["Live video streaming requires a highly performant and scalable ",(0,n.jsx)(t.a,{href:"/media-storage/core-concepts/origin",children:"origin server"})," to handle the demands of a global audience. Traditional origin servers often struggle with latency, scalability, or complexity when integrated with modern cloud workflows. Momento Media Storage offers a simple, high-scale solution by providing a robust, low-latency, and cost-effective origin solution tailored for live video streaming."]}),"\n",(0,n.jsxs)(t.p,{children:["In this tutorial, you will learn how to set up Momento Media Storage as the origin server for a live video stream encoded by ",(0,n.jsx)(t.a,{href:"https://aws.amazon.com/medialive/",children:"AWS Elemental MediaLive"})," and delivered via ",(0,n.jsx)(t.a,{href:"https://aws.amazon.com/CloudFront/",children:"Amazon CloudFront"}),". By the end of this guide, you'll have a fully functional workflow capable of delivering live ",(0,n.jsx)(t.a,{href:"/media-storage/performance/adaptive-bitrates/hls",children:"HLS streams"})," optimized for performance and reliability."]}),"\n",(0,n.jsx)(t.p,{children:"Here's what we'll cover:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Creating a storage namespace in Momento Media Storage to act as the origin server."}),"\n",(0,n.jsx)(t.li,{children:"Configuring AWS Elemental MediaLive to encode and push live content to Momento."}),"\n",(0,n.jsx)(t.li,{children:"Setting up Amazon CloudFront to serve content to viewers with low latency."}),"\n",(0,n.jsx)(t.li,{children:"Testing and troubleshooting the setup to ensure smooth playback."}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["In this tutorial, we will use the ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com",children:"Momento console"}),", but everything could be created and configured programmatically through ",(0,n.jsx)(t.a,{href:"/platform/sdks",children:"the Momento SDK"}),"."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.strong,{children:"Prefer to learn through video?"})}),"\n",(0,n.jsx)(t.p,{children:"Watch this quick walkthrough of the tutorial to see the steps in action. This video compliments the guide below and is perfect if you're a visual learner or want a high-level overview or additional context before diving into the details."}),"\n",(0,n.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/dwb8Qd7CDYw?si=ALK8BnC2Ugh5ty-S",title:"YouTube video player",frameborder:"0",allow:"accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",referrerpolicy:"strict-origin-when-cross-origin",allowfullscreen:!0}),"\n",(0,n.jsx)(t.h2,{id:"preparation",children:"Preparation"}),"\n",(0,n.jsx)(t.p,{children:"Before creating any resources, please determine the basic characteristics of the live video channel."}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Channel bitrates"}),": The bitrate of a channel depends on the resolution, framerate, and encoding. The table below lists the example bitrates used in this guide."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Segment duration"}),": Segment duration should fall between 1 and 2.5 seconds to minimize glass-to-glass latency. This guide uses 2.5 seconds."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"TTL (Time-to-Live)"}),": TTL determines how long stream data remains available for playback. This guide uses 3600 seconds (1 hour). Note that if your product includes features like DVR playback, you may need a much longer TTL measured in days."]}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsxs)(t.p,{children:["Momento Media Storage supports a maximum object size of 10MB. To estimate segment size, divide the bitrate in Kbps by 8, multiply by the segment duration in seconds, and add 10% to account for headers. For example, a 2 second segment at 1000 Kbps is roughly ",(0,n.jsx)(t.code,{children:"1000 / 8 * 2 * 1.1 = 275 KB"}),"."]})}),"\n",(0,n.jsxs)(t.p,{children:["For the purposes of this tutorial, configure one live video channel for an ",(0,n.jsx)(t.a,{href:"/media-storage/core-concepts/abr-ladder",children:"adaptive bitrate ladder"})," with 3 encoding profiles and 2.5-second segments:"]}),"\n",(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{style:{textAlign:"center"},children:"resolution"}),(0,n.jsx)(t.th,{style:{textAlign:"center"},children:"framerate"}),(0,n.jsx)(t.th,{style:{textAlign:"center"},children:"bitrate"}),(0,n.jsx)(t.th,{style:{textAlign:"center"},children:"segment size"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"720p"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"30"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"2,500 kbps"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"850 KiB"})})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"480p"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"30"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"1,500 kbps"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"500 KiB"})})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"240p"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"30"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"750 kbps"})}),(0,n.jsx)(t.td,{style:{textAlign:"center"},children:(0,n.jsx)(t.code,{children:"250 KiB"})})]})]})]}),"\n",(0,n.jsx)(t.h2,{id:"1-create-a-storage-namespace-in-your-momento-account",children:"1. Create a storage namespace in your Momento account"}),"\n",(0,n.jsxs)(t.p,{children:["Momento Media Storage is currently restricted to private preview access by key design partners. To create a storage namespace, please ensure that you have successfully logged in to the ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com/",children:"Momento Console"})," once to initialize your account. Then, contact ",(0,n.jsx)(t.code,{children:"support@momentohq.com"})," or your support representative with the following information to create a storage namespace:"]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"account id"}),": Locate your account id in the dropdown in the upper right corner of the ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com/",children:"console"})," (",(0,n.jsx)(t.code,{children:"a-xxxxxxxxxxxx"}),")."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"namespace id"}),": The desired id for the new storage namespace. This guide uses ",(0,n.jsx)(t.code,{children:"live-origin"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"AWS region"}),": The AWS region for the new storage namespace. This guide uses ",(0,n.jsx)(t.code,{children:"us-west-1"}),". Once AZ-alignment becomes available, you will also need to specify two AZs within the region."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"hot storage capacity"}),": This determines how much stream data will be held in low-latency storage. Estimate required capacity by adding up the size of all segments and multiplying by the number of segments to keep in hot storage. For example, keeping 5 minutes of the example bitrate ladder in hot storage requires ",(0,n.jsx)(t.code,{children:"(850+500+250)Kib * 300/2.5 \u2248 200 MiB"}),"."]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["While Momento Media Storage is in private preview, the Storage ",(0,n.jsx)(t.em,{children:"namespace"})," will be appear as a ",(0,n.jsx)(t.em,{children:"cache"})," in the console. This guide will use ",(0,n.jsx)(t.em,{children:"namespace"})," interchangeably with ",(0,n.jsx)(t.em,{children:"cache"}),". As Momento Media Storage approaches general availability, updates to the console will make namespace creation a self-service process."]}),"\n",(0,n.jsxs)(t.p,{children:["Next, generate the API key that the encoder will use to securely write segment and manifest files to the ",(0,n.jsx)(t.code,{children:"live-origin"})," namespace. In the ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com/api-keys",children:"API Key section"})," of Momento console, create a Fine-Grained Access Key that expires in 30 days with ",(0,n.jsx)(t.em,{children:"readwrite"})," access to the ",(0,n.jsx)(t.code,{children:"live-origin"}),' namespace. Don\'t forget to click on "Add Permission" to grant the permissions before generating the API key.']}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Momento console showing readwrite permissions for the live-origin namespace",src:i(71718).A+"",width:"1593",height:"936"})}),"\n",(0,n.jsxs)(t.p,{children:["API key information will no longer be available after you navigate away from this page, so download the API key as a JSON file. The guide will refer to this API key as ",(0,n.jsx)(t.code,{children:"encoder_api_key"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Video players read the content pushed by encoders to Momento Media Storage via a ",(0,n.jsx)(t.strong,{children:"Content Delivery Network (CDN)"}),". As a security best practices, create a second API key with ",(0,n.jsx)(t.em,{children:"readonly"})," access to the ",(0,n.jsx)(t.code,{children:"live-origin"})," namespace. Use the same ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com/api-keys",children:"API key page"})," as before to create this new API key. The guide will refer to this API key as ",(0,n.jsx)(t.code,{children:"player_api_key"}),"."]}),"\n",(0,n.jsx)(t.admonition,{title:"Checking in",type:"info",children:(0,n.jsxs)(t.p,{children:["At the end of this step, you should have created two API keys: one that grants ",(0,n.jsx)(t.em,{children:"readwrite"})," access and one that ",(0,n.jsx)(t.em,{children:"readonly"})," access to the ",(0,n.jsx)(t.code,{children:"live-origin"})," namespace. Keep these handy to use in the upcoming steps."]})}),"\n",(0,n.jsx)(t.h2,{id:"2-set-up-aws-medialive-for-live-video-encoding",children:"2. Set up AWS MediaLive for live video encoding"}),"\n",(0,n.jsxs)(t.p,{children:["AWS Elemental MediaLive is a live video encoding service from AWS that processes and delivers live streams at scale. MediaLive converts live video into streaming formats like ",(0,n.jsx)(t.a,{href:"/media-storage/performance/adaptive-bitrates/hls",children:"HLS"}),". It is commonly used for live sports, major live events, and 24/7 channels."]}),"\n",(0,n.jsxs)(t.p,{children:["MediaLive will act as the ",(0,n.jsx)(t.strong,{children:"encoder"})," in this live video workflow. The encoded video will be sent directly to Momento Media Storage, which functions as the origin server."]}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsxs)(t.p,{children:["For best performance, make sure the MediaLive service and the ",(0,n.jsx)(t.code,{children:"live-origin"})," namespace are in the same AWS region or as close as possible. If you are new to MediaLive, refer to the ",(0,n.jsx)(t.a,{href:"https://docs.aws.amazon.com/medialive/latest/ug/container-planning-workflow.html",children:"AWS documentation"})," for detailed setup instructions."]})}),"\n",(0,n.jsx)(t.h3,{id:"channel-settings",children:"Channel settings"}),"\n",(0,n.jsxs)(t.p,{children:["First navigate to the ",(0,n.jsx)(t.a,{href:"https://console.aws.amazon.com/medialive/home#/channels/new",children:"create channel"})," page in AWS MediaLive. Give your channel a meaningful name, and if this is your first time using the service, follow the instructions to ",(0,n.jsx)(t.em,{children:"Create role from template"})," to create an IAM role with the necessary permissions for encoding. After setup, select the ",(0,n.jsx)(t.code,{children:"MediaLiveAccessRole"})," role."]}),"\n",(0,n.jsxs)(t.p,{children:["We will not be using a channel template or changing any input specifications. However, we will be changing the ",(0,n.jsx)(t.strong,{children:"Channel class"})," to ",(0,n.jsx)(t.code,{children:"SINGLE_PIPELINE"}),". Leave all other configuration fields alone, the default values are appropriate for our use case. Once configured, you should have something that resembles the screenshot below."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"MediaLive channel settings page fully configured",src:i(16471).A+"",width:"1269",height:"1111"})}),"\n",(0,n.jsx)(t.h3,{id:"input-attachments",children:"Input attachments"}),"\n",(0,n.jsxs)(t.p,{children:["Next, we must configure an input for our channel. The input is the media that will be streamed on our channel while it is active. You can either click the ",(0,n.jsx)(t.em,{children:"Add"})," button next to the ",(0,n.jsx)(t.strong,{children:"Input attachments"})," label, or ",(0,n.jsx)(t.a,{href:"https://console.aws.amazon.com/medialive/home#/inputs",children:"navigate directly"})," to the input list."]}),"\n",(0,n.jsxs)(t.p,{children:["If you already have an input you'd like to use, select it now. Otherwise, click on the ",(0,n.jsx)(t.em,{children:"Create input"})," button to create a new one. For our example, we will be streaming a copy of ",(0,n.jsx)(t.em,{children:"Big Buck Bunny"})," in MP4 format that is publicly available in an S3 bucket. So let's give it an appropriate name, input type of ",(0,n.jsx)(t.code,{children:"MP4"}),", and select an ",(0,n.jsx)(t.strong,{children:"Input class"})," of ",(0,n.jsx)(t.code,{children:"SINGLE_INPUT"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Put the publicly accessible url to the MP4 in the ",(0,n.jsx)(t.strong,{children:"Input source A"})," field, and leave all other fields alone. It should resemble the following:"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"MediaLive completed input page",src:i(30452).A+"",width:"1340",height:"1138"})}),"\n",(0,n.jsxs)(t.p,{children:["Once configured, hit the ",(0,n.jsx)(t.em,{children:"Create input"})," button, navigate back to the channel configuration page, and select the input we just created."]}),"\n",(0,n.jsx)(t.h3,{id:"output-groups",children:"Output groups"}),"\n",(0,n.jsxs)(t.p,{children:["Now time for the important part: configuring the outputs we would like the input converted to. As mentioned at the beginning of this tutorial, we will be generating three variants at different resolutions: ",(0,n.jsx)(t.em,{children:"720p"}),", ",(0,n.jsx)(t.em,{children:"480p"}),", and ",(0,n.jsx)(t.em,{children:"240p"}),". To do this, we configure an output group for our channel."]}),"\n",(0,n.jsxs)(t.p,{children:["Click on the ",(0,n.jsx)(t.em,{children:"Add"})," button next to ",(0,n.jsx)(t.strong,{children:"Output groups"})," on the channel configuration page, select ",(0,n.jsx)(t.em,{children:"HLS"})," as the output group type, and hit the ",(0,n.jsx)(t.em,{children:"Confirm"})," button."]}),"\n",(0,n.jsxs)(t.p,{children:["The destination URL is going to be writing directly to the ",(0,n.jsx)(t.a,{href:"https://docs.momentohq.com/cache/develop/api-reference/http-api",children:"Momento HTTP API"})," using the ",(0,n.jsx)(t.code,{children:"encoder_api_key"})," we setup earlier. It should be in the following format:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"https://In this tutorial, we will use the Momento console, but everything could be created and configured programmatically through the Momento SDK.
+Prefer to learn through video?
+Watch this quick walkthrough of the tutorial to see the steps in action. This video compliments the guide below and is perfect if you're a visual learner or want a high-level overview or additional context before diving into the details.
+Before creating any resources, please determine the basic characteristics of the live video channel.
Channel bitrates: The bitrate of a channel depends on the resolution, framerate, and encoding. The table below lists the example bitrates used in this guide.
@@ -50,18 +53,32 @@MediaLive will act as the encoder in this live video workflow. The encoded video will be sent directly to Momento Media Storage, which functions as the origin server.
For best performance, make sure the MediaLive service and the live-origin
namespace are in the same AWS region or as close as possible. If you are new to MediaLive, refer to the AWS documentation for detailed setup instructions.
Configure a MediaLive channel with one encoding pipeline that outputs to a single destination, the live-origin
namespace. The output destination URL for the channel should follow this format:
https://<momento_rest_endpoint>/cache/<namespace_id>/playlist.m3u8?ttl_seconds=<ttl>
First navigate to the create channel page in AWS MediaLive. Give your channel a meaningful name, and if this is your first time using the service, follow the instructions to Create role from template to create an IAM role with the necessary permissions for encoding. After setup, select the MediaLiveAccessRole
role.
We will not be using a channel template or changing any input specifications. However, we will be changing the Channel class to SINGLE_PIPELINE
. Leave all other configuration fields alone, the default values are appropriate for our use case. Once configured, you should have something that resembles the screenshot below.
Next, we must configure an input for our channel. The input is the media that will be streamed on our channel while it is active. You can either click the Add button next to the Input attachments label, or navigate directly to the input list.
+If you already have an input you'd like to use, select it now. Otherwise, click on the Create input button to create a new one. For our example, we will be streaming a copy of Big Buck Bunny in MP4 format that is publicly available in an S3 bucket. So let's give it an appropriate name, input type of MP4
, and select an Input class of SINGLE_INPUT
.
Put the publicly accessible url to the MP4 in the Input source A field, and leave all other fields alone. It should resemble the following:
+ +Once configured, hit the Create input button, navigate back to the channel configuration page, and select the input we just created.
+Now time for the important part: configuring the outputs we would like the input converted to. As mentioned at the beginning of this tutorial, we will be generating three variants at different resolutions: 720p, 480p, and 240p. To do this, we configure an output group for our channel.
+Click on the Add button next to Output groups on the channel configuration page, select HLS as the output group type, and hit the Confirm button.
+The destination URL is going to be writing directly to the Momento HTTP API using the encoder_api_key
we setup earlier. It should be in the following format:
https://<momento_rest_endpoint>/cache/<namespace_id>/playlist.m3u8?ttl_seconds=<ttl>&role=origin
The variable placeholders are:
momento_rest_endpoint
- Momento HTTP API region-specific endpoint (see list)namespace_id
- ID of the namespace receiving uploaded segmentsttl
- number of seconds to retain the playlist and segments before deletionApplying the configuration from this tutorial, the resulting destination URL would be:
-https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600
NOTE - notice the role=origin
query parameter at the end. This is required for MediaLive to publish segments!
As an example, your destination URL should look something like this:
+https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600&role=origin
Next, expand the Credentials section. Set Username to momento
. Select Create parameter under Password and follow the instructions to create a new parameter named /medialive/momento_api_key
that contains the previously-created encoder API key.
Under CDN Settings, select HLS Akamai. It is necessary to specify HLS Akamai so that MediaLive will properly transmit credentials with each request.
+Under CDN Settings, select HLS Akamai. We use HLS Akamai so that MediaLive will properly transmit credentials with each request. There's a small quirk with the service when using HLS basic put that omits the credentials.
In the Manifest and Segments section, configure the following fields:
Variant playlists behavior: These playlist_*.m3u8
files are refreshed every time a new media segment is available from AWS Elemental MediaLive. When MediaLive recreates the playlists, it automatically appends the encoder_api_key
token query parameter in its URI. Since the default rules apply a different, conflicting value (player_api_key
) in Authorization header when requesting these segments, we need to define a behavior where the Authorization header is dropped for these requests. To accomplish this, set the Origin request policy to None.
With that, we're ready to stream! You can now point your favorite HLS player (in VLC media player open a network stream and paste the .m3u8 path) to https://<cloudfront_id>.CloudFront.net/playlist.m3u8
and play the live stream encoded by AWS Elemental MediaLive.
Now that we have our CDN configured allowing video players to access the playlists and segments, let's see if it works! Navigate back to the channel we created and hit the Start button. After a few moments, your channel will be broadcasting the video!
+ +That's it, the stream is active and will be creating segments and uploading them to our live-origin
cache. Now let's see it in action.
If you already have a compatible media player like VLC media player that accepts an HLS playlist, great! If you'd rather use an online player, you can navigate to Livepush.io for testing purposes.
+To get the url of our livestream, we need to get the distribution id of our CloudFront distribution. Navigate to the CloudFront distribution page to find it. Once you have it, the url to our playlist is in the following format:
+https://<cloudfront_id>.CloudFront.net/playlist.m3u8
You can put this url in the player to start watching your stream!
+ +If things go wrong and the stream doesn't play, the best way to troubleshoot is to manually check each of the steps that is performed by the HLS video player.
-