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:///cache//playlist.m3u8?ttl_seconds=&role=origin\n"})}),"\n",(0,n.jsx)(t.p,{children:"The variable placeholders are:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"momento_rest_endpoint"})," - Momento HTTP API region-specific endpoint (",(0,n.jsx)(t.a,{href:"/platform/regions",children:"see list"}),")"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"namespace_id"})," - ID of the namespace receiving uploaded segments"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ttl"})," - number of seconds to retain the playlist and segments before deletion"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsxs)(t.em,{children:["NOTE - notice the ",(0,n.jsx)(t.code,{children:"role=origin"})," query parameter at the end. This is required for MediaLive to publish segments!"]})}),"\n",(0,n.jsx)(t.p,{children:"As an example, your destination URL should look something like this:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600&role=origin\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Next, expand the ",(0,n.jsx)(t.em,{children:"Credentials"})," section. Set ",(0,n.jsx)(t.em,{children:"Username"})," to ",(0,n.jsx)(t.code,{children:"momento"}),". Select ",(0,n.jsx)(t.strong,{children:"Create parameter"})," under ",(0,n.jsx)(t.em,{children:"Password"})," and follow the instructions to create a new parameter named ",(0,n.jsx)(t.code,{children:"/medialive/momento_api_key"})," that contains the previously-created encoder API key."]}),"\n",(0,n.jsxs)(t.p,{children:["Under ",(0,n.jsx)(t.em,{children:"CDN Settings"}),", select ",(0,n.jsx)(t.strong,{children:"HLS Akamai"}),". We use ",(0,n.jsx)(t.strong,{children:"HLS Akamai"})," so that MediaLive will properly transmit credentials with each request. There's a small quirk with the service when using ",(0,n.jsx)(t.em,{children:"HLS basic put"})," that omits the credentials."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"AWS MediaLive console with channel configuration filled out",src:i(17793).A+"",width:"1338",height:"1436"})}),"\n",(0,n.jsxs)(t.p,{children:["In the ",(0,n.jsx)(t.strong,{children:"Manifest and Segments"})," section, configure the following fields:"]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Output Selection"})," - MANIFESTS_AND_SEGMENTS"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Mode"})," - LIVE"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"TS File Mode"})," - SEGMENTED_FILES"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Segment Length"})," - 2"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"The remaining settings should match the configuration below:"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"AWS MediaLive console with output configuration complete",src:i(600).A+"",width:"1449",height:"830"})}),"\n",(0,n.jsxs)(t.p,{children:["Finally, we configure how AWS Elemental MediaLive updates the variant playlists: the variant playlists are derived from the master manifest by appending a ",(0,n.jsx)(t.em,{children:"Name modifier"})," at the end of the master playlist chosen name. For each variant playlist/output, add a descriptive modifier that tells us at a glance which playlist we are looking at. For example, each of the variant playlists in the example bitrate ladder will have ",(0,n.jsx)(t.code,{children:"_480p30"}),", ",(0,n.jsx)(t.code,{children:"_240p30"}),", and ",(0,n.jsx)(t.code,{children:"_720p30"})," as the ",(0,n.jsx)(t.em,{children:"Name Modifier"}),". Since we named the master manifest ",(0,n.jsx)(t.code,{children:"playlist.m3u8"}),", the resulting variant manifests will be named respectively ",(0,n.jsx)(t.code,{children:"playlist_480p30.m3u8"}),", ",(0,n.jsx)(t.code,{children:"playlist_240p30.m3u8"}),", and ",(0,n.jsx)(t.code,{children:"playlist_720p30.m3u8"}),". This naming convention will need to be specified in the CloudFront settings below."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"AWS MediaLive console with the name modifier configured for all outputs",src:i(4693).A+"",width:"1436",height:"819"})}),"\n",(0,n.jsxs)(t.p,{children:["Once everything is configured, hit the ",(0,n.jsx)(t.em,{children:"Create channel"})," button to create the encoder!"]}),"\n",(0,n.jsx)(t.h2,{id:"3-optimize-content-delivery-with-amazon-cloudfront",children:"3. Optimize content delivery with Amazon CloudFront"}),"\n",(0,n.jsx)(t.p,{children:"Amazon CloudFront is a Content Delivery Network (CDN) that ensures the live video streams are delivered quickly and reliably to viewers worldwide. In this step, we'll configure CloudFront to work with Momento Media Storage - optimizing latency, managing costs, and securing access."}),"\n",(0,n.jsx)(t.p,{children:"CloudFront will serve two key purposes in this workflow:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Reduce latency and costs by caching video segments across its Points of Presence (PoPs)."}),"\n",(0,n.jsx)(t.li,{children:"Secure access to the Momento origin by adding the appropriate authorization tokens to requests."}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"/media-storage/core-concepts/segments",children:"Media segments"})," are assets that change infrequently. They represent 1-5 seconds of video, audio, or metadata that will not change once it's been generated by the encoder. These media assets are usually best cached by a CDN service like Amazon CloudFront across multiple PoPs located close to the end viewers for both ",(0,n.jsx)(t.a,{href:"/media-storage/streaming/live-streaming/how-it-works",children:"live"})," and ",(0,n.jsx)(t.a,{href:"/media-storage/streaming/video-on-demand/media-storage",children:"VOD"})," video workflows."]}),"\n",(0,n.jsxs)(t.p,{children:['While VOD workflows have HLS manifests that never change once they are created, HLS manifests in live video workflows are constantly recreated by the encoders to present the latest media segments, at the "live point". As a result, ',(0,n.jsx)(t.em,{children:"live HLS manifests should not be cached by a CDN for longer than the size of a media segment"}),". So we will ",(0,n.jsx)(t.strong,{children:"not cache the manifests"})," and instead hand them over the Momento origin, which is designed to manage frequently changing objects."]}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsx)(t.p,{children:"You can optimize retrieval of manifest files by specifying a short TTL in the appropriate CloudFront behavior."})}),"\n",(0,n.jsxs)(t.p,{children:["In the ",(0,n.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront",children:"Amazon CloudFront console"}),", create a CloudFront distribution that enables these rules through custom CloudFront behaviors."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CloudFront console with the create distribution fields completed",src:i(72130).A+"",width:"1433",height:"885"})}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.em,{children:"Origin domain"})," of the CloudFront distribution must be set as the ",(0,n.jsx)(t.code,{children:"momento_rest_endpoint"})," url we used to configure the MediaLive channel, with the ",(0,n.jsx)(t.em,{children:"Origin path"})," as ",(0,n.jsx)(t.code,{children:"/cache/"}),". Note the ",(0,n.jsx)(t.em,{children:"Origin path"})," field ",(0,n.jsx)(t.strong,{children:"is required for this workflow"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Since CloudFront is accessed by video players, which don't go through auth flows to obtain API keys or session tokens, we must set up the default policy to add an ",(0,n.jsx)(t.em,{children:"Authorization"})," header with ",(0,n.jsx)(t.code,{children:"player_api_key"})," for incoming requests. This enables CloudFront to automatically forward an API key to Momento, granting read-only access to the generated segments."]}),"\n",(0,n.jsxs)(t.p,{children:["You do not need to enable the ",(0,n.jsx)(t.em,{children:"Origin Shield"})," functionality of CloudFront, Momento takes care of it natively."]}),"\n",(0,n.jsxs)(t.p,{children:["For the ",(0,n.jsx)(t.strong,{children:"Web Application Firewall (WAF)"})," settings, select ",(0,n.jsx)(t.em,{children:"Do not enable security protections"})," for the demo."]}),"\n",(0,n.jsx)(t.p,{children:"Now we need to define the CloudFront behaviors for three types of objects read from the Momento origin server:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"The default behavior"}),"\n",(0,n.jsx)(t.li,{children:"The behavior for media segments"}),"\n",(0,n.jsx)(t.li,{children:"The behavior for variant playlists"}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CloudFront console listing the caching behaviors and their policies",src:i(74155).A+"",width:"1444",height:"527"})}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Default behavior"}),': This "behavior" is for items that are not part of the video origin workflow. We assume these objects will be changed frequently, so we won\'t cache them in CloudFront, using the a "CachingDisabled" policy. Configure the policy as outlined below.']}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CloudFront behavior for the default behavior",src:i(40021).A+"",width:"1446",height:"895"})}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Media segments behavior"}),': These files won\'t change after the encoder has sent them to the origin, so they are good candidates for being cached by CloudFront and its "CachingOptimized" policy. From the AWS MediaLive configuration, the segments that contain audio/video will always have the file extension ',(0,n.jsx)(t.code,{children:".ts"})," :"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CloudFront behavior for caching segments",src:i(24386).A+"",width:"1450",height:"864"})}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Variant playlists behavior"}),": These ",(0,n.jsx)(t.code,{children:"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 ",(0,n.jsx)(t.code,{children:"encoder_api_key"})," token query parameter in its URI. Since the default rules apply a different, conflicting value (",(0,n.jsx)(t.code,{children:"player_api_key"}),") in ",(0,n.jsx)(t.em,{children:"Authorization"})," header when requesting these segments, we need to define a behavior where the ",(0,n.jsx)(t.em,{children:"Authorization"})," header is dropped for these requests. To accomplish this, set the ",(0,n.jsx)(t.em,{children:"Origin request policy"})," to None."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CloudFront behavior for variant playlists",src:i(17118).A+"",width:"1450",height:"840"})}),"\n",(0,n.jsx)(t.h2,{id:"4-starting-the-stream",children:"4. Starting the stream"}),"\n",(0,n.jsxs)(t.p,{children:["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 ",(0,n.jsx)(t.a,{href:"https://console.aws.amazon.com/medialive/home#/channels",children:"channel we created"})," and hit the ",(0,n.jsx)(t.strong,{children:"Start"})," button. After a few moments, your channel will be broadcasting the video!"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"MediaLive channel in a playing status",src:i(47728).A+"",width:"1343",height:"627"})}),"\n",(0,n.jsxs)(t.p,{children:["That's it, the stream is active and will be creating segments and uploading them to our ",(0,n.jsx)(t.code,{children:"live-origin"})," cache. Now let's see it in action."]}),"\n",(0,n.jsx)(t.h2,{id:"5-watching-the-stream",children:"5. Watching the stream"}),"\n",(0,n.jsxs)(t.p,{children:["If you already have a compatible media player like ",(0,n.jsx)(t.a,{href:"https://www.videolan.org/",children:"VLC media player"})," that accepts an HLS playlist, great! If you'd rather use an online player, you can navigate to ",(0,n.jsx)(t.a,{href:"https://livepush.io/hlsplayer/index.html",children:"Livepush.io"})," for testing purposes."]}),"\n",(0,n.jsxs)(t.p,{children:["To get the url of our livestream, we need to get the distribution id of our CloudFront distribution. Navigate to the ",(0,n.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront/v4/home#/distributions",children:"CloudFront distribution page"})," to find it. Once you have it, the url to our playlist is in the following format:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"https://.CloudFront.net/playlist.m3u8\n"})}),"\n",(0,n.jsx)(t.p,{children:"You can put this url in the player to start watching your stream!"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"HLS player streaming our content",src:i(12222).A+"",width:"970",height:"650"})}),"\n",(0,n.jsx)(t.h2,{id:"6-troubleshooting",children:"6. Troubleshooting"}),"\n",(0,n.jsx)(t.p,{children:"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."}),"\n",(0,n.jsx)(t.h3,{id:"medialive-and-momento",children:"MediaLive and Momento"}),"\n",(0,n.jsxs)(t.p,{children:["Verify the master manifest is accessible with ",(0,n.jsx)(t.code,{children:"player_api_key"})," and returns the variant playlists correctly. Use the following ",(0,n.jsx)(t.code,{children:"curl"})," command to test, or use the ",(0,n.jsx)(t.a,{href:"https://console.gomomento.com/caches/live-origin",children:"Momento console"})," to view data in the namespace."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-STREAM-INF:BANDWIDTH=2648800,AVERAGE-BANDWIDTH=1790800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=30.000\nplaylist_480p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=1394800,AVERAGE-BANDWIDTH=965800,CODECS="avc1.4d400d,mp4a.40.2",RESOLUTION=320x240,FRAME-RATE=30.000\nplaylist_240p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=4391200,AVERAGE-BANDWIDTH=2961200,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x720,FRAME-RATE=30.000\nplaylist_720p30.m3u8?ttl_seconds=3600\n'})}),"\n",(0,n.jsxs)(t.p,{children:["Verify that each variant playlist is accessible, and if you can download the last media segment listed in the variant playlists (aka ",(0,n.jsx)(t.em,{children:"the live point"}),"). Below are the ",(0,n.jsx)(t.code,{children:"curl"})," commands to view the 480p manifest and the live point."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist_480p30.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:2\n#EXT-X-MEDIA-SEQUENCE:891\n#EXTINF:2.00000,\nplaylist_480p30_00891.ts\n#EXTINF:2.00000,\nplaylist_480p30_00892.ts\n#EXTINF:2.00000,\n[...]\n#EXTINF:2.00000,\nplaylist_480p30_00939.ts\n#EXTINF:2.00000,\nplaylist_480p30_00940.ts\n\n$ curl -o test.ts "https:///cache/live-origin/playlist_480p30_00940.ts?token="\n'})}),"\n",(0,n.jsxs)(t.p,{children:["When viewing the live point, verify a ",(0,n.jsx)(t.code,{children:"test.ts"})," file is correctly downloaded and looks OK with your favorite test tool (",(0,n.jsx)(t.a,{href:"https://ffmpeg.org/ffprobe.html",children:"ffprobe"}),", ",(0,n.jsx)(t.a,{href:"https://mediaarea.net/en/MediaInfo",children:"mediainfo"}),", etc...)."]}),"\n",(0,n.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"encoder_api_key"})," or ",(0,n.jsx)(t.code,{children:"player_api_key"})," might not have the right access level to the namespace."]}),"\n",(0,n.jsxs)(t.li,{children:["AWS Elemental MediaLive isn't configured correctly or isn't running.","\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Double check the URI provided in the ",(0,n.jsx)(t.em,{children:"Destination URL"})," field at the HLS output group level, and don't forget to add the query parameters ",(0,n.jsx)(t.code,{children:"&ttl_seconds=&role=origin"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"cloudfront",children:"CloudFront"}),"\n",(0,n.jsxs)(t.p,{children:["If everything looks correct in MediaLive and Momento, verify the requests from CloudFront. The distribution rules already embed an authorization header, so you don't need to add ",(0,n.jsx)(t.code,{children:"player_api_key"})," in the URIs. Verify that CloudFront inserts them properly."]}),"\n",(0,n.jsxs)(t.p,{children:["The three commands below produce the same results as the requests sent from the player through CloudFront to Momento Media Storage. Remember that the media segments listed in each variant playlist constantly change, so replace ",(0,n.jsx)(t.code,{children:""})," in the final command with a valid value from the fetched playlist:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'$ curl "https://.CloudFront.net/playlist.m3u8"\n\n$ curl "https://.CloudFront.net/playlist_480p30.m3u8"\n\n$ curl -o test.ts "https://.CloudFront.net/playlist_480p30_.ts"\n'})}),"\n",(0,n.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["The ",(0,n.jsx)(t.em,{children:"Authorization"})," header has not been correctly set to the ",(0,n.jsx)(t.code,{children:"player_api_key"})," when the CloudFront distribution was created."]}),"\n",(0,n.jsx)(t.li,{children:"A CloudFront behavior might be incorrectly set. Double check the file patterns and the associated caching policies."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"thats-it",children:"That's it!"}),"\n",(0,n.jsx)(t.p,{children:"Congratulations! You've successfully set up a live video streaming workflow using Momento Media Storage, AWS MediaLive, and Amazon CloudFront. This modern, scalable solution ensures low latency, reliability, and optimal performance for delivering live HLS streams."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.strong,{children:"Here's what you've learned:"})}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Configured Momento Media Storage as a highly performant and cost-effective origin server."}),"\n",(0,n.jsx)(t.li,{children:"Set up AWS MediaLive to encode and push adaptive bitrate streams directly to Momento."}),"\n",(0,n.jsx)(t.li,{children:"Optimized content delivery using CloudFront to reduce latency, manage costs, and secure playback access."}),"\n",(0,n.jsx)(t.li,{children:"Tested and troubleshot the setup to ensure seamless streaming from origin to viewers."}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.strong,{children:"Next Steps"})}),"\n",(0,n.jsx)(t.p,{children:"Now that your live streaming workflow is up and running, consider exploring additional features and optimizations:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Learn about ",(0,n.jsx)(t.a,{href:"/media-storage/entitlements/about",children:"adding entitlements"})," to your workflow."]}),"\n",(0,n.jsxs)(t.li,{children:["Discover ",(0,n.jsx)(t.a,{href:"/media-storage/streaming/capture/rtmp",children:"how to use ffmpeg and an RTMP stream"})," to stream to Momento."]}),"\n",(0,n.jsxs)(t.li,{children:["Add ",(0,n.jsx)(t.a,{href:"/media-storage/enhancements/live-reactions",children:"real-time reactions"})," to your streams."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"We can't wait to see what you build. Happy coding!"})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},74155:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/cloudfront-behaviors-92f08c82ed020eb64f587494e7f9954b.png"},40021:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/cloudfront-default-566d7cf82846c4605a1f7cbede42a0d0.png"},72130:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/cloudfront-origin-a1e9cbd1c710e1b9f52d8249986c6444.png"},17118:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/cloudfront-playlist-051452112d56ec21ffd125f52f727c8e.png"},24386:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/cloudfront-segments-76df56e726fd2007b4fb5a7e747d1b81.png"},71718:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/console-api-key-2-a4a7f23149d0dfbb3526c1fd7694ef90.png"},12222:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png"},47728:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png"},16471:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png"},17793:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-hls-group-06db498b5dadcfa35c3e4e21c6447c2d.png"},30452:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png"},4693:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-output-8013ead6ef592f79ec11c8d9a97edf5d.png"},600:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/medialive-segments-865e610dfd66c11fbaa5dae87166cf45.png"},28453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var n=i(96540);const s={},o=n.createContext(s);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/afdab408.7122bf99.js b/assets/js/afdab408.7122bf99.js deleted file mode 100644 index 8dbf34e23..000000000 --- a/assets/js/afdab408.7122bf99.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmomento_docs=self.webpackChunkmomento_docs||[]).push([[5697],{38663:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=n(74848),o=n(28453);const s={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:"3. Optimize content delivery with Amazon CloudFront",id:"3-optimize-content-delivery-with-amazon-cloudfront",level:2},{value:"4. Playback and troubleshooting",id:"4-playback-and-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,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.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,i.jsxs)(t.p,{children:["Live video streaming requires a highly performant and scalable ",(0,i.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,i.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,i.jsx)(t.a,{href:"https://aws.amazon.com/medialive/",children:"AWS Elemental MediaLive"})," and delivered via ",(0,i.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,i.jsx)(t.a,{href:"/media-storage/performance/adaptive-bitrates/hls",children:"HLS streams"})," optimized for performance and reliability."]}),"\n",(0,i.jsx)(t.p,{children:"Here's what we'll cover:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Creating a storage namespace in Momento Media Storage to act as the origin server."}),"\n",(0,i.jsx)(t.li,{children:"Configuring AWS Elemental MediaLive to encode and push live content to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Setting up Amazon CloudFront to serve content to viewers with low latency."}),"\n",(0,i.jsx)(t.li,{children:"Testing and troubleshooting the setup to ensure smooth playback."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["In this tutorial, we will use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com",children:"Momento console"}),", but everything could be created and configured programmatically through ",(0,i.jsx)(t.a,{href:"/platform/sdks",children:"the Momento SDK"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"preparation",children:"Preparation"}),"\n",(0,i.jsx)(t.p,{children:"Before creating any resources, please determine the basic characteristics of the live video channel."}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.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,i.jsx)(t.code,{children:"1000 / 8 * 2 * 1.1 = 275 KB"}),"."]})}),"\n",(0,i.jsxs)(t.p,{children:["For the purposes of this tutorial, configure one live video channel for an ",(0,i.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,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"resolution"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"framerate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"bitrate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"segment size"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"720p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"2,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"850 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"480p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"1,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"500 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"240p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"750 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"250 KiB"})})]})]})]}),"\n",(0,i.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,i.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,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"Momento Console"})," once to initialize your account. Then, contact ",(0,i.jsx)(t.code,{children:"support@momentohq.com"})," or your support representative with the following information to create a storage namespace:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"account id"}),": Locate your account id in the dropdown in the upper right corner of the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"console"})," (",(0,i.jsx)(t.code,{children:"a-xxxxxxxxxxxx"}),")."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"namespace id"}),": The desired id for the new storage namespace. This guide uses ",(0,i.jsx)(t.code,{children:"live-origin"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"AWS region"}),": The AWS region for the new storage namespace. This guide uses ",(0,i.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,i.jsxs)(t.li,{children:[(0,i.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,i.jsx)(t.code,{children:"(850+500+250)Kib * 300/2.5 \u2248 200 MiB"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["While Momento Media Storage is in private preview, the Storage ",(0,i.jsx)(t.em,{children:"namespace"})," will be appear as a ",(0,i.jsx)(t.em,{children:"cache"})," in the console. This guide will use ",(0,i.jsx)(t.em,{children:"namespace"})," interchangeably with ",(0,i.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,i.jsxs)(t.p,{children:["Next, generate the API key that the encoder will use to securely write segment and manifest files to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. In the ",(0,i.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,i.jsx)(t.em,{children:"readwrite"})," access to the ",(0,i.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,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Momento console showing readwrite permissions for the live-origin namespace",src:n(71718).A+"",width:"1593",height:"936"})}),"\n",(0,i.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,i.jsx)(t.code,{children:"encoder_api_key"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Video players read the content pushed by encoders to Momento Media Storage via a ",(0,i.jsx)(t.strong,{children:"Content Delivery Network (CDN)"}),". As a security best practices, create a second API key with ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Use the same ",(0,i.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,i.jsx)(t.code,{children:"player_api_key"}),"."]}),"\n",(0,i.jsx)(t.admonition,{title:"Checking in",type:"info",children:(0,i.jsxs)(t.p,{children:["At the end of this step, you should have created two API keys: one that grants ",(0,i.jsx)(t.em,{children:"readwrite"})," access and one that ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Keep these handy to use in the upcoming steps."]})}),"\n",(0,i.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,i.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,i.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,i.jsxs)(t.p,{children:["MediaLive will act as the ",(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsxs)(t.p,{children:["For best performance, make sure the MediaLive service and the ",(0,i.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,i.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,i.jsxs)(t.p,{children:["Configure a MediaLive channel with one encoding pipeline that outputs to a single destination, the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. The output destination URL for the channel should follow this format:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https:///cache//playlist.m3u8?ttl_seconds=\n"})}),"\n",(0,i.jsx)(t.p,{children:"The variable placeholders are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," - Momento HTTP API region-specific endpoint (",(0,i.jsx)(t.a,{href:"/platform/regions",children:"see list"}),")"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"namespace_id"})," - ID of the namespace receiving uploaded segments"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"ttl"})," - number of seconds to retain the playlist and segments before deletion"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Applying the configuration from this tutorial, the resulting destination URL would be:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600\n"})}),"\n",(0,i.jsxs)(t.p,{children:["Next, expand the ",(0,i.jsx)(t.em,{children:"Credentials"})," section. Set ",(0,i.jsx)(t.em,{children:"Username"})," to ",(0,i.jsx)(t.code,{children:"momento"}),". Select ",(0,i.jsx)(t.strong,{children:"Create parameter"})," under ",(0,i.jsx)(t.em,{children:"Password"})," and follow the instructions to create a new parameter named ",(0,i.jsx)(t.code,{children:"/medialive/momento_api_key"})," that contains the previously-created encoder API key."]}),"\n",(0,i.jsxs)(t.p,{children:["Under ",(0,i.jsx)(t.em,{children:"CDN Settings"}),", select ",(0,i.jsx)(t.strong,{children:"HLS Akamai"}),". It is necessary to specify ",(0,i.jsx)(t.strong,{children:"HLS Akamai"})," so that MediaLive will properly transmit credentials with each request."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with channel configuration filled out",src:n(17793).A+"",width:"1338",height:"1436"})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.strong,{children:"Manifest and Segments"})," section, configure the following fields:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Output Selection"})," - MANIFESTS_AND_SEGMENTS"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Mode"})," - LIVE"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"TS File Mode"})," - SEGMENTED_FILES"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Segment Length"})," - 2"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The remaining settings should match the configuration below:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with output configuration complete",src:n(600).A+"",width:"1449",height:"830"})}),"\n",(0,i.jsxs)(t.p,{children:["Finally, we configure how AWS Elemental MediaLive updates the variant playlists: the variant playlists are derived from the master manifest by appending a ",(0,i.jsx)(t.em,{children:"Name modifier"})," at the end of the master playlist chosen name. For each variant playlist/output, add a descriptive modifier that tells us at a glance which playlist we are looking at. For example, each of the variant playlists in the example bitrate ladder will have ",(0,i.jsx)(t.code,{children:"_480p30"}),", ",(0,i.jsx)(t.code,{children:"_240p30"}),", and ",(0,i.jsx)(t.code,{children:"_720p30"})," as the ",(0,i.jsx)(t.em,{children:"Name Modifier"}),". Since we named the master manifest ",(0,i.jsx)(t.code,{children:"playlist.m3u8"}),", the resulting variant manifests will be named respectively ",(0,i.jsx)(t.code,{children:"playlist_480p30.m3u8"}),", ",(0,i.jsx)(t.code,{children:"playlist_240p30.m3u8"}),", and ",(0,i.jsx)(t.code,{children:"playlist_720p30.m3u8"}),". This naming convention will need to be specified in the CloudFront settings below."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with the name modifier configured for all outputs",src:n(4693).A+"",width:"1436",height:"819"})}),"\n",(0,i.jsxs)(t.p,{children:["Once everything is configured, hit the ",(0,i.jsx)(t.em,{children:"Create channel"})," button to create the encoder!"]}),"\n",(0,i.jsx)(t.h2,{id:"3-optimize-content-delivery-with-amazon-cloudfront",children:"3. Optimize content delivery with Amazon CloudFront"}),"\n",(0,i.jsx)(t.p,{children:"Amazon CloudFront is a Content Delivery Network (CDN) that ensures the live video streams are delivered quickly and reliably to viewers worldwide. In this step, we'll configure CloudFront to work with Momento Media Storage - optimizing latency, managing costs, and securing access."}),"\n",(0,i.jsx)(t.p,{children:"CloudFront will serve two key purposes in this workflow:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Reduce latency and costs by caching video segments across its Points of Presence (PoPs)."}),"\n",(0,i.jsx)(t.li,{children:"Secure access to the Momento origin by adding the appropriate authorization tokens to requests."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.a,{href:"/media-storage/core-concepts/segments",children:"Media segments"})," are assets that change infrequently. They represent 1-5 seconds of video, audio, or metadata that will not change once it's been generated by the encoder. These media assets are usually best cached by a CDN service like Amazon CloudFront across multiple PoPs located close to the end viewers for both ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/live-streaming/how-it-works",children:"live"})," and ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/video-on-demand/media-storage",children:"VOD"})," video workflows."]}),"\n",(0,i.jsxs)(t.p,{children:['While VOD workflows have HLS manifests that never change once they are created, HLS manifests in live video workflows are constantly recreated by the encoders to present the latest media segments, at the "live point". As a result, ',(0,i.jsx)(t.em,{children:"live HLS manifests should not be cached by a CDN for longer than the size of a media segment"}),". So we will ",(0,i.jsx)(t.strong,{children:"not cache the manifests"})," and instead hand them over the Momento origin, which is designed to manage frequently changing objects."]}),"\n",(0,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsx)(t.p,{children:"You can optimize retrieval of manifest files by specifying a short TTL in the appropriate CloudFront behavior."})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront",children:"Amazon CloudFront console"}),", create a CloudFront distribution that enables these rules through custom CloudFront behaviors."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console with the create distribution fields completed",src:n(72130).A+"",width:"1433",height:"885"})}),"\n",(0,i.jsxs)(t.p,{children:["The ",(0,i.jsx)(t.em,{children:"Origin domain"})," of the CloudFront distribution must be set as the ",(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," url we used to configure the MediaLive channel, with the ",(0,i.jsx)(t.em,{children:"Origin path"})," as ",(0,i.jsx)(t.code,{children:"/cache/"}),". Note the ",(0,i.jsx)(t.em,{children:"Origin path"})," field ",(0,i.jsx)(t.strong,{children:"is required for this workflow"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Since CloudFront is accessed by video players, which don't go through auth flows to obtain API keys or session tokens, we must set up the default policy to add an ",(0,i.jsx)(t.em,{children:"Authorization"})," header with ",(0,i.jsx)(t.code,{children:"player_api_key"})," for incoming requests. This enables CloudFront to automatically forward an API key to Momento, granting read-only access to the generated segments."]}),"\n",(0,i.jsxs)(t.p,{children:["You do not need to enable the ",(0,i.jsx)(t.em,{children:"Origin Shield"})," functionality of CloudFront, Momento takes care of it natively."]}),"\n",(0,i.jsxs)(t.p,{children:["For the ",(0,i.jsx)(t.strong,{children:"Web Application Firewall (WAF)"})," settings, select ",(0,i.jsx)(t.em,{children:"Do not enable security protections"})," for the demo."]}),"\n",(0,i.jsx)(t.p,{children:"Now we need to define the CloudFront behaviors for three types of objects read from the Momento origin server:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"The default behavior"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for media segments"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for variant playlists"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console listing the caching behaviors and their policies",src:n(74155).A+"",width:"1444",height:"527"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Default behavior"}),': This "behavior" is for items that are not part of the video origin workflow. We assume these objects will be changed frequently, so we won\'t cache them in CloudFront, using the a "CachingDisabled" policy. Configure the policy as outlined below.']}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for the default behavior",src:n(40021).A+"",width:"1446",height:"895"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Media segments behavior"}),': These files won\'t change after the encoder has sent them to the origin, so they are good candidates for being cached by CloudFront and its "CachingOptimized" policy. From the AWS MediaLive configuration, the segments that contain audio/video will always have the file extension ',(0,i.jsx)(t.code,{children:".ts"})," :"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for caching segments",src:n(24386).A+"",width:"1450",height:"864"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Variant playlists behavior"}),": These ",(0,i.jsx)(t.code,{children:"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 ",(0,i.jsx)(t.code,{children:"encoder_api_key"})," token query parameter in its URI. Since the default rules apply a different, conflicting value (",(0,i.jsx)(t.code,{children:"player_api_key"}),") in ",(0,i.jsx)(t.em,{children:"Authorization"})," header when requesting these segments, we need to define a behavior where the ",(0,i.jsx)(t.em,{children:"Authorization"})," header is dropped for these requests. To accomplish this, set the ",(0,i.jsx)(t.em,{children:"Origin request policy"})," to None."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for variant playlists",src:n(17118).A+"",width:"1450",height:"840"})}),"\n",(0,i.jsx)(t.h2,{id:"4-playback-and-troubleshooting",children:"4. Playback and troubleshooting"}),"\n",(0,i.jsxs)(t.p,{children:["With that, we're ready to stream! You can now point your favorite HLS player (in ",(0,i.jsx)(t.a,{href:"https://www.videolan.org/",children:"VLC media player"})," open a network stream and paste the .m3u8 path) to ",(0,i.jsx)(t.code,{children:"https://.CloudFront.net/playlist.m3u8"})," and play the live stream encoded by AWS Elemental MediaLive."]}),"\n",(0,i.jsx)(t.p,{children:"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."}),"\n",(0,i.jsx)(t.h3,{id:"medialive-and-momento",children:"MediaLive and Momento"}),"\n",(0,i.jsxs)(t.p,{children:["Verify the master manifest is accessible with ",(0,i.jsx)(t.code,{children:"player_api_key"})," and returns the variant playlists correctly. Use the following ",(0,i.jsx)(t.code,{children:"curl"})," command to test, or use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/caches/live-origin",children:"Momento console"})," to view data in the namespace."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-STREAM-INF:BANDWIDTH=2648800,AVERAGE-BANDWIDTH=1790800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=30.000\nplaylist_480p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=1394800,AVERAGE-BANDWIDTH=965800,CODECS="avc1.4d400d,mp4a.40.2",RESOLUTION=320x240,FRAME-RATE=30.000\nplaylist_240p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=4391200,AVERAGE-BANDWIDTH=2961200,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x720,FRAME-RATE=30.000\nplaylist_720p30.m3u8?ttl_seconds=3600\n'})}),"\n",(0,i.jsxs)(t.p,{children:["Verify that each variant playlist is accessible, and if you can download the last media segment listed in the variant playlists (aka ",(0,i.jsx)(t.em,{children:"the live point"}),"). Below are the ",(0,i.jsx)(t.code,{children:"curl"})," commands to view the 480p manifest and the live point."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist_480p30.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:2\n#EXT-X-MEDIA-SEQUENCE:891\n#EXTINF:2.00000,\nplaylist_480p30_00891.ts\n#EXTINF:2.00000,\nplaylist_480p30_00892.ts\n#EXTINF:2.00000,\n[...]\n#EXTINF:2.00000,\nplaylist_480p30_00939.ts\n#EXTINF:2.00000,\nplaylist_480p30_00940.ts\n\n$ curl -o test.ts "https:///cache/live-origin/playlist_480p30_00940.ts?token="\n'})}),"\n",(0,i.jsxs)(t.p,{children:["When viewing the live point, verify a ",(0,i.jsx)(t.code,{children:"test.ts"})," file is correctly downloaded and looks OK with your favorite test tool (",(0,i.jsx)(t.a,{href:"https://ffmpeg.org/ffprobe.html",children:"ffprobe"}),", ",(0,i.jsx)(t.a,{href:"https://mediaarea.net/en/MediaInfo",children:"mediainfo"}),", etc...)."]}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"encoder_api_key"})," or ",(0,i.jsx)(t.code,{children:"player_api_key"})," might not have the right access level to the namespace."]}),"\n",(0,i.jsxs)(t.li,{children:["AWS Elemental MediaLive isn't configured correctly or isn't running.","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Double check the URI provided in the ",(0,i.jsx)(t.em,{children:"Destination URL"})," field at the HLS output group level, and don't forget to add the query parameters ",(0,i.jsx)(t.code,{children:"&ttl_seconds=&role=origin"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"cloudfront",children:"CloudFront"}),"\n",(0,i.jsxs)(t.p,{children:["If everything looks correct in MediaLive and Momento, verify the requests from CloudFront. The distribution rules already embed an authorization header, so you don't need to add ",(0,i.jsx)(t.code,{children:"player_api_key"})," in the URIs. Verify that CloudFront inserts them properly."]}),"\n",(0,i.jsxs)(t.p,{children:["The three commands below produce the same results as the requests sent from the player through CloudFront to Momento Media Storage. Remember that the media segments listed in each variant playlist constantly change, so replace ",(0,i.jsx)(t.code,{children:""})," in the final command with a valid value from the fetched playlist:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https://.CloudFront.net/playlist.m3u8"\n\n$ curl "https://.CloudFront.net/playlist_480p30.m3u8"\n\n$ curl -o test.ts "https://.CloudFront.net/playlist_480p30_.ts"\n'})}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["The ",(0,i.jsx)(t.em,{children:"Authorization"})," header has not been correctly set to the ",(0,i.jsx)(t.code,{children:"player_api_key"})," when the CloudFront distribution was created."]}),"\n",(0,i.jsx)(t.li,{children:"A CloudFront behavior might be incorrectly set. Double check the file patterns and the associated caching policies."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"thats-it",children:"That's it!"}),"\n",(0,i.jsx)(t.p,{children:"Congratulations! You've successfully set up a live video streaming workflow using Momento Media Storage, AWS MediaLive, and Amazon CloudFront. This modern, scalable solution ensures low latency, reliability, and optimal performance for delivering live HLS streams."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Here's what you've learned:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Configured Momento Media Storage as a highly performant and cost-effective origin server."}),"\n",(0,i.jsx)(t.li,{children:"Set up AWS MediaLive to encode and push adaptive bitrate streams directly to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Optimized content delivery using CloudFront to reduce latency, manage costs, and secure playback access."}),"\n",(0,i.jsx)(t.li,{children:"Tested and troubleshot the setup to ensure seamless streaming from origin to viewers."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Next Steps"})}),"\n",(0,i.jsx)(t.p,{children:"Now that your live streaming workflow is up and running, consider exploring additional features and optimizations:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Learn about ",(0,i.jsx)(t.a,{href:"/media-storage/entitlements/about",children:"adding entitlements"})," to your workflow."]}),"\n",(0,i.jsxs)(t.li,{children:["Discover ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/capture/rtmp",children:"how to use ffmpeg and an RTMP stream"})," to stream to Momento."]}),"\n",(0,i.jsxs)(t.li,{children:["Add ",(0,i.jsx)(t.a,{href:"/media-storage/enhancements/live-reactions",children:"real-time reactions"})," to your streams."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"We can't wait to see what you build. Happy coding!"})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},74155:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-behaviors-92f08c82ed020eb64f587494e7f9954b.png"},40021:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-default-566d7cf82846c4605a1f7cbede42a0d0.png"},72130:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-origin-a1e9cbd1c710e1b9f52d8249986c6444.png"},17118:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-playlist-051452112d56ec21ffd125f52f727c8e.png"},24386:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-segments-76df56e726fd2007b4fb5a7e747d1b81.png"},71718:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/console-api-key-2-a4a7f23149d0dfbb3526c1fd7694ef90.png"},17793:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-hls-group-06db498b5dadcfa35c3e4e21c6447c2d.png"},4693:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-output-8013ead6ef592f79ec11c8d9a97edf5d.png"},600:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-segments-865e610dfd66c11fbaa5dae87166cf45.png"},28453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(96540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.7bb025e1.js b/assets/js/runtime~main.510514cf.js similarity index 99% rename from assets/js/runtime~main.7bb025e1.js rename to assets/js/runtime~main.510514cf.js index edaa7b501..76f2982bf 100644 --- a/assets/js/runtime~main.7bb025e1.js +++ b/assets/js/runtime~main.510514cf.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,d,c,f,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var d=t[e]={exports:{}};return b[e].call(d.exports,d,d.exports,r),d.exports}r.m=b,e=[],r.O=(a,d,c,f)=>{if(!d){var b=1/0;for(i=0;i=f)&&Object.keys(r.O).every((e=>r.O[e](d[o])))?d.splice(o--,1):(t=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[d,c,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,d({}),d([]),d(d)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=d(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var d in a)r.o(a,d)&&!r.o(e,d)&&Object.defineProperty(e,d,{enumerable:!0,get:a[d]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,d)=>(r.f[d](e,a),a)),[])),r.u=e=>"assets/js/"+({19:"1e62fb3c",45:"7ed88a61",111:"0ef94572",200:"9dd40145",211:"51e95708",238:"5cd8257c",338:"626fbfd1",356:"7e2f3cc4",416:"230e4609",594:"5e8c322a",633:"0aaa0fdc",670:"96422a8e",683:"bb880fe1",809:"ceed180f",874:"746edba2",904:"3afce2d3",957:"c141421f",1021:"664e9e92",1115:"207294ae",1134:"adf6c133",1235:"a7456010",1278:"c7250c61",1368:"3dc47e7b",1382:"8cb190db",1428:"657bd20a",1545:"0dede077",1567:"22dd74f7",1789:"66845bad",1817:"1dd5bc0a",1925:"660d4217",1928:"a5571990",1956:"f0e18a9a",2040:"270fc14c",2042:"411f0360",2049:"e9c2d7dd",2138:"1a4e3797",2154:"756c330b",2243:"934a9936",2290:"91fae9f8",2343:"90c95a67",2345:"af44c8f0",2426:"d970ddbc",2428:"f7970594",2576:"06b11012",2620:"69e4bc42",2734:"fbdf9d8d",2735:"1d77dea7",2856:"bbc7de84",2879:"0538e42e",2916:"4c716954",3153:"a621c737",3176:"40f6f508",3205:"255db43a",3226:"586df815",3276:"965abd06",3329:"df9e6c14",3367:"1a37f6c1",3426:"bbe01c24",3458:"62e32adb",3619:"1cd3ce65",3641:"ea3b032b",3715:"cab03762",3730:"9421dd9f",3748:"1d49aadc",3779:"a604b270",3840:"5121bb6d",3841:"3d0020de",3935:"a79b190c",3939:"8651edc2",4056:"bf1bf633",4114:"08de6c49",4118:"3d74beb4",4211:"123fd48f",4246:"c597145e",4247:"23349560",4257:"1eb6787d",4280:"eff70aea",4454:"dbe937be",4463:"830144b0",4481:"c33b4c48",4578:"9148fab2",4583:"1df93b7f",4599:"52644124",4610:"6c9527a4",4623:"53e56619",4639:"c70c9a94",4729:"d15f7fef",4734:"692fbf28",4768:"ac9107df",4857:"356b4e8c",4893:"80d715fe",4927:"aa621474",5035:"0b052ba4",5112:"20e927c7",5261:"e912cc25",5289:"11f5cea8",5311:"47f4431e",5325:"230f0e31",5452:"3e2087cc",5454:"30f74562",5527:"3ffcc902",5533:"d4495d4d",5586:"ed69384c",5607:"e4c3df98",5653:"1a7690d8",5677:"eeb8db93",5697:"afdab408",5742:"aba21aa0",5786:"68175c03",5843:"7f0698a5",6067:"c4958ee1",6165:"4c898cba",6201:"5d7e8f94",6219:"38a0f530",6246:"f72dc270",6337:"29a96ee3",6378:"68e330c3",6568:"a5cccfca",6582:"91e2c2e6",6613:"5a72a66d",6706:"39a01540",6782:"0ed5231c",6795:"723a8663",6853:"5576825f",6863:"9b8b7561",6906:"10cfd298",6923:"54d45a1f",6986:"00291e08",7098:"a7bd4aaa",7169:"3babf929",7213:"eb93e787",7238:"47127f80",7449:"8156e603",7459:"09801ae4",7468:"5f20be76",7494:"d2116cd8",7501:"3a099677",7598:"d6e3c147",7652:"3432cc94",7687:"ef265a61",7766:"b76bdc3b",7788:"d1d332ae",7817:"3889f620",7828:"83d9fcf2",7966:"574ab1b1",8045:"cd3b93ec",8137:"0fcb86af",8316:"213fabb0",8401:"17896441",8461:"d49f8296",8463:"4bda389e",8504:"ba370059",8528:"bdbb6afd",8552:"92b22ed5",8600:"5d94a398",8609:"11f888b8",8734:"8771a47d",8816:"3a932a39",8844:"9dd79f37",8947:"ee96381a",8957:"ed5ec39f",9031:"d5c4f0d2",9048:"a94703ab",9162:"63e7c654",9180:"8c9351cc",9204:"974c762a",9217:"b6eb2a39",9259:"6c8acfd7",9315:"71e23ad1",9342:"0d99fb32",9506:"75caad2d",9625:"81c3ec67",9647:"5e95c892",9659:"0fead853",9735:"4136d815",9746:"4660ec0e",9897:"b28ccf7c",9924:"f20fef3e",9957:"ba91e686",9964:"aa997ddf"}[e]||e)+"."+{19:"6cdeff30",45:"35ca2a36",111:"55e5f425",200:"be8f589a",211:"7cb9d210",238:"e203f50f",338:"4010a4be",356:"732a2537",375:"d50d4158",416:"b5265985",518:"92b1244d",594:"d6156b6c",633:"3a88c7ce",670:"cfe66b8c",683:"4772b388",802:"dcc6ccf3",809:"0ac91719",874:"d2c77908",904:"d6fc1dbf",957:"2136c8f3",1021:"6e6739d5",1115:"fd239b31",1134:"3390f2dd",1169:"883adae1",1176:"9a0aab73",1235:"74362299",1245:"c78fa6b0",1278:"619d7ba0",1368:"3c97e01b",1378:"da701329",1382:"d19525e5",1428:"9b8ec3eb",1451:"eeddb009",1497:"437ce67f",1545:"26b13350",1566:"167fceb0",1567:"0d7ef74a",1590:"51c68563",1789:"862393ca",1817:"a9a2fee4",1925:"41c9e04c",1928:"0cac3181",1956:"b95c6a49",2034:"c3263f23",2040:"97615caa",2042:"01221dbb",2049:"ab02173c",2130:"12d2e528",2138:"be1e2d7f",2154:"a4e41f42",2237:"0d5f378f",2243:"4c2388d2",2270:"4c7b7436",2290:"4040463e",2343:"74ae2acb",2345:"62870b75",2412:"f8f7fb53",2426:"79505920",2428:"d026faa7",2576:"b8c5b825",2620:"6ca05f0d",2734:"5094710f",2735:"de687993",2856:"dee9dc4e",2879:"08a15689",2916:"8a8300b3",2966:"00631f0d",3153:"1506d0fd",3176:"a2f9c2c3",3205:"eaad93aa",3226:"c75b8473",3276:"c80f4824",3329:"81b09b9e",3367:"83e25767",3426:"df0670ab",3458:"98b3fd3b",3619:"51854374",3641:"37bcccd2",3715:"8ee2fa53",3730:"7e618ddd",3748:"6c8945ff",3775:"5a596aa8",3779:"99cc5928",3840:"e5764917",3841:"23fe9706",3935:"b37722b0",3939:"ee85651d",4056:"c2cc6173",4114:"362628b8",4118:"26327f81",4211:"e9feb877",4246:"cc5c6d12",4247:"519aa0da",4257:"46b3c6a3",4280:"ccaccee4",4328:"624cf4bc",4454:"d7984e55",4463:"bf1d2b9a",4481:"f675bd42",4578:"650857ba",4583:"6c5e516f",4599:"b1039283",4610:"a16108be",4623:"72548cdb",4639:"25036b87",4729:"b557d4da",4734:"1b13c44d",4768:"562eb709",4857:"180d0143",4893:"61ea95cf",4927:"fa36483c",5035:"158c341b",5060:"8ee5bb77",5112:"e2c14778",5261:"a2ba148a",5289:"1debe39f",5311:"5a9f4dee",5325:"cf50dd52",5394:"f5b26d62",5452:"83334908",5454:"08e67285",5479:"58b8eec5",5481:"8227c55a",5527:"1a92f0e2",5530:"6db93ac5",5533:"8a524e90",5586:"597b0eb1",5607:"7fc710d8",5653:"3f714d9a",5677:"2da07148",5697:"7122bf99",5742:"21608be8",5786:"1731d2b0",5843:"796604ba",6067:"a95b88d0",6126:"1406159b",6136:"da5eb7dd",6165:"8737f7f7",6201:"174d86c9",6219:"912742c9",6246:"85293c7e",6258:"cde8a5ac",6337:"b5cde53c",6378:"32b09601",6530:"b54b8df1",6568:"a66770e6",6582:"2bcc1ff8",6613:"ce665e36",6643:"e39b8c6c",6706:"694e6e76",6782:"f1198de6",6795:"9660a755",6853:"7d01b1e6",6863:"1cb3806c",6906:"a0e51528",6923:"9360bf54",6986:"80a34c57",7098:"27fecdcf",7169:"b22202d6",7213:"1f3a2cac",7224:"1826f441",7238:"65632cb9",7256:"e4af7340",7441:"cfe73e9c",7449:"2b50e31b",7459:"4fcf0738",7468:"f8ff4282",7494:"47e07bd1",7501:"77d3850d",7598:"230047ce",7652:"4a215670",7687:"7c46976a",7766:"b49e1468",7788:"f4588b16",7817:"fd025389",7828:"119117ee",7966:"db859866",8035:"55fd1bcf",8045:"7f0afb03",8137:"f17790e1",8158:"1af3c3c7",8316:"1e57fa1d",8401:"583d9d50",8461:"58f478f2",8463:"ea277135",8504:"b447d718",8528:"b41f42ef",8552:"8bcf27d7",8554:"6c28e10d",8600:"da017428",8609:"c58a612c",8734:"678df369",8816:"7d243e64",8844:"7bfc9f9d",8913:"25f3c37e",8947:"a3cd04e2",8957:"a87f0f26",9031:"d554653b",9048:"2a1cd364",9162:"d0030c8f",9180:"22bd2138",9204:"06252903",9217:"a0268a3b",9259:"13fcf519",9315:"681b52cb",9342:"c820ce57",9471:"51471f3b",9506:"dc8ba9fa",9625:"ffd2bedc",9647:"23f53dcf",9659:"c2e81543",9672:"44a6baae",9735:"26730715",9746:"f71e5fa8",9763:"ccbd257f",9897:"6c41313d",9924:"239473b2",9957:"8907d5a9",9964:"1f0097bd"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},f="momento-docs:",r.l=(e,a,d,b)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==d)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var f=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),f&&f.forEach((e=>e(d))),a)return a(d)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",23349560:"4247",52644124:"4599","1e62fb3c":"19","7ed88a61":"45","0ef94572":"111","9dd40145":"200","51e95708":"211","5cd8257c":"238","626fbfd1":"338","7e2f3cc4":"356","230e4609":"416","5e8c322a":"594","0aaa0fdc":"633","96422a8e":"670",bb880fe1:"683",ceed180f:"809","746edba2":"874","3afce2d3":"904",c141421f:"957","664e9e92":"1021","207294ae":"1115",adf6c133:"1134",a7456010:"1235",c7250c61:"1278","3dc47e7b":"1368","8cb190db":"1382","657bd20a":"1428","0dede077":"1545","22dd74f7":"1567","66845bad":"1789","1dd5bc0a":"1817","660d4217":"1925",a5571990:"1928",f0e18a9a:"1956","270fc14c":"2040","411f0360":"2042",e9c2d7dd:"2049","1a4e3797":"2138","756c330b":"2154","934a9936":"2243","91fae9f8":"2290","90c95a67":"2343",af44c8f0:"2345",d970ddbc:"2426",f7970594:"2428","06b11012":"2576","69e4bc42":"2620",fbdf9d8d:"2734","1d77dea7":"2735",bbc7de84:"2856","0538e42e":"2879","4c716954":"2916",a621c737:"3153","40f6f508":"3176","255db43a":"3205","586df815":"3226","965abd06":"3276",df9e6c14:"3329","1a37f6c1":"3367",bbe01c24:"3426","62e32adb":"3458","1cd3ce65":"3619",ea3b032b:"3641",cab03762:"3715","9421dd9f":"3730","1d49aadc":"3748",a604b270:"3779","5121bb6d":"3840","3d0020de":"3841",a79b190c:"3935","8651edc2":"3939",bf1bf633:"4056","08de6c49":"4114","3d74beb4":"4118","123fd48f":"4211",c597145e:"4246","1eb6787d":"4257",eff70aea:"4280",dbe937be:"4454","830144b0":"4463",c33b4c48:"4481","9148fab2":"4578","1df93b7f":"4583","6c9527a4":"4610","53e56619":"4623",c70c9a94:"4639",d15f7fef:"4729","692fbf28":"4734",ac9107df:"4768","356b4e8c":"4857","80d715fe":"4893",aa621474:"4927","0b052ba4":"5035","20e927c7":"5112",e912cc25:"5261","11f5cea8":"5289","47f4431e":"5311","230f0e31":"5325","3e2087cc":"5452","30f74562":"5454","3ffcc902":"5527",d4495d4d:"5533",ed69384c:"5586",e4c3df98:"5607","1a7690d8":"5653",eeb8db93:"5677",afdab408:"5697",aba21aa0:"5742","68175c03":"5786","7f0698a5":"5843",c4958ee1:"6067","4c898cba":"6165","5d7e8f94":"6201","38a0f530":"6219",f72dc270:"6246","29a96ee3":"6337","68e330c3":"6378",a5cccfca:"6568","91e2c2e6":"6582","5a72a66d":"6613","39a01540":"6706","0ed5231c":"6782","723a8663":"6795","5576825f":"6853","9b8b7561":"6863","10cfd298":"6906","54d45a1f":"6923","00291e08":"6986",a7bd4aaa:"7098","3babf929":"7169",eb93e787:"7213","47127f80":"7238","8156e603":"7449","09801ae4":"7459","5f20be76":"7468",d2116cd8:"7494","3a099677":"7501",d6e3c147:"7598","3432cc94":"7652",ef265a61:"7687",b76bdc3b:"7766",d1d332ae:"7788","3889f620":"7817","83d9fcf2":"7828","574ab1b1":"7966",cd3b93ec:"8045","0fcb86af":"8137","213fabb0":"8316",d49f8296:"8461","4bda389e":"8463",ba370059:"8504",bdbb6afd:"8528","92b22ed5":"8552","5d94a398":"8600","11f888b8":"8609","8771a47d":"8734","3a932a39":"8816","9dd79f37":"8844",ee96381a:"8947",ed5ec39f:"8957",d5c4f0d2:"9031",a94703ab:"9048","63e7c654":"9162","8c9351cc":"9180","974c762a":"9204",b6eb2a39:"9217","6c8acfd7":"9259","71e23ad1":"9315","0d99fb32":"9342","75caad2d":"9506","81c3ec67":"9625","5e95c892":"9647","0fead853":"9659","4136d815":"9735","4660ec0e":"9746",b28ccf7c:"9897",f20fef3e:"9924",ba91e686:"9957",aa997ddf:"9964"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,d)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)d.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var f=new Promise(((d,f)=>c=e[a]=[d,f]));d.push(c[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(d=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var f=d&&("load"===d.type?"missing":d.type),b=d&&d.target&&d.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,d)=>{var c,f,b=d[0],t=d[1],o=d[2],n=0;if(b.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(d);n{"use strict";var e,a,d,c,f,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var d=t[e]={exports:{}};return b[e].call(d.exports,d,d.exports,r),d.exports}r.m=b,e=[],r.O=(a,d,c,f)=>{if(!d){var b=1/0;for(i=0;i=f)&&Object.keys(r.O).every((e=>r.O[e](d[o])))?d.splice(o--,1):(t=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[d,c,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,d({}),d([]),d(d)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=d(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var d in a)r.o(a,d)&&!r.o(e,d)&&Object.defineProperty(e,d,{enumerable:!0,get:a[d]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,d)=>(r.f[d](e,a),a)),[])),r.u=e=>"assets/js/"+({19:"1e62fb3c",45:"7ed88a61",111:"0ef94572",200:"9dd40145",211:"51e95708",238:"5cd8257c",338:"626fbfd1",356:"7e2f3cc4",416:"230e4609",594:"5e8c322a",633:"0aaa0fdc",670:"96422a8e",683:"bb880fe1",809:"ceed180f",874:"746edba2",904:"3afce2d3",957:"c141421f",1021:"664e9e92",1115:"207294ae",1134:"adf6c133",1235:"a7456010",1278:"c7250c61",1368:"3dc47e7b",1382:"8cb190db",1428:"657bd20a",1545:"0dede077",1567:"22dd74f7",1789:"66845bad",1817:"1dd5bc0a",1925:"660d4217",1928:"a5571990",1956:"f0e18a9a",2040:"270fc14c",2042:"411f0360",2049:"e9c2d7dd",2138:"1a4e3797",2154:"756c330b",2243:"934a9936",2290:"91fae9f8",2343:"90c95a67",2345:"af44c8f0",2426:"d970ddbc",2428:"f7970594",2576:"06b11012",2620:"69e4bc42",2734:"fbdf9d8d",2735:"1d77dea7",2856:"bbc7de84",2879:"0538e42e",2916:"4c716954",3153:"a621c737",3176:"40f6f508",3205:"255db43a",3226:"586df815",3276:"965abd06",3329:"df9e6c14",3367:"1a37f6c1",3426:"bbe01c24",3458:"62e32adb",3619:"1cd3ce65",3641:"ea3b032b",3715:"cab03762",3730:"9421dd9f",3748:"1d49aadc",3779:"a604b270",3840:"5121bb6d",3841:"3d0020de",3935:"a79b190c",3939:"8651edc2",4056:"bf1bf633",4114:"08de6c49",4118:"3d74beb4",4211:"123fd48f",4246:"c597145e",4247:"23349560",4257:"1eb6787d",4280:"eff70aea",4454:"dbe937be",4463:"830144b0",4481:"c33b4c48",4578:"9148fab2",4583:"1df93b7f",4599:"52644124",4610:"6c9527a4",4623:"53e56619",4639:"c70c9a94",4729:"d15f7fef",4734:"692fbf28",4768:"ac9107df",4857:"356b4e8c",4893:"80d715fe",4927:"aa621474",5035:"0b052ba4",5112:"20e927c7",5261:"e912cc25",5289:"11f5cea8",5311:"47f4431e",5325:"230f0e31",5452:"3e2087cc",5454:"30f74562",5527:"3ffcc902",5533:"d4495d4d",5586:"ed69384c",5607:"e4c3df98",5653:"1a7690d8",5677:"eeb8db93",5697:"afdab408",5742:"aba21aa0",5786:"68175c03",5843:"7f0698a5",6067:"c4958ee1",6165:"4c898cba",6201:"5d7e8f94",6219:"38a0f530",6246:"f72dc270",6337:"29a96ee3",6378:"68e330c3",6568:"a5cccfca",6582:"91e2c2e6",6613:"5a72a66d",6706:"39a01540",6782:"0ed5231c",6795:"723a8663",6853:"5576825f",6863:"9b8b7561",6906:"10cfd298",6923:"54d45a1f",6986:"00291e08",7098:"a7bd4aaa",7169:"3babf929",7213:"eb93e787",7238:"47127f80",7449:"8156e603",7459:"09801ae4",7468:"5f20be76",7494:"d2116cd8",7501:"3a099677",7598:"d6e3c147",7652:"3432cc94",7687:"ef265a61",7766:"b76bdc3b",7788:"d1d332ae",7817:"3889f620",7828:"83d9fcf2",7966:"574ab1b1",8045:"cd3b93ec",8137:"0fcb86af",8316:"213fabb0",8401:"17896441",8461:"d49f8296",8463:"4bda389e",8504:"ba370059",8528:"bdbb6afd",8552:"92b22ed5",8600:"5d94a398",8609:"11f888b8",8734:"8771a47d",8816:"3a932a39",8844:"9dd79f37",8947:"ee96381a",8957:"ed5ec39f",9031:"d5c4f0d2",9048:"a94703ab",9162:"63e7c654",9180:"8c9351cc",9204:"974c762a",9217:"b6eb2a39",9259:"6c8acfd7",9315:"71e23ad1",9342:"0d99fb32",9506:"75caad2d",9625:"81c3ec67",9647:"5e95c892",9659:"0fead853",9735:"4136d815",9746:"4660ec0e",9897:"b28ccf7c",9924:"f20fef3e",9957:"ba91e686",9964:"aa997ddf"}[e]||e)+"."+{19:"6cdeff30",45:"35ca2a36",111:"55e5f425",200:"be8f589a",211:"7cb9d210",238:"e203f50f",338:"4010a4be",356:"732a2537",375:"d50d4158",416:"b5265985",518:"92b1244d",594:"d6156b6c",633:"3a88c7ce",670:"cfe66b8c",683:"4772b388",802:"dcc6ccf3",809:"0ac91719",874:"d2c77908",904:"d6fc1dbf",957:"2136c8f3",1021:"6e6739d5",1115:"fd239b31",1134:"3390f2dd",1169:"883adae1",1176:"9a0aab73",1235:"74362299",1245:"c78fa6b0",1278:"619d7ba0",1368:"3c97e01b",1378:"da701329",1382:"d19525e5",1428:"9b8ec3eb",1451:"eeddb009",1497:"437ce67f",1545:"26b13350",1566:"167fceb0",1567:"0d7ef74a",1590:"51c68563",1789:"862393ca",1817:"a9a2fee4",1925:"41c9e04c",1928:"0cac3181",1956:"b95c6a49",2034:"c3263f23",2040:"97615caa",2042:"01221dbb",2049:"ab02173c",2130:"12d2e528",2138:"be1e2d7f",2154:"a4e41f42",2237:"0d5f378f",2243:"4c2388d2",2270:"4c7b7436",2290:"4040463e",2343:"74ae2acb",2345:"62870b75",2412:"f8f7fb53",2426:"79505920",2428:"d026faa7",2576:"b8c5b825",2620:"6ca05f0d",2734:"5094710f",2735:"de687993",2856:"dee9dc4e",2879:"08a15689",2916:"8a8300b3",2966:"00631f0d",3153:"1506d0fd",3176:"a2f9c2c3",3205:"eaad93aa",3226:"c75b8473",3276:"c80f4824",3329:"81b09b9e",3367:"83e25767",3426:"df0670ab",3458:"98b3fd3b",3619:"51854374",3641:"37bcccd2",3715:"8ee2fa53",3730:"7e618ddd",3748:"6c8945ff",3775:"5a596aa8",3779:"99cc5928",3840:"e5764917",3841:"23fe9706",3935:"b37722b0",3939:"ee85651d",4056:"c2cc6173",4114:"362628b8",4118:"26327f81",4211:"e9feb877",4246:"cc5c6d12",4247:"519aa0da",4257:"46b3c6a3",4280:"ccaccee4",4328:"624cf4bc",4454:"d7984e55",4463:"bf1d2b9a",4481:"f675bd42",4578:"650857ba",4583:"6c5e516f",4599:"b1039283",4610:"a16108be",4623:"72548cdb",4639:"25036b87",4729:"b557d4da",4734:"1b13c44d",4768:"562eb709",4857:"180d0143",4893:"61ea95cf",4927:"fa36483c",5035:"158c341b",5060:"8ee5bb77",5112:"e2c14778",5261:"a2ba148a",5289:"1debe39f",5311:"5a9f4dee",5325:"cf50dd52",5394:"f5b26d62",5452:"83334908",5454:"08e67285",5479:"58b8eec5",5481:"8227c55a",5527:"1a92f0e2",5530:"6db93ac5",5533:"8a524e90",5586:"597b0eb1",5607:"7fc710d8",5653:"3f714d9a",5677:"2da07148",5697:"63e2b33f",5742:"21608be8",5786:"1731d2b0",5843:"796604ba",6067:"a95b88d0",6126:"1406159b",6136:"da5eb7dd",6165:"8737f7f7",6201:"174d86c9",6219:"912742c9",6246:"85293c7e",6258:"cde8a5ac",6337:"b5cde53c",6378:"32b09601",6530:"b54b8df1",6568:"a66770e6",6582:"2bcc1ff8",6613:"ce665e36",6643:"e39b8c6c",6706:"694e6e76",6782:"f1198de6",6795:"9660a755",6853:"7d01b1e6",6863:"1cb3806c",6906:"a0e51528",6923:"9360bf54",6986:"80a34c57",7098:"27fecdcf",7169:"b22202d6",7213:"1f3a2cac",7224:"1826f441",7238:"65632cb9",7256:"e4af7340",7441:"cfe73e9c",7449:"2b50e31b",7459:"4fcf0738",7468:"f8ff4282",7494:"47e07bd1",7501:"77d3850d",7598:"230047ce",7652:"4a215670",7687:"7c46976a",7766:"b49e1468",7788:"f4588b16",7817:"fd025389",7828:"119117ee",7966:"db859866",8035:"55fd1bcf",8045:"7f0afb03",8137:"f17790e1",8158:"1af3c3c7",8316:"1e57fa1d",8401:"583d9d50",8461:"58f478f2",8463:"ea277135",8504:"b447d718",8528:"b41f42ef",8552:"8bcf27d7",8554:"6c28e10d",8600:"da017428",8609:"c58a612c",8734:"678df369",8816:"7d243e64",8844:"7bfc9f9d",8913:"25f3c37e",8947:"a3cd04e2",8957:"a87f0f26",9031:"d554653b",9048:"2a1cd364",9162:"d0030c8f",9180:"22bd2138",9204:"06252903",9217:"a0268a3b",9259:"13fcf519",9315:"681b52cb",9342:"c820ce57",9471:"51471f3b",9506:"dc8ba9fa",9625:"ffd2bedc",9647:"23f53dcf",9659:"c2e81543",9672:"44a6baae",9735:"26730715",9746:"f71e5fa8",9763:"ccbd257f",9897:"6c41313d",9924:"239473b2",9957:"8907d5a9",9964:"1f0097bd"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},f="momento-docs:",r.l=(e,a,d,b)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==d)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var f=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),f&&f.forEach((e=>e(d))),a)return a(d)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",23349560:"4247",52644124:"4599","1e62fb3c":"19","7ed88a61":"45","0ef94572":"111","9dd40145":"200","51e95708":"211","5cd8257c":"238","626fbfd1":"338","7e2f3cc4":"356","230e4609":"416","5e8c322a":"594","0aaa0fdc":"633","96422a8e":"670",bb880fe1:"683",ceed180f:"809","746edba2":"874","3afce2d3":"904",c141421f:"957","664e9e92":"1021","207294ae":"1115",adf6c133:"1134",a7456010:"1235",c7250c61:"1278","3dc47e7b":"1368","8cb190db":"1382","657bd20a":"1428","0dede077":"1545","22dd74f7":"1567","66845bad":"1789","1dd5bc0a":"1817","660d4217":"1925",a5571990:"1928",f0e18a9a:"1956","270fc14c":"2040","411f0360":"2042",e9c2d7dd:"2049","1a4e3797":"2138","756c330b":"2154","934a9936":"2243","91fae9f8":"2290","90c95a67":"2343",af44c8f0:"2345",d970ddbc:"2426",f7970594:"2428","06b11012":"2576","69e4bc42":"2620",fbdf9d8d:"2734","1d77dea7":"2735",bbc7de84:"2856","0538e42e":"2879","4c716954":"2916",a621c737:"3153","40f6f508":"3176","255db43a":"3205","586df815":"3226","965abd06":"3276",df9e6c14:"3329","1a37f6c1":"3367",bbe01c24:"3426","62e32adb":"3458","1cd3ce65":"3619",ea3b032b:"3641",cab03762:"3715","9421dd9f":"3730","1d49aadc":"3748",a604b270:"3779","5121bb6d":"3840","3d0020de":"3841",a79b190c:"3935","8651edc2":"3939",bf1bf633:"4056","08de6c49":"4114","3d74beb4":"4118","123fd48f":"4211",c597145e:"4246","1eb6787d":"4257",eff70aea:"4280",dbe937be:"4454","830144b0":"4463",c33b4c48:"4481","9148fab2":"4578","1df93b7f":"4583","6c9527a4":"4610","53e56619":"4623",c70c9a94:"4639",d15f7fef:"4729","692fbf28":"4734",ac9107df:"4768","356b4e8c":"4857","80d715fe":"4893",aa621474:"4927","0b052ba4":"5035","20e927c7":"5112",e912cc25:"5261","11f5cea8":"5289","47f4431e":"5311","230f0e31":"5325","3e2087cc":"5452","30f74562":"5454","3ffcc902":"5527",d4495d4d:"5533",ed69384c:"5586",e4c3df98:"5607","1a7690d8":"5653",eeb8db93:"5677",afdab408:"5697",aba21aa0:"5742","68175c03":"5786","7f0698a5":"5843",c4958ee1:"6067","4c898cba":"6165","5d7e8f94":"6201","38a0f530":"6219",f72dc270:"6246","29a96ee3":"6337","68e330c3":"6378",a5cccfca:"6568","91e2c2e6":"6582","5a72a66d":"6613","39a01540":"6706","0ed5231c":"6782","723a8663":"6795","5576825f":"6853","9b8b7561":"6863","10cfd298":"6906","54d45a1f":"6923","00291e08":"6986",a7bd4aaa:"7098","3babf929":"7169",eb93e787:"7213","47127f80":"7238","8156e603":"7449","09801ae4":"7459","5f20be76":"7468",d2116cd8:"7494","3a099677":"7501",d6e3c147:"7598","3432cc94":"7652",ef265a61:"7687",b76bdc3b:"7766",d1d332ae:"7788","3889f620":"7817","83d9fcf2":"7828","574ab1b1":"7966",cd3b93ec:"8045","0fcb86af":"8137","213fabb0":"8316",d49f8296:"8461","4bda389e":"8463",ba370059:"8504",bdbb6afd:"8528","92b22ed5":"8552","5d94a398":"8600","11f888b8":"8609","8771a47d":"8734","3a932a39":"8816","9dd79f37":"8844",ee96381a:"8947",ed5ec39f:"8957",d5c4f0d2:"9031",a94703ab:"9048","63e7c654":"9162","8c9351cc":"9180","974c762a":"9204",b6eb2a39:"9217","6c8acfd7":"9259","71e23ad1":"9315","0d99fb32":"9342","75caad2d":"9506","81c3ec67":"9625","5e95c892":"9647","0fead853":"9659","4136d815":"9735","4660ec0e":"9746",b28ccf7c:"9897",f20fef3e:"9924",ba91e686:"9957",aa997ddf:"9964"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,d)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)d.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var f=new Promise(((d,f)=>c=e[a]=[d,f]));d.push(c[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(d=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var f=d&&("load"===d.type?"missing":d.type),b=d&&d.target&&d.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,d)=>{var c,f,b=d[0],t=d[1],o=d[2],n=0;if(b.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(d);n - + diff --git a/cache.html b/cache.html index fd9d1cf60..bad4efc00 100644 --- a/cache.html +++ b/cache.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop.html b/cache/develop.html index e66ebc77c..1350d881c 100644 --- a/cache/develop.html +++ b/cache/develop.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference.html b/cache/develop/api-reference.html index d0b486e3d..1912471cc 100644 --- a/cache/develop/api-reference.html +++ b/cache/develop/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/auth.html b/cache/develop/api-reference/auth.html index f1bb1bfc2..4001eecaf 100644 --- a/cache/develop/api-reference/auth.html +++ b/cache/develop/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/collection-ttl.html b/cache/develop/api-reference/collection-ttl.html index 3d2c18a94..593f9e87c 100644 --- a/cache/develop/api-reference/collection-ttl.html +++ b/cache/develop/api-reference/collection-ttl.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/dictionary-collections.html b/cache/develop/api-reference/dictionary-collections.html index 591e37221..6a06e62b9 100644 --- a/cache/develop/api-reference/dictionary-collections.html +++ b/cache/develop/api-reference/dictionary-collections.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/http-api.html b/cache/develop/api-reference/http-api.html index 6b8b9dc0c..b2f57fa2a 100644 --- a/cache/develop/api-reference/http-api.html +++ b/cache/develop/api-reference/http-api.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/list-collections.html b/cache/develop/api-reference/list-collections.html index 087671fb3..380ad9a82 100644 --- a/cache/develop/api-reference/list-collections.html +++ b/cache/develop/api-reference/list-collections.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/response-objects.html b/cache/develop/api-reference/response-objects.html index eb932a024..0de4fa3c6 100644 --- a/cache/develop/api-reference/response-objects.html +++ b/cache/develop/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/set-collections.html b/cache/develop/api-reference/set-collections.html index 7c62907c5..073c35c1b 100644 --- a/cache/develop/api-reference/set-collections.html +++ b/cache/develop/api-reference/set-collections.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/api-reference/sorted-set-collections.html b/cache/develop/api-reference/sorted-set-collections.html index d06303406..1a40e6655 100644 --- a/cache/develop/api-reference/sorted-set-collections.html +++ b/cache/develop/api-reference/sorted-set-collections.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/authentication.html b/cache/develop/authentication.html index c24a162d3..fe4b2d002 100644 --- a/cache/develop/authentication.html +++ b/cache/develop/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/authentication/api-keys.html b/cache/develop/authentication/api-keys.html index e8b946149..1d4e647a1 100644 --- a/cache/develop/authentication/api-keys.html +++ b/cache/develop/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/authentication/permissions.html b/cache/develop/authentication/permissions.html index e18bcef90..f89cec0ee 100644 --- a/cache/develop/authentication/permissions.html +++ b/cache/develop/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/authentication/tokens.html b/cache/develop/authentication/tokens.html index 03ed9699d..d7c560eeb 100644 --- a/cache/develop/authentication/tokens.html +++ b/cache/develop/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/basics/client-configuration-objects.html b/cache/develop/basics/client-configuration-objects.html index 05f53b69e..c43252b1b 100644 --- a/cache/develop/basics/client-configuration-objects.html +++ b/cache/develop/basics/client-configuration-objects.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/basics/datatypes.html b/cache/develop/basics/datatypes.html index 63379735f..e9c38c5e2 100644 --- a/cache/develop/basics/datatypes.html +++ b/cache/develop/basics/datatypes.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/basics/error-handling-production-readiness.html b/cache/develop/basics/error-handling-production-readiness.html index 54a274a4d..101e38591 100644 --- a/cache/develop/basics/error-handling-production-readiness.html +++ b/cache/develop/basics/error-handling-production-readiness.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/guides/working-with-files-cache.html b/cache/develop/guides/working-with-files-cache.html index e6cb7539b..2f0745b9c 100644 --- a/cache/develop/guides/working-with-files-cache.html +++ b/cache/develop/guides/working-with-files-cache.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/guides/working-with-time-series-data.html b/cache/develop/guides/working-with-time-series-data.html index ea03b1121..6a3db9e6e 100644 --- a/cache/develop/guides/working-with-time-series-data.html +++ b/cache/develop/guides/working-with-time-series-data.html @@ -9,7 +9,7 @@ - + diff --git a/cache/develop/language-support.html b/cache/develop/language-support.html index f62ac37fc..b3700a53e 100644 --- a/cache/develop/language-support.html +++ b/cache/develop/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/cache/getting-started.html b/cache/getting-started.html index b3d93deb9..29e81b443 100644 --- a/cache/getting-started.html +++ b/cache/getting-started.html @@ -9,7 +9,7 @@ - + diff --git a/cache/how-to/rate-limiter.html b/cache/how-to/rate-limiter.html index b5e19d0fd..ab1b73aa2 100644 --- a/cache/how-to/rate-limiter.html +++ b/cache/how-to/rate-limiter.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/amazon-eventbridge.html b/cache/integrations/amazon-eventbridge.html index 464e893dc..1636a20eb 100644 --- a/cache/integrations/amazon-eventbridge.html +++ b/cache/integrations/amazon-eventbridge.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/aws-secrets-manager.html b/cache/integrations/aws-secrets-manager.html index fde043376..ae3389bce 100644 --- a/cache/integrations/aws-secrets-manager.html +++ b/cache/integrations/aws-secrets-manager.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/bulk-writing-from-redis-json-csv.html b/cache/integrations/bulk-writing-from-redis-json-csv.html index 08d69c1bf..106d70259 100644 --- a/cache/integrations/bulk-writing-from-redis-json-csv.html +++ b/cache/integrations/bulk-writing-from-redis-json-csv.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/cloudflare.html b/cache/integrations/cloudflare.html index 4ce19d567..1bb185a42 100644 --- a/cache/integrations/cloudflare.html +++ b/cache/integrations/cloudflare.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/deno.html b/cache/integrations/deno.html index 2283c26f9..f6146060d 100644 --- a/cache/integrations/deno.html +++ b/cache/integrations/deno.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/drupal-integration.html b/cache/integrations/drupal-integration.html index 38780d726..48db605f1 100644 --- a/cache/integrations/drupal-integration.html +++ b/cache/integrations/drupal-integration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/fastly.html b/cache/integrations/fastly.html index 2c38a49fe..edf86f3ec 100644 --- a/cache/integrations/fastly.html +++ b/cache/integrations/fastly.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/momento-cache-laravel-php.html b/cache/integrations/momento-cache-laravel-php.html index 154a77971..f1ff8ca65 100644 --- a/cache/integrations/momento-cache-laravel-php.html +++ b/cache/integrations/momento-cache-laravel-php.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/netlify-integration.html b/cache/integrations/netlify-integration.html index 69f0fd168..a6c124da5 100644 --- a/cache/integrations/netlify-integration.html +++ b/cache/integrations/netlify-integration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/redis-client-compatibility.html b/cache/integrations/redis-client-compatibility.html index 688d7ad8b..7b8ba9a34 100644 --- a/cache/integrations/redis-client-compatibility.html +++ b/cache/integrations/redis-client-compatibility.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/sequelize.html b/cache/integrations/sequelize.html index 4e8594075..bb1d229c4 100644 --- a/cache/integrations/sequelize.html +++ b/cache/integrations/sequelize.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/terraform.html b/cache/integrations/terraform.html index 0d830e380..6a2f987f2 100644 --- a/cache/integrations/terraform.html +++ b/cache/integrations/terraform.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/unity-integration.html b/cache/integrations/unity-integration.html index ec7171ea1..00a78f2e7 100644 --- a/cache/integrations/unity-integration.html +++ b/cache/integrations/unity-integration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/integrations/vercel-integration.html b/cache/integrations/vercel-integration.html index cc5da88e0..8f35e972c 100644 --- a/cache/integrations/vercel-integration.html +++ b/cache/integrations/vercel-integration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/introduction/common-caching-patterns.html b/cache/introduction/common-caching-patterns.html index 3aff1e1e9..6299e1deb 100644 --- a/cache/introduction/common-caching-patterns.html +++ b/cache/introduction/common-caching-patterns.html @@ -9,7 +9,7 @@ - + diff --git a/cache/introduction/common-caching-strategies.html b/cache/introduction/common-caching-strategies.html index e5a5219c8..3c99925d0 100644 --- a/cache/introduction/common-caching-strategies.html +++ b/cache/introduction/common-caching-strategies.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/courses/cache-concepts.html b/cache/learn/courses/cache-concepts.html index cfe8525a0..53f5206d6 100644 --- a/cache/learn/courses/cache-concepts.html +++ b/cache/learn/courses/cache-concepts.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html b/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html index a71ee50c5..b3c4cec72 100644 --- a/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html +++ b/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/courses/cache-concepts/common-caching-use-cases.html b/cache/learn/courses/cache-concepts/common-caching-use-cases.html index 3824df554..fa07240a4 100644 --- a/cache/learn/courses/cache-concepts/common-caching-use-cases.html +++ b/cache/learn/courses/cache-concepts/common-caching-use-cases.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/courses/cache-concepts/time-to-live.html b/cache/learn/courses/cache-concepts/time-to-live.html index 38f4c534d..7f3945471 100644 --- a/cache/learn/courses/cache-concepts/time-to-live.html +++ b/cache/learn/courses/cache-concepts/time-to-live.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/courses/cache-concepts/why-use-serverless-services.html b/cache/learn/courses/cache-concepts/why-use-serverless-services.html index 00a28f67a..8fca83ad3 100644 --- a/cache/learn/courses/cache-concepts/why-use-serverless-services.html +++ b/cache/learn/courses/cache-concepts/why-use-serverless-services.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/how-it-works/cache-eviction-vs-expiration.html b/cache/learn/how-it-works/cache-eviction-vs-expiration.html index 9f331e4d5..c0465fbc5 100644 --- a/cache/learn/how-it-works/cache-eviction-vs-expiration.html +++ b/cache/learn/how-it-works/cache-eviction-vs-expiration.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/how-it-works/expire-data-with-ttl.html b/cache/learn/how-it-works/expire-data-with-ttl.html index f56fef21e..8aa302a93 100644 --- a/cache/learn/how-it-works/expire-data-with-ttl.html +++ b/cache/learn/how-it-works/expire-data-with-ttl.html @@ -9,7 +9,7 @@ - + diff --git a/cache/learn/how-it-works/read-concern.html b/cache/learn/how-it-works/read-concern.html index 4572426b7..735e4521b 100644 --- a/cache/learn/how-it-works/read-concern.html +++ b/cache/learn/how-it-works/read-concern.html @@ -9,7 +9,7 @@ - + diff --git a/cache/limits.html b/cache/limits.html index 5ca9f02e8..12e722eda 100644 --- a/cache/limits.html +++ b/cache/limits.html @@ -9,7 +9,7 @@ - + diff --git a/cache/manage/metrics_in_the_console.html b/cache/manage/metrics_in_the_console.html index 50030cdb9..e1c2d5ba6 100644 --- a/cache/manage/metrics_in_the_console.html +++ b/cache/manage/metrics_in_the_console.html @@ -9,7 +9,7 @@ - + diff --git a/cache/patterns/api-caching.html b/cache/patterns/api-caching.html index 91b31f4a0..23433a7ad 100644 --- a/cache/patterns/api-caching.html +++ b/cache/patterns/api-caching.html @@ -9,7 +9,7 @@ - + diff --git a/cache/patterns/database-caching.html b/cache/patterns/database-caching.html index de09851f5..6414fca5b 100644 --- a/cache/patterns/database-caching.html +++ b/cache/patterns/database-caching.html @@ -9,7 +9,7 @@ - + diff --git a/cloud-linter.html b/cloud-linter.html index c1099d10e..133cae12b 100644 --- a/cloud-linter.html +++ b/cloud-linter.html @@ -9,7 +9,7 @@ - + diff --git a/cloud-linter/getting-started.html b/cloud-linter/getting-started.html index 18fac87c7..32ce54fb2 100644 --- a/cloud-linter/getting-started.html +++ b/cloud-linter/getting-started.html @@ -9,7 +9,7 @@ - + diff --git a/index.html b/index.html index b6ff1e811..46957d029 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ - + diff --git a/ja/404.html b/ja/404.html index e44763d6e..8be2a59d3 100644 --- a/ja/404.html +++ b/ja/404.html @@ -9,7 +9,7 @@ - + diff --git a/ja/account-sharing.html b/ja/account-sharing.html index 2cbbf806b..c3af1d5e1 100644 --- a/ja/account-sharing.html +++ b/ja/account-sharing.html @@ -9,7 +9,7 @@ - + diff --git a/ja/api.html b/ja/api.html index fc4338221..96e4ba0df 100644 --- a/ja/api.html +++ b/ja/api.html @@ -9,7 +9,7 @@ - + diff --git a/ja/api/authentication.html b/ja/api/authentication.html index d2821ff12..fcb815a9d 100644 --- a/ja/api/authentication.html +++ b/ja/api/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/ja/api/authentication/api-keys.html b/ja/api/authentication/api-keys.html index d100eb1aa..41c71c632 100644 --- a/ja/api/authentication/api-keys.html +++ b/ja/api/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/ja/api/authentication/permissions.html b/ja/api/authentication/permissions.html index 6e2257519..52206b293 100644 --- a/ja/api/authentication/permissions.html +++ b/ja/api/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/ja/api/authentication/tokens.html b/ja/api/authentication/tokens.html index 6c80ccf81..f0c8f8ef0 100644 --- a/ja/api/authentication/tokens.html +++ b/ja/api/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/ja/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png b/ja/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png new file mode 100644 index 000000000..6b04f7321 Binary files /dev/null and b/ja/assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png differ diff --git a/ja/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png b/ja/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png new file mode 100644 index 000000000..8397859b9 Binary files /dev/null and b/ja/assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png differ diff --git a/ja/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png b/ja/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png new file mode 100644 index 000000000..75ee32998 Binary files /dev/null and b/ja/assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png differ diff --git a/ja/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png b/ja/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png new file mode 100644 index 000000000..37f71ae37 Binary files /dev/null and b/ja/assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png differ diff --git a/ja/assets/js/afdab408.2026675a.js b/ja/assets/js/afdab408.2026675a.js deleted file mode 100644 index 2d49b62d9..000000000 --- a/ja/assets/js/afdab408.2026675a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmomento_docs=self.webpackChunkmomento_docs||[]).push([[5697],{38663:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=n(74848),o=n(28453);const s={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:"/ja/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:"Glass-to-glass latency",permalink:"/ja/media-storage/streaming/live-streaming/glass-to-glass-latency"}},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:"3. Optimize content delivery with Amazon CloudFront",id:"3-optimize-content-delivery-with-amazon-cloudfront",level:2},{value:"4. Playback and troubleshooting",id:"4-playback-and-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,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.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,i.jsxs)(t.p,{children:["Live video streaming requires a highly performant and scalable ",(0,i.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,i.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,i.jsx)(t.a,{href:"https://aws.amazon.com/medialive/",children:"AWS Elemental MediaLive"})," and delivered via ",(0,i.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,i.jsx)(t.a,{href:"/media-storage/performance/adaptive-bitrates/hls",children:"HLS streams"})," optimized for performance and reliability."]}),"\n",(0,i.jsx)(t.p,{children:"Here's what we'll cover:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Creating a storage namespace in Momento Media Storage to act as the origin server."}),"\n",(0,i.jsx)(t.li,{children:"Configuring AWS Elemental MediaLive to encode and push live content to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Setting up Amazon CloudFront to serve content to viewers with low latency."}),"\n",(0,i.jsx)(t.li,{children:"Testing and troubleshooting the setup to ensure smooth playback."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["In this tutorial, we will use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com",children:"Momento console"}),", but everything could be created and configured programmatically through ",(0,i.jsx)(t.a,{href:"/platform/sdks",children:"the Momento SDK"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"preparation",children:"Preparation"}),"\n",(0,i.jsx)(t.p,{children:"Before creating any resources, please determine the basic characteristics of the live video channel."}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.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,i.jsx)(t.code,{children:"1000 / 8 * 2 * 1.1 = 275 KB"}),"."]})}),"\n",(0,i.jsxs)(t.p,{children:["For the purposes of this tutorial, configure one live video channel for an ",(0,i.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,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"resolution"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"framerate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"bitrate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"segment size"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"720p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"2,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"850 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"480p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"1,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"500 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"240p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"750 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"250 KiB"})})]})]})]}),"\n",(0,i.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,i.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,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"Momento Console"})," once to initialize your account. Then, contact ",(0,i.jsx)(t.code,{children:"support@momentohq.com"})," or your support representative with the following information to create a storage namespace:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"account id"}),": Locate your account id in the dropdown in the upper right corner of the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"console"})," (",(0,i.jsx)(t.code,{children:"a-xxxxxxxxxxxx"}),")."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"namespace id"}),": The desired id for the new storage namespace. This guide uses ",(0,i.jsx)(t.code,{children:"live-origin"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"AWS region"}),": The AWS region for the new storage namespace. This guide uses ",(0,i.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,i.jsxs)(t.li,{children:[(0,i.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,i.jsx)(t.code,{children:"(850+500+250)Kib * 300/2.5 \u2248 200 MiB"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["While Momento Media Storage is in private preview, the Storage ",(0,i.jsx)(t.em,{children:"namespace"})," will be appear as a ",(0,i.jsx)(t.em,{children:"cache"})," in the console. This guide will use ",(0,i.jsx)(t.em,{children:"namespace"})," interchangeably with ",(0,i.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,i.jsxs)(t.p,{children:["Next, generate the API key that the encoder will use to securely write segment and manifest files to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. In the ",(0,i.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,i.jsx)(t.em,{children:"readwrite"})," access to the ",(0,i.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,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Momento console showing readwrite permissions for the live-origin namespace",src:n(71718).A+"",width:"1593",height:"936"})}),"\n",(0,i.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,i.jsx)(t.code,{children:"encoder_api_key"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Video players read the content pushed by encoders to Momento Media Storage via a ",(0,i.jsx)(t.strong,{children:"Content Delivery Network (CDN)"}),". As a security best practices, create a second API key with ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Use the same ",(0,i.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,i.jsx)(t.code,{children:"player_api_key"}),"."]}),"\n",(0,i.jsx)(t.admonition,{title:"Checking in",type:"info",children:(0,i.jsxs)(t.p,{children:["At the end of this step, you should have created two API keys: one that grants ",(0,i.jsx)(t.em,{children:"readwrite"})," access and one that ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Keep these handy to use in the upcoming steps."]})}),"\n",(0,i.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,i.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,i.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,i.jsxs)(t.p,{children:["MediaLive will act as the ",(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsxs)(t.p,{children:["For best performance, make sure the MediaLive service and the ",(0,i.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,i.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,i.jsxs)(t.p,{children:["Configure a MediaLive channel with one encoding pipeline that outputs to a single destination, the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. The output destination URL for the channel should follow this format:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https:///cache//playlist.m3u8?ttl_seconds=\n"})}),"\n",(0,i.jsx)(t.p,{children:"The variable placeholders are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," - Momento HTTP API region-specific endpoint (",(0,i.jsx)(t.a,{href:"/platform/regions",children:"see list"}),")"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"namespace_id"})," - ID of the namespace receiving uploaded segments"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"ttl"})," - number of seconds to retain the playlist and segments before deletion"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Applying the configuration from this tutorial, the resulting destination URL would be:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600\n"})}),"\n",(0,i.jsxs)(t.p,{children:["Next, expand the ",(0,i.jsx)(t.em,{children:"Credentials"})," section. Set ",(0,i.jsx)(t.em,{children:"Username"})," to ",(0,i.jsx)(t.code,{children:"momento"}),". Select ",(0,i.jsx)(t.strong,{children:"Create parameter"})," under ",(0,i.jsx)(t.em,{children:"Password"})," and follow the instructions to create a new parameter named ",(0,i.jsx)(t.code,{children:"/medialive/momento_api_key"})," that contains the previously-created encoder API key."]}),"\n",(0,i.jsxs)(t.p,{children:["Under ",(0,i.jsx)(t.em,{children:"CDN Settings"}),", select ",(0,i.jsx)(t.strong,{children:"HLS Akamai"}),". It is necessary to specify ",(0,i.jsx)(t.strong,{children:"HLS Akamai"})," so that MediaLive will properly transmit credentials with each request."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with channel configuration filled out",src:n(17793).A+"",width:"1338",height:"1436"})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.strong,{children:"Manifest and Segments"})," section, configure the following fields:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Output Selection"})," - MANIFESTS_AND_SEGMENTS"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Mode"})," - LIVE"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"TS File Mode"})," - SEGMENTED_FILES"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Segment Length"})," - 2"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The remaining settings should match the configuration below:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with output configuration complete",src:n(600).A+"",width:"1449",height:"830"})}),"\n",(0,i.jsxs)(t.p,{children:["Finally, we configure how AWS Elemental MediaLive updates the variant playlists: the variant playlists are derived from the master manifest by appending a ",(0,i.jsx)(t.em,{children:"Name modifier"})," at the end of the master playlist chosen name. For each variant playlist/output, add a descriptive modifier that tells us at a glance which playlist we are looking at. For example, each of the variant playlists in the example bitrate ladder will have ",(0,i.jsx)(t.code,{children:"_480p30"}),", ",(0,i.jsx)(t.code,{children:"_240p30"}),", and ",(0,i.jsx)(t.code,{children:"_720p30"})," as the ",(0,i.jsx)(t.em,{children:"Name Modifier"}),". Since we named the master manifest ",(0,i.jsx)(t.code,{children:"playlist.m3u8"}),", the resulting variant manifests will be named respectively ",(0,i.jsx)(t.code,{children:"playlist_480p30.m3u8"}),", ",(0,i.jsx)(t.code,{children:"playlist_240p30.m3u8"}),", and ",(0,i.jsx)(t.code,{children:"playlist_720p30.m3u8"}),". This naming convention will need to be specified in the CloudFront settings below."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with the name modifier configured for all outputs",src:n(4693).A+"",width:"1436",height:"819"})}),"\n",(0,i.jsxs)(t.p,{children:["Once everything is configured, hit the ",(0,i.jsx)(t.em,{children:"Create channel"})," button to create the encoder!"]}),"\n",(0,i.jsx)(t.h2,{id:"3-optimize-content-delivery-with-amazon-cloudfront",children:"3. Optimize content delivery with Amazon CloudFront"}),"\n",(0,i.jsx)(t.p,{children:"Amazon CloudFront is a Content Delivery Network (CDN) that ensures the live video streams are delivered quickly and reliably to viewers worldwide. In this step, we'll configure CloudFront to work with Momento Media Storage - optimizing latency, managing costs, and securing access."}),"\n",(0,i.jsx)(t.p,{children:"CloudFront will serve two key purposes in this workflow:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Reduce latency and costs by caching video segments across its Points of Presence (PoPs)."}),"\n",(0,i.jsx)(t.li,{children:"Secure access to the Momento origin by adding the appropriate authorization tokens to requests."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.a,{href:"/media-storage/core-concepts/segments",children:"Media segments"})," are assets that change infrequently. They represent 1-5 seconds of video, audio, or metadata that will not change once it's been generated by the encoder. These media assets are usually best cached by a CDN service like Amazon CloudFront across multiple PoPs located close to the end viewers for both ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/live-streaming/how-it-works",children:"live"})," and ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/video-on-demand/media-storage",children:"VOD"})," video workflows."]}),"\n",(0,i.jsxs)(t.p,{children:['While VOD workflows have HLS manifests that never change once they are created, HLS manifests in live video workflows are constantly recreated by the encoders to present the latest media segments, at the "live point". As a result, ',(0,i.jsx)(t.em,{children:"live HLS manifests should not be cached by a CDN for longer than the size of a media segment"}),". So we will ",(0,i.jsx)(t.strong,{children:"not cache the manifests"})," and instead hand them over the Momento origin, which is designed to manage frequently changing objects."]}),"\n",(0,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsx)(t.p,{children:"You can optimize retrieval of manifest files by specifying a short TTL in the appropriate CloudFront behavior."})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront",children:"Amazon CloudFront console"}),", create a CloudFront distribution that enables these rules through custom CloudFront behaviors."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console with the create distribution fields completed",src:n(72130).A+"",width:"1433",height:"885"})}),"\n",(0,i.jsxs)(t.p,{children:["The ",(0,i.jsx)(t.em,{children:"Origin domain"})," of the CloudFront distribution must be set as the ",(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," url we used to configure the MediaLive channel, with the ",(0,i.jsx)(t.em,{children:"Origin path"})," as ",(0,i.jsx)(t.code,{children:"/cache/"}),". Note the ",(0,i.jsx)(t.em,{children:"Origin path"})," field ",(0,i.jsx)(t.strong,{children:"is required for this workflow"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Since CloudFront is accessed by video players, which don't go through auth flows to obtain API keys or session tokens, we must set up the default policy to add an ",(0,i.jsx)(t.em,{children:"Authorization"})," header with ",(0,i.jsx)(t.code,{children:"player_api_key"})," for incoming requests. This enables CloudFront to automatically forward an API key to Momento, granting read-only access to the generated segments."]}),"\n",(0,i.jsxs)(t.p,{children:["You do not need to enable the ",(0,i.jsx)(t.em,{children:"Origin Shield"})," functionality of CloudFront, Momento takes care of it natively."]}),"\n",(0,i.jsxs)(t.p,{children:["For the ",(0,i.jsx)(t.strong,{children:"Web Application Firewall (WAF)"})," settings, select ",(0,i.jsx)(t.em,{children:"Do not enable security protections"})," for the demo."]}),"\n",(0,i.jsx)(t.p,{children:"Now we need to define the CloudFront behaviors for three types of objects read from the Momento origin server:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"The default behavior"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for media segments"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for variant playlists"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console listing the caching behaviors and their policies",src:n(74155).A+"",width:"1444",height:"527"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Default behavior"}),': This "behavior" is for items that are not part of the video origin workflow. We assume these objects will be changed frequently, so we won\'t cache them in CloudFront, using the a "CachingDisabled" policy. Configure the policy as outlined below.']}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for the default behavior",src:n(40021).A+"",width:"1446",height:"895"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Media segments behavior"}),': These files won\'t change after the encoder has sent them to the origin, so they are good candidates for being cached by CloudFront and its "CachingOptimized" policy. From the AWS MediaLive configuration, the segments that contain audio/video will always have the file extension ',(0,i.jsx)(t.code,{children:".ts"})," :"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for caching segments",src:n(24386).A+"",width:"1450",height:"864"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Variant playlists behavior"}),": These ",(0,i.jsx)(t.code,{children:"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 ",(0,i.jsx)(t.code,{children:"encoder_api_key"})," token query parameter in its URI. Since the default rules apply a different, conflicting value (",(0,i.jsx)(t.code,{children:"player_api_key"}),") in ",(0,i.jsx)(t.em,{children:"Authorization"})," header when requesting these segments, we need to define a behavior where the ",(0,i.jsx)(t.em,{children:"Authorization"})," header is dropped for these requests. To accomplish this, set the ",(0,i.jsx)(t.em,{children:"Origin request policy"})," to None."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for variant playlists",src:n(17118).A+"",width:"1450",height:"840"})}),"\n",(0,i.jsx)(t.h2,{id:"4-playback-and-troubleshooting",children:"4. Playback and troubleshooting"}),"\n",(0,i.jsxs)(t.p,{children:["With that, we're ready to stream! You can now point your favorite HLS player (in ",(0,i.jsx)(t.a,{href:"https://www.videolan.org/",children:"VLC media player"})," open a network stream and paste the .m3u8 path) to ",(0,i.jsx)(t.code,{children:"https://.CloudFront.net/playlist.m3u8"})," and play the live stream encoded by AWS Elemental MediaLive."]}),"\n",(0,i.jsx)(t.p,{children:"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."}),"\n",(0,i.jsx)(t.h3,{id:"medialive-and-momento",children:"MediaLive and Momento"}),"\n",(0,i.jsxs)(t.p,{children:["Verify the master manifest is accessible with ",(0,i.jsx)(t.code,{children:"player_api_key"})," and returns the variant playlists correctly. Use the following ",(0,i.jsx)(t.code,{children:"curl"})," command to test, or use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/caches/live-origin",children:"Momento console"})," to view data in the namespace."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-STREAM-INF:BANDWIDTH=2648800,AVERAGE-BANDWIDTH=1790800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=30.000\nplaylist_480p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=1394800,AVERAGE-BANDWIDTH=965800,CODECS="avc1.4d400d,mp4a.40.2",RESOLUTION=320x240,FRAME-RATE=30.000\nplaylist_240p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=4391200,AVERAGE-BANDWIDTH=2961200,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x720,FRAME-RATE=30.000\nplaylist_720p30.m3u8?ttl_seconds=3600\n'})}),"\n",(0,i.jsxs)(t.p,{children:["Verify that each variant playlist is accessible, and if you can download the last media segment listed in the variant playlists (aka ",(0,i.jsx)(t.em,{children:"the live point"}),"). Below are the ",(0,i.jsx)(t.code,{children:"curl"})," commands to view the 480p manifest and the live point."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist_480p30.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:2\n#EXT-X-MEDIA-SEQUENCE:891\n#EXTINF:2.00000,\nplaylist_480p30_00891.ts\n#EXTINF:2.00000,\nplaylist_480p30_00892.ts\n#EXTINF:2.00000,\n[...]\n#EXTINF:2.00000,\nplaylist_480p30_00939.ts\n#EXTINF:2.00000,\nplaylist_480p30_00940.ts\n\n$ curl -o test.ts "https:///cache/live-origin/playlist_480p30_00940.ts?token="\n'})}),"\n",(0,i.jsxs)(t.p,{children:["When viewing the live point, verify a ",(0,i.jsx)(t.code,{children:"test.ts"})," file is correctly downloaded and looks OK with your favorite test tool (",(0,i.jsx)(t.a,{href:"https://ffmpeg.org/ffprobe.html",children:"ffprobe"}),", ",(0,i.jsx)(t.a,{href:"https://mediaarea.net/en/MediaInfo",children:"mediainfo"}),", etc...)."]}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"encoder_api_key"})," or ",(0,i.jsx)(t.code,{children:"player_api_key"})," might not have the right access level to the namespace."]}),"\n",(0,i.jsxs)(t.li,{children:["AWS Elemental MediaLive isn't configured correctly or isn't running.","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Double check the URI provided in the ",(0,i.jsx)(t.em,{children:"Destination URL"})," field at the HLS output group level, and don't forget to add the query parameters ",(0,i.jsx)(t.code,{children:"&ttl_seconds=&role=origin"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"cloudfront",children:"CloudFront"}),"\n",(0,i.jsxs)(t.p,{children:["If everything looks correct in MediaLive and Momento, verify the requests from CloudFront. The distribution rules already embed an authorization header, so you don't need to add ",(0,i.jsx)(t.code,{children:"player_api_key"})," in the URIs. Verify that CloudFront inserts them properly."]}),"\n",(0,i.jsxs)(t.p,{children:["The three commands below produce the same results as the requests sent from the player through CloudFront to Momento Media Storage. Remember that the media segments listed in each variant playlist constantly change, so replace ",(0,i.jsx)(t.code,{children:""})," in the final command with a valid value from the fetched playlist:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https://.CloudFront.net/playlist.m3u8"\n\n$ curl "https://.CloudFront.net/playlist_480p30.m3u8"\n\n$ curl -o test.ts "https://.CloudFront.net/playlist_480p30_.ts"\n'})}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["The ",(0,i.jsx)(t.em,{children:"Authorization"})," header has not been correctly set to the ",(0,i.jsx)(t.code,{children:"player_api_key"})," when the CloudFront distribution was created."]}),"\n",(0,i.jsx)(t.li,{children:"A CloudFront behavior might be incorrectly set. Double check the file patterns and the associated caching policies."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"thats-it",children:"That's it!"}),"\n",(0,i.jsx)(t.p,{children:"Congratulations! You've successfully set up a live video streaming workflow using Momento Media Storage, AWS MediaLive, and Amazon CloudFront. This modern, scalable solution ensures low latency, reliability, and optimal performance for delivering live HLS streams."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Here's what you've learned:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Configured Momento Media Storage as a highly performant and cost-effective origin server."}),"\n",(0,i.jsx)(t.li,{children:"Set up AWS MediaLive to encode and push adaptive bitrate streams directly to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Optimized content delivery using CloudFront to reduce latency, manage costs, and secure playback access."}),"\n",(0,i.jsx)(t.li,{children:"Tested and troubleshot the setup to ensure seamless streaming from origin to viewers."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Next Steps"})}),"\n",(0,i.jsx)(t.p,{children:"Now that your live streaming workflow is up and running, consider exploring additional features and optimizations:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Learn about ",(0,i.jsx)(t.a,{href:"/media-storage/entitlements/about",children:"adding entitlements"})," to your workflow."]}),"\n",(0,i.jsxs)(t.li,{children:["Discover ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/capture/rtmp",children:"how to use ffmpeg and an RTMP stream"})," to stream to Momento."]}),"\n",(0,i.jsxs)(t.li,{children:["Add ",(0,i.jsx)(t.a,{href:"/media-storage/enhancements/live-reactions",children:"real-time reactions"})," to your streams."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"We can't wait to see what you build. Happy coding!"})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},74155:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-behaviors-92f08c82ed020eb64f587494e7f9954b.png"},40021:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-default-566d7cf82846c4605a1f7cbede42a0d0.png"},72130:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-origin-a1e9cbd1c710e1b9f52d8249986c6444.png"},17118:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-playlist-051452112d56ec21ffd125f52f727c8e.png"},24386:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-segments-76df56e726fd2007b4fb5a7e747d1b81.png"},71718:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/console-api-key-2-a4a7f23149d0dfbb3526c1fd7694ef90.png"},17793:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-hls-group-06db498b5dadcfa35c3e4e21c6447c2d.png"},4693:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-output-8013ead6ef592f79ec11c8d9a97edf5d.png"},600:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-segments-865e610dfd66c11fbaa5dae87166cf45.png"},28453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(96540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/ja/assets/js/afdab408.7d2c8f0f.js b/ja/assets/js/afdab408.7d2c8f0f.js new file mode 100644 index 000000000..09e2996d7 --- /dev/null +++ b/ja/assets/js/afdab408.7d2c8f0f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmomento_docs=self.webpackChunkmomento_docs||[]).push([[5697],{38663:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(74848),s=n(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:"/ja/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:"Glass-to-glass latency",permalink:"/ja/media-storage/streaming/live-streaming/glass-to-glass-latency"}},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,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.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,i.jsxs)(t.p,{children:["Live video streaming requires a highly performant and scalable ",(0,i.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,i.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,i.jsx)(t.a,{href:"https://aws.amazon.com/medialive/",children:"AWS Elemental MediaLive"})," and delivered via ",(0,i.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,i.jsx)(t.a,{href:"/media-storage/performance/adaptive-bitrates/hls",children:"HLS streams"})," optimized for performance and reliability."]}),"\n",(0,i.jsx)(t.p,{children:"Here's what we'll cover:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Creating a storage namespace in Momento Media Storage to act as the origin server."}),"\n",(0,i.jsx)(t.li,{children:"Configuring AWS Elemental MediaLive to encode and push live content to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Setting up Amazon CloudFront to serve content to viewers with low latency."}),"\n",(0,i.jsx)(t.li,{children:"Testing and troubleshooting the setup to ensure smooth playback."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["In this tutorial, we will use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com",children:"Momento console"}),", but everything could be created and configured programmatically through ",(0,i.jsx)(t.a,{href:"/platform/sdks",children:"the Momento SDK"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Prefer to learn through video?"})}),"\n",(0,i.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,i.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,i.jsx)(t.h2,{id:"preparation",children:"Preparation"}),"\n",(0,i.jsx)(t.p,{children:"Before creating any resources, please determine the basic characteristics of the live video channel."}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsxs)(t.p,{children:[(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.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,i.jsx)(t.code,{children:"1000 / 8 * 2 * 1.1 = 275 KB"}),"."]})}),"\n",(0,i.jsxs)(t.p,{children:["For the purposes of this tutorial, configure one live video channel for an ",(0,i.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,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"resolution"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"framerate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"bitrate"}),(0,i.jsx)(t.th,{style:{textAlign:"center"},children:"segment size"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"720p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"2,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"850 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"480p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"1,500 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"500 KiB"})})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"240p"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"30"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"750 kbps"})}),(0,i.jsx)(t.td,{style:{textAlign:"center"},children:(0,i.jsx)(t.code,{children:"250 KiB"})})]})]})]}),"\n",(0,i.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,i.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,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"Momento Console"})," once to initialize your account. Then, contact ",(0,i.jsx)(t.code,{children:"support@momentohq.com"})," or your support representative with the following information to create a storage namespace:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"account id"}),": Locate your account id in the dropdown in the upper right corner of the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/",children:"console"})," (",(0,i.jsx)(t.code,{children:"a-xxxxxxxxxxxx"}),")."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"namespace id"}),": The desired id for the new storage namespace. This guide uses ",(0,i.jsx)(t.code,{children:"live-origin"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"AWS region"}),": The AWS region for the new storage namespace. This guide uses ",(0,i.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,i.jsxs)(t.li,{children:[(0,i.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,i.jsx)(t.code,{children:"(850+500+250)Kib * 300/2.5 \u2248 200 MiB"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["While Momento Media Storage is in private preview, the Storage ",(0,i.jsx)(t.em,{children:"namespace"})," will be appear as a ",(0,i.jsx)(t.em,{children:"cache"})," in the console. This guide will use ",(0,i.jsx)(t.em,{children:"namespace"})," interchangeably with ",(0,i.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,i.jsxs)(t.p,{children:["Next, generate the API key that the encoder will use to securely write segment and manifest files to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. In the ",(0,i.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,i.jsx)(t.em,{children:"readwrite"})," access to the ",(0,i.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,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Momento console showing readwrite permissions for the live-origin namespace",src:n(71718).A+"",width:"1593",height:"936"})}),"\n",(0,i.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,i.jsx)(t.code,{children:"encoder_api_key"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Video players read the content pushed by encoders to Momento Media Storage via a ",(0,i.jsx)(t.strong,{children:"Content Delivery Network (CDN)"}),". As a security best practices, create a second API key with ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Use the same ",(0,i.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,i.jsx)(t.code,{children:"player_api_key"}),"."]}),"\n",(0,i.jsx)(t.admonition,{title:"Checking in",type:"info",children:(0,i.jsxs)(t.p,{children:["At the end of this step, you should have created two API keys: one that grants ",(0,i.jsx)(t.em,{children:"readwrite"})," access and one that ",(0,i.jsx)(t.em,{children:"readonly"})," access to the ",(0,i.jsx)(t.code,{children:"live-origin"})," namespace. Keep these handy to use in the upcoming steps."]})}),"\n",(0,i.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,i.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,i.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,i.jsxs)(t.p,{children:["MediaLive will act as the ",(0,i.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,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsxs)(t.p,{children:["For best performance, make sure the MediaLive service and the ",(0,i.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,i.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,i.jsx)(t.h3,{id:"channel-settings",children:"Channel settings"}),"\n",(0,i.jsxs)(t.p,{children:["First navigate to the ",(0,i.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,i.jsx)(t.em,{children:"Create role from template"})," to create an IAM role with the necessary permissions for encoding. After setup, select the ",(0,i.jsx)(t.code,{children:"MediaLiveAccessRole"})," role."]}),"\n",(0,i.jsxs)(t.p,{children:["We will not be using a channel template or changing any input specifications. However, we will be changing the ",(0,i.jsx)(t.strong,{children:"Channel class"})," to ",(0,i.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,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"MediaLive channel settings page fully configured",src:n(16471).A+"",width:"1269",height:"1111"})}),"\n",(0,i.jsx)(t.h3,{id:"input-attachments",children:"Input attachments"}),"\n",(0,i.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,i.jsx)(t.em,{children:"Add"})," button next to the ",(0,i.jsx)(t.strong,{children:"Input attachments"})," label, or ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/medialive/home#/inputs",children:"navigate directly"})," to the input list."]}),"\n",(0,i.jsxs)(t.p,{children:["If you already have an input you'd like to use, select it now. Otherwise, click on the ",(0,i.jsx)(t.em,{children:"Create input"})," button to create a new one. For our example, we will be streaming a copy of ",(0,i.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,i.jsx)(t.code,{children:"MP4"}),", and select an ",(0,i.jsx)(t.strong,{children:"Input class"})," of ",(0,i.jsx)(t.code,{children:"SINGLE_INPUT"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Put the publicly accessible url to the MP4 in the ",(0,i.jsx)(t.strong,{children:"Input source A"})," field, and leave all other fields alone. It should resemble the following:"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"MediaLive completed input page",src:n(30452).A+"",width:"1340",height:"1138"})}),"\n",(0,i.jsxs)(t.p,{children:["Once configured, hit the ",(0,i.jsx)(t.em,{children:"Create input"})," button, navigate back to the channel configuration page, and select the input we just created."]}),"\n",(0,i.jsx)(t.h3,{id:"output-groups",children:"Output groups"}),"\n",(0,i.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,i.jsx)(t.em,{children:"720p"}),", ",(0,i.jsx)(t.em,{children:"480p"}),", and ",(0,i.jsx)(t.em,{children:"240p"}),". To do this, we configure an output group for our channel."]}),"\n",(0,i.jsxs)(t.p,{children:["Click on the ",(0,i.jsx)(t.em,{children:"Add"})," button next to ",(0,i.jsx)(t.strong,{children:"Output groups"})," on the channel configuration page, select ",(0,i.jsx)(t.em,{children:"HLS"})," as the output group type, and hit the ",(0,i.jsx)(t.em,{children:"Confirm"})," button."]}),"\n",(0,i.jsxs)(t.p,{children:["The destination URL is going to be writing directly to the ",(0,i.jsx)(t.a,{href:"https://docs.momentohq.com/cache/develop/api-reference/http-api",children:"Momento HTTP API"})," using the ",(0,i.jsx)(t.code,{children:"encoder_api_key"})," we setup earlier. It should be in the following format:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https:///cache//playlist.m3u8?ttl_seconds=&role=origin\n"})}),"\n",(0,i.jsx)(t.p,{children:"The variable placeholders are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," - Momento HTTP API region-specific endpoint (",(0,i.jsx)(t.a,{href:"/platform/regions",children:"see list"}),")"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"namespace_id"})," - ID of the namespace receiving uploaded segments"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"ttl"})," - number of seconds to retain the playlist and segments before deletion"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsxs)(t.em,{children:["NOTE - notice the ",(0,i.jsx)(t.code,{children:"role=origin"})," query parameter at the end. This is required for MediaLive to publish segments!"]})}),"\n",(0,i.jsx)(t.p,{children:"As an example, your destination URL should look something like this:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https://api.cache.cell-4-us-west-2-1.prod.a.momentohq.com/cache/live-origin/playlist.m3u8?ttl_seconds=3600&role=origin\n"})}),"\n",(0,i.jsxs)(t.p,{children:["Next, expand the ",(0,i.jsx)(t.em,{children:"Credentials"})," section. Set ",(0,i.jsx)(t.em,{children:"Username"})," to ",(0,i.jsx)(t.code,{children:"momento"}),". Select ",(0,i.jsx)(t.strong,{children:"Create parameter"})," under ",(0,i.jsx)(t.em,{children:"Password"})," and follow the instructions to create a new parameter named ",(0,i.jsx)(t.code,{children:"/medialive/momento_api_key"})," that contains the previously-created encoder API key."]}),"\n",(0,i.jsxs)(t.p,{children:["Under ",(0,i.jsx)(t.em,{children:"CDN Settings"}),", select ",(0,i.jsx)(t.strong,{children:"HLS Akamai"}),". We use ",(0,i.jsx)(t.strong,{children:"HLS Akamai"})," so that MediaLive will properly transmit credentials with each request. There's a small quirk with the service when using ",(0,i.jsx)(t.em,{children:"HLS basic put"})," that omits the credentials."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with channel configuration filled out",src:n(17793).A+"",width:"1338",height:"1436"})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.strong,{children:"Manifest and Segments"})," section, configure the following fields:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Output Selection"})," - MANIFESTS_AND_SEGMENTS"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Mode"})," - LIVE"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"TS File Mode"})," - SEGMENTED_FILES"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Segment Length"})," - 2"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The remaining settings should match the configuration below:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with output configuration complete",src:n(600).A+"",width:"1449",height:"830"})}),"\n",(0,i.jsxs)(t.p,{children:["Finally, we configure how AWS Elemental MediaLive updates the variant playlists: the variant playlists are derived from the master manifest by appending a ",(0,i.jsx)(t.em,{children:"Name modifier"})," at the end of the master playlist chosen name. For each variant playlist/output, add a descriptive modifier that tells us at a glance which playlist we are looking at. For example, each of the variant playlists in the example bitrate ladder will have ",(0,i.jsx)(t.code,{children:"_480p30"}),", ",(0,i.jsx)(t.code,{children:"_240p30"}),", and ",(0,i.jsx)(t.code,{children:"_720p30"})," as the ",(0,i.jsx)(t.em,{children:"Name Modifier"}),". Since we named the master manifest ",(0,i.jsx)(t.code,{children:"playlist.m3u8"}),", the resulting variant manifests will be named respectively ",(0,i.jsx)(t.code,{children:"playlist_480p30.m3u8"}),", ",(0,i.jsx)(t.code,{children:"playlist_240p30.m3u8"}),", and ",(0,i.jsx)(t.code,{children:"playlist_720p30.m3u8"}),". This naming convention will need to be specified in the CloudFront settings below."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"AWS MediaLive console with the name modifier configured for all outputs",src:n(4693).A+"",width:"1436",height:"819"})}),"\n",(0,i.jsxs)(t.p,{children:["Once everything is configured, hit the ",(0,i.jsx)(t.em,{children:"Create channel"})," button to create the encoder!"]}),"\n",(0,i.jsx)(t.h2,{id:"3-optimize-content-delivery-with-amazon-cloudfront",children:"3. Optimize content delivery with Amazon CloudFront"}),"\n",(0,i.jsx)(t.p,{children:"Amazon CloudFront is a Content Delivery Network (CDN) that ensures the live video streams are delivered quickly and reliably to viewers worldwide. In this step, we'll configure CloudFront to work with Momento Media Storage - optimizing latency, managing costs, and securing access."}),"\n",(0,i.jsx)(t.p,{children:"CloudFront will serve two key purposes in this workflow:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Reduce latency and costs by caching video segments across its Points of Presence (PoPs)."}),"\n",(0,i.jsx)(t.li,{children:"Secure access to the Momento origin by adding the appropriate authorization tokens to requests."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.a,{href:"/media-storage/core-concepts/segments",children:"Media segments"})," are assets that change infrequently. They represent 1-5 seconds of video, audio, or metadata that will not change once it's been generated by the encoder. These media assets are usually best cached by a CDN service like Amazon CloudFront across multiple PoPs located close to the end viewers for both ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/live-streaming/how-it-works",children:"live"})," and ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/video-on-demand/media-storage",children:"VOD"})," video workflows."]}),"\n",(0,i.jsxs)(t.p,{children:['While VOD workflows have HLS manifests that never change once they are created, HLS manifests in live video workflows are constantly recreated by the encoders to present the latest media segments, at the "live point". As a result, ',(0,i.jsx)(t.em,{children:"live HLS manifests should not be cached by a CDN for longer than the size of a media segment"}),". So we will ",(0,i.jsx)(t.strong,{children:"not cache the manifests"})," and instead hand them over the Momento origin, which is designed to manage frequently changing objects."]}),"\n",(0,i.jsx)(t.admonition,{type:"tip",children:(0,i.jsx)(t.p,{children:"You can optimize retrieval of manifest files by specifying a short TTL in the appropriate CloudFront behavior."})}),"\n",(0,i.jsxs)(t.p,{children:["In the ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront",children:"Amazon CloudFront console"}),", create a CloudFront distribution that enables these rules through custom CloudFront behaviors."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console with the create distribution fields completed",src:n(72130).A+"",width:"1433",height:"885"})}),"\n",(0,i.jsxs)(t.p,{children:["The ",(0,i.jsx)(t.em,{children:"Origin domain"})," of the CloudFront distribution must be set as the ",(0,i.jsx)(t.code,{children:"momento_rest_endpoint"})," url we used to configure the MediaLive channel, with the ",(0,i.jsx)(t.em,{children:"Origin path"})," as ",(0,i.jsx)(t.code,{children:"/cache/"}),". Note the ",(0,i.jsx)(t.em,{children:"Origin path"})," field ",(0,i.jsx)(t.strong,{children:"is required for this workflow"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Since CloudFront is accessed by video players, which don't go through auth flows to obtain API keys or session tokens, we must set up the default policy to add an ",(0,i.jsx)(t.em,{children:"Authorization"})," header with ",(0,i.jsx)(t.code,{children:"player_api_key"})," for incoming requests. This enables CloudFront to automatically forward an API key to Momento, granting read-only access to the generated segments."]}),"\n",(0,i.jsxs)(t.p,{children:["You do not need to enable the ",(0,i.jsx)(t.em,{children:"Origin Shield"})," functionality of CloudFront, Momento takes care of it natively."]}),"\n",(0,i.jsxs)(t.p,{children:["For the ",(0,i.jsx)(t.strong,{children:"Web Application Firewall (WAF)"})," settings, select ",(0,i.jsx)(t.em,{children:"Do not enable security protections"})," for the demo."]}),"\n",(0,i.jsx)(t.p,{children:"Now we need to define the CloudFront behaviors for three types of objects read from the Momento origin server:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"The default behavior"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for media segments"}),"\n",(0,i.jsx)(t.li,{children:"The behavior for variant playlists"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront console listing the caching behaviors and their policies",src:n(74155).A+"",width:"1444",height:"527"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Default behavior"}),': This "behavior" is for items that are not part of the video origin workflow. We assume these objects will be changed frequently, so we won\'t cache them in CloudFront, using the a "CachingDisabled" policy. Configure the policy as outlined below.']}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for the default behavior",src:n(40021).A+"",width:"1446",height:"895"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Media segments behavior"}),': These files won\'t change after the encoder has sent them to the origin, so they are good candidates for being cached by CloudFront and its "CachingOptimized" policy. From the AWS MediaLive configuration, the segments that contain audio/video will always have the file extension ',(0,i.jsx)(t.code,{children:".ts"})," :"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for caching segments",src:n(24386).A+"",width:"1450",height:"864"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Variant playlists behavior"}),": These ",(0,i.jsx)(t.code,{children:"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 ",(0,i.jsx)(t.code,{children:"encoder_api_key"})," token query parameter in its URI. Since the default rules apply a different, conflicting value (",(0,i.jsx)(t.code,{children:"player_api_key"}),") in ",(0,i.jsx)(t.em,{children:"Authorization"})," header when requesting these segments, we need to define a behavior where the ",(0,i.jsx)(t.em,{children:"Authorization"})," header is dropped for these requests. To accomplish this, set the ",(0,i.jsx)(t.em,{children:"Origin request policy"})," to None."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CloudFront behavior for variant playlists",src:n(17118).A+"",width:"1450",height:"840"})}),"\n",(0,i.jsx)(t.h2,{id:"4-starting-the-stream",children:"4. Starting the stream"}),"\n",(0,i.jsxs)(t.p,{children:["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 ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/medialive/home#/channels",children:"channel we created"})," and hit the ",(0,i.jsx)(t.strong,{children:"Start"})," button. After a few moments, your channel will be broadcasting the video!"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"MediaLive channel in a playing status",src:n(47728).A+"",width:"1343",height:"627"})}),"\n",(0,i.jsxs)(t.p,{children:["That's it, the stream is active and will be creating segments and uploading them to our ",(0,i.jsx)(t.code,{children:"live-origin"})," cache. Now let's see it in action."]}),"\n",(0,i.jsx)(t.h2,{id:"5-watching-the-stream",children:"5. Watching the stream"}),"\n",(0,i.jsxs)(t.p,{children:["If you already have a compatible media player like ",(0,i.jsx)(t.a,{href:"https://www.videolan.org/",children:"VLC media player"})," that accepts an HLS playlist, great! If you'd rather use an online player, you can navigate to ",(0,i.jsx)(t.a,{href:"https://livepush.io/hlsplayer/index.html",children:"Livepush.io"})," for testing purposes."]}),"\n",(0,i.jsxs)(t.p,{children:["To get the url of our livestream, we need to get the distribution id of our CloudFront distribution. Navigate to the ",(0,i.jsx)(t.a,{href:"https://console.aws.amazon.com/cloudfront/v4/home#/distributions",children:"CloudFront distribution page"})," to find it. Once you have it, the url to our playlist is in the following format:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"https://.CloudFront.net/playlist.m3u8\n"})}),"\n",(0,i.jsx)(t.p,{children:"You can put this url in the player to start watching your stream!"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"HLS player streaming our content",src:n(12222).A+"",width:"970",height:"650"})}),"\n",(0,i.jsx)(t.h2,{id:"6-troubleshooting",children:"6. Troubleshooting"}),"\n",(0,i.jsx)(t.p,{children:"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."}),"\n",(0,i.jsx)(t.h3,{id:"medialive-and-momento",children:"MediaLive and Momento"}),"\n",(0,i.jsxs)(t.p,{children:["Verify the master manifest is accessible with ",(0,i.jsx)(t.code,{children:"player_api_key"})," and returns the variant playlists correctly. Use the following ",(0,i.jsx)(t.code,{children:"curl"})," command to test, or use the ",(0,i.jsx)(t.a,{href:"https://console.gomomento.com/caches/live-origin",children:"Momento console"})," to view data in the namespace."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-STREAM-INF:BANDWIDTH=2648800,AVERAGE-BANDWIDTH=1790800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=30.000\nplaylist_480p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=1394800,AVERAGE-BANDWIDTH=965800,CODECS="avc1.4d400d,mp4a.40.2",RESOLUTION=320x240,FRAME-RATE=30.000\nplaylist_240p30.m3u8?ttl_seconds=3600\n#EXT-X-STREAM-INF:BANDWIDTH=4391200,AVERAGE-BANDWIDTH=2961200,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x720,FRAME-RATE=30.000\nplaylist_720p30.m3u8?ttl_seconds=3600\n'})}),"\n",(0,i.jsxs)(t.p,{children:["Verify that each variant playlist is accessible, and if you can download the last media segment listed in the variant playlists (aka ",(0,i.jsx)(t.em,{children:"the live point"}),"). Below are the ",(0,i.jsx)(t.code,{children:"curl"})," commands to view the 480p manifest and the live point."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https:///cache/live-origin/playlist_480p30.m3u8?token="\n\n#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:2\n#EXT-X-MEDIA-SEQUENCE:891\n#EXTINF:2.00000,\nplaylist_480p30_00891.ts\n#EXTINF:2.00000,\nplaylist_480p30_00892.ts\n#EXTINF:2.00000,\n[...]\n#EXTINF:2.00000,\nplaylist_480p30_00939.ts\n#EXTINF:2.00000,\nplaylist_480p30_00940.ts\n\n$ curl -o test.ts "https:///cache/live-origin/playlist_480p30_00940.ts?token="\n'})}),"\n",(0,i.jsxs)(t.p,{children:["When viewing the live point, verify a ",(0,i.jsx)(t.code,{children:"test.ts"})," file is correctly downloaded and looks OK with your favorite test tool (",(0,i.jsx)(t.a,{href:"https://ffmpeg.org/ffprobe.html",children:"ffprobe"}),", ",(0,i.jsx)(t.a,{href:"https://mediaarea.net/en/MediaInfo",children:"mediainfo"}),", etc...)."]}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"encoder_api_key"})," or ",(0,i.jsx)(t.code,{children:"player_api_key"})," might not have the right access level to the namespace."]}),"\n",(0,i.jsxs)(t.li,{children:["AWS Elemental MediaLive isn't configured correctly or isn't running.","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Double check the URI provided in the ",(0,i.jsx)(t.em,{children:"Destination URL"})," field at the HLS output group level, and don't forget to add the query parameters ",(0,i.jsx)(t.code,{children:"&ttl_seconds=&role=origin"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"cloudfront",children:"CloudFront"}),"\n",(0,i.jsxs)(t.p,{children:["If everything looks correct in MediaLive and Momento, verify the requests from CloudFront. The distribution rules already embed an authorization header, so you don't need to add ",(0,i.jsx)(t.code,{children:"player_api_key"})," in the URIs. Verify that CloudFront inserts them properly."]}),"\n",(0,i.jsxs)(t.p,{children:["The three commands below produce the same results as the requests sent from the player through CloudFront to Momento Media Storage. Remember that the media segments listed in each variant playlist constantly change, so replace ",(0,i.jsx)(t.code,{children:""})," in the final command with a valid value from the fetched playlist:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'$ curl "https://.CloudFront.net/playlist.m3u8"\n\n$ curl "https://.CloudFront.net/playlist_480p30.m3u8"\n\n$ curl -o test.ts "https://.CloudFront.net/playlist_480p30_.ts"\n'})}),"\n",(0,i.jsx)(t.p,{children:"If any of these steps fails, usual suspects are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["The ",(0,i.jsx)(t.em,{children:"Authorization"})," header has not been correctly set to the ",(0,i.jsx)(t.code,{children:"player_api_key"})," when the CloudFront distribution was created."]}),"\n",(0,i.jsx)(t.li,{children:"A CloudFront behavior might be incorrectly set. Double check the file patterns and the associated caching policies."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"thats-it",children:"That's it!"}),"\n",(0,i.jsx)(t.p,{children:"Congratulations! You've successfully set up a live video streaming workflow using Momento Media Storage, AWS MediaLive, and Amazon CloudFront. This modern, scalable solution ensures low latency, reliability, and optimal performance for delivering live HLS streams."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Here's what you've learned:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Configured Momento Media Storage as a highly performant and cost-effective origin server."}),"\n",(0,i.jsx)(t.li,{children:"Set up AWS MediaLive to encode and push adaptive bitrate streams directly to Momento."}),"\n",(0,i.jsx)(t.li,{children:"Optimized content delivery using CloudFront to reduce latency, manage costs, and secure playback access."}),"\n",(0,i.jsx)(t.li,{children:"Tested and troubleshot the setup to ensure seamless streaming from origin to viewers."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Next Steps"})}),"\n",(0,i.jsx)(t.p,{children:"Now that your live streaming workflow is up and running, consider exploring additional features and optimizations:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Learn about ",(0,i.jsx)(t.a,{href:"/media-storage/entitlements/about",children:"adding entitlements"})," to your workflow."]}),"\n",(0,i.jsxs)(t.li,{children:["Discover ",(0,i.jsx)(t.a,{href:"/media-storage/streaming/capture/rtmp",children:"how to use ffmpeg and an RTMP stream"})," to stream to Momento."]}),"\n",(0,i.jsxs)(t.li,{children:["Add ",(0,i.jsx)(t.a,{href:"/media-storage/enhancements/live-reactions",children:"real-time reactions"})," to your streams."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"We can't wait to see what you build. Happy coding!"})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},74155:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-behaviors-92f08c82ed020eb64f587494e7f9954b.png"},40021:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-default-566d7cf82846c4605a1f7cbede42a0d0.png"},72130:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-origin-a1e9cbd1c710e1b9f52d8249986c6444.png"},17118:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-playlist-051452112d56ec21ffd125f52f727c8e.png"},24386:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/cloudfront-segments-76df56e726fd2007b4fb5a7e747d1b81.png"},71718:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/console-api-key-2-a4a7f23149d0dfbb3526c1fd7694ef90.png"},12222:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/hls-player-39988b45026daf5bedb5fcb11dd38170.png"},47728:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-channel-playing-6b5d71f8d44c1220b1287783a640cb56.png"},16471:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-channel-settings-b64f02e72b5ec37d26b680c3cf50413b.png"},17793:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-hls-group-06db498b5dadcfa35c3e4e21c6447c2d.png"},30452:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-input-settings-9769919d1c0b7a7c673ff19bf8ba5df2.png"},4693:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-output-8013ead6ef592f79ec11c8d9a97edf5d.png"},600:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/medialive-segments-865e610dfd66c11fbaa5dae87166cf45.png"},28453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(96540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/ja/assets/js/runtime~main.2d956e7a.js b/ja/assets/js/runtime~main.2af0e730.js similarity index 99% rename from ja/assets/js/runtime~main.2d956e7a.js rename to ja/assets/js/runtime~main.2af0e730.js index 8fd7b27d5..996967c8b 100644 --- a/ja/assets/js/runtime~main.2d956e7a.js +++ b/ja/assets/js/runtime~main.2af0e730.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,b,f,d,c={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var b=t[e]={exports:{}};return c[e].call(b.exports,b,b.exports,r),b.exports}r.m=c,e=[],r.O=(a,b,f,d)=>{if(!b){var c=1/0;for(i=0;i=d)&&Object.keys(r.O).every((e=>r.O[e](b[o])))?b.splice(o--,1):(t=!1,d0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[b,f,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var c={};a=a||[null,b({}),b([]),b(b)];for(var t=2&f&&e;"object"==typeof t&&!~a.indexOf(t);t=b(t))Object.getOwnPropertyNames(t).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,r.d(d,c),d},r.d=(e,a)=>{for(var b in a)r.o(a,b)&&!r.o(e,b)&&Object.defineProperty(e,b,{enumerable:!0,get:a[b]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,b)=>(r.f[b](e,a),a)),[])),r.u=e=>"assets/js/"+({54:"700ba566",164:"abfc53e0",184:"ae2ccdab",245:"dc01436a",282:"fab06213",311:"924df60e",338:"626fbfd1",362:"06da040b",559:"2552e03d",585:"ca10f696",587:"4b93b5c4",592:"93b48d41",594:"5e8c322a",602:"b817e55f",633:"0aaa0fdc",670:"96422a8e",806:"7df93f80",939:"6481fae3",957:"c141421f",976:"50f05764",1051:"c6522e74",1064:"7b7fffbe",1081:"24d265c4",1098:"0cddfb06",1182:"1dcf9a29",1205:"d08db822",1235:"a7456010",1434:"7abaa3fd",1452:"4c71f648",1464:"18ef01d0",1487:"c3af9f28",1494:"bd4bc387",1841:"9baec6c7",1955:"f6ccc656",1959:"fa2e647c",1963:"e0164697",1969:"67b91739",2024:"d7c924a9",2030:"36fdba0c",2090:"5d17f0bf",2138:"1a4e3797",2175:"78d83c18",2188:"dd75dd3b",2364:"b6dfeff2",2366:"b88618a5",2383:"96e91e0a",2398:"7a451a59",2524:"514ee296",2586:"c4d4e1e1",2700:"8eca53d6",2701:"b1139356",2742:"94918ed5",2797:"a9b57a6e",2808:"255b16e3",2809:"b3069e29",2825:"c660befb",2832:"7ea9e491",2872:"4d729bcd",2959:"b518d585",3040:"10641efb",3081:"071fc034",3125:"b83a730f",3159:"bd4773d3",3171:"589d973e",3190:"e3c88de7",3335:"18a4c0b7",3422:"4f089fee",3436:"a8081494",3594:"2caef42f",3834:"cb6820d2",3841:"3d0020de",3881:"c7b888d2",3910:"73f4ba55",3981:"a7d173ab",4116:"85a15465",4118:"3d74beb4",4134:"2444bb98",4280:"eff70aea",4316:"952836ce",4376:"7f8485c8",4450:"9f2fd51b",4479:"0b1626be",4522:"b1bc8559",4583:"1df93b7f",4606:"6d43f213",4641:"6e823bff",4660:"8c0960be",4684:"466b73a0",4726:"ed713f01",4829:"e4c839a7",4854:"ff97290f",4903:"0b673b57",4957:"3dc0e382",4984:"101ed19d",5059:"eb9d53e1",5250:"04811054",5265:"9241b000",5287:"154b27f7",5312:"1c1da36b",5372:"813ba4cc",5482:"6a2e2506",5634:"3c410eba",5671:"f9c6986a",5685:"300d1b68",5694:"2d0bfbab",5697:"afdab408",5710:"92dde59e",5739:"bd1c8c64",5742:"aba21aa0",5756:"828b8e9a",5956:"598e721d",6087:"35a1eb90",6121:"b0687173",6147:"1ec1a4fc",6150:"b3adc6e7",6256:"0bb9166a",6328:"6be3ce43",6423:"61807a90",6643:"722eec08",6697:"8a270c96",6847:"b1b7c436",6982:"137eacb7",7043:"8e9de881",7094:"cd780e22",7098:"a7bd4aaa",7133:"29e6f763",7138:"71ebd33f",7142:"4275bcea",7253:"8ed97a55",7319:"78038a03",7378:"9089baca",7381:"9c9b402a",7616:"84b3321b",7624:"ac5df9f9",7816:"8c44000d",7817:"3889f620",7999:"de0a69ba",8066:"b455233a",8101:"d39037fb",8120:"6da9e3c2",8151:"a070532d",8295:"54271fc2",8401:"17896441",8419:"50893c13",8466:"3a48dd49",8528:"bdbb6afd",8679:"ff747875",8849:"b2a13c8f",8863:"1fbd9f6d",8912:"f056ce88",8958:"405239d0",8960:"476b4f3c",8974:"55656f84",8989:"15231cc4",9040:"de6a326d",9048:"a94703ab",9076:"660da82b",9114:"9e264c5c",9134:"24d533d0",9228:"346e3509",9259:"6c8acfd7",9276:"9ad2df70",9290:"38f12deb",9309:"65b2fd3f",9319:"4c35d9db",9322:"8a5ae23b",9325:"ee63f739",9486:"6d2eee91",9492:"9168da95",9603:"ba5f89dc",9632:"50b6fcd5",9647:"5e95c892",9712:"3994cf5d",9720:"12b0a7a7",9730:"48e0bb60",9798:"16015150",9885:"f83eaef4",9893:"002f497b",9954:"31f5cca7",9985:"c28309ff"}[e]||e)+"."+{54:"f5e0f93e",164:"f869a59b",184:"a4e517ac",245:"2ef1402c",282:"9065a9fc",311:"4b5814b3",338:"59494f63",362:"3b21f16c",375:"d50d4158",416:"79e6c1ae",518:"92b1244d",559:"28c4e7f0",585:"e1e33b8f",587:"e74cc61c",592:"85f21079",594:"d9bd9192",602:"43e90e9f",633:"3a1e95b5",670:"787009ad",802:"dcc6ccf3",806:"db249ac4",939:"ada671d9",957:"2136c8f3",976:"574d5494",1051:"b33fe48a",1064:"b5f1c78a",1081:"5812f8a6",1098:"3de260b7",1169:"883adae1",1176:"9a0aab73",1182:"99e89960",1205:"d2d2ca77",1235:"74362299",1245:"c78fa6b0",1378:"da701329",1434:"1d7b666e",1451:"eeddb009",1452:"33cef55a",1464:"927bcc0d",1487:"6a8270b4",1494:"65604c59",1497:"437ce67f",1566:"167fceb0",1590:"51c68563",1841:"df0df01e",1955:"2fe3d041",1959:"85fa0371",1963:"a656ed52",1969:"771d23af",2024:"7eecb101",2030:"630be57f",2034:"c3263f23",2090:"95206bc4",2130:"12d2e528",2138:"be1e2d7f",2175:"dfcff2eb",2188:"3c38817e",2237:"0d5f378f",2270:"4c7b7436",2364:"03353401",2366:"5e6e8361",2383:"9571bc27",2398:"8efe36f0",2412:"f8f7fb53",2524:"462846d1",2586:"7299d535",2700:"d9cfd5d1",2701:"6a380d4c",2742:"d7dde112",2797:"8bd8f3e5",2808:"0ff06564",2809:"f7fea258",2825:"e27fc602",2832:"406ae73f",2872:"8abd474c",2959:"5c738cb1",2966:"00631f0d",3040:"034536c6",3081:"3fb75e25",3125:"f7ec58b9",3159:"a51f58bb",3171:"72d78a7c",3190:"09928e7c",3335:"9435c495",3422:"d5cd329a",3436:"efe1855b",3594:"d6b688b8",3775:"5a596aa8",3834:"9bf7c2c6",3841:"612b9152",3881:"6d6a7945",3910:"19c0b3f6",3981:"7ffca418",4116:"bcbf437c",4118:"26327f81",4134:"8486582b",4280:"29c8cb7b",4316:"8dc0a8bb",4328:"624cf4bc",4376:"a68a0642",4450:"375d1b99",4479:"40673e5a",4522:"80c399fe",4583:"6c5e516f",4606:"58583818",4641:"6ae0db07",4660:"ad88dba6",4684:"4d775907",4726:"3d9c6000",4829:"49ecf29e",4854:"0fd24f46",4903:"2c531628",4957:"2400418c",4984:"b7b3a0c3",5059:"f0f4f075",5060:"8ee5bb77",5250:"ccf15da6",5265:"5033f385",5287:"c7cafa72",5312:"1c9f19b7",5372:"7a3f92d7",5394:"f5b26d62",5479:"58b8eec5",5481:"8227c55a",5482:"6fb2e1c9",5530:"6db93ac5",5634:"396124d8",5671:"5642e858",5685:"70a43cd7",5694:"c2ae3fb8",5697:"2026675a",5710:"2bf543aa",5739:"dd82431d",5742:"21608be8",5756:"bfa860aa",5956:"3ba6599f",6087:"cfe21d28",6121:"4723ead7",6126:"1406159b",6136:"da5eb7dd",6147:"9bdd09df",6150:"ea78bf9d",6256:"992b963c",6258:"cde8a5ac",6328:"f57322dc",6423:"3e2976c2",6530:"b54b8df1",6643:"07dfc224",6697:"85d8651e",6847:"d12eae71",6982:"a2e03dbc",7043:"5bbdb309",7094:"f0ffe81b",7098:"27fecdcf",7133:"30b21a86",7138:"a1e5cad0",7142:"24d0ce0c",7224:"1826f441",7253:"71fec98f",7256:"e4af7340",7319:"fcad4aa9",7378:"40305649",7381:"b96a5b10",7441:"cfe73e9c",7616:"88c3f228",7624:"bb911968",7816:"6b7d6707",7817:"583105dd",7999:"516df293",8066:"1059f651",8101:"97b36189",8120:"7f2a7900",8151:"ff51deb4",8158:"1af3c3c7",8295:"c50e9c3c",8401:"9c4d4dda",8419:"1464056f",8466:"dea2405c",8528:"9125971d",8554:"6c28e10d",8679:"7d4d5d68",8849:"839251d4",8863:"82d7ac3b",8912:"5d93e8ab",8913:"25f3c37e",8958:"02a8c952",8960:"4c2c15df",8974:"10ba6230",8989:"ecdcca0e",9024:"116fc2a0",9040:"9a533db0",9048:"2a1cd364",9076:"019becd4",9114:"7cb5247d",9134:"f065b2e6",9228:"fc54e323",9259:"d0d6265e",9276:"9b8d8d45",9290:"47c280aa",9309:"e2bc906a",9319:"07daba90",9322:"cbe587af",9325:"7f8628b9",9471:"51471f3b",9486:"9bd362ab",9492:"77f6d32d",9603:"8ebd4c01",9632:"cbc82be3",9647:"23f53dcf",9672:"44a6baae",9712:"b1035f84",9720:"2da6e381",9730:"4cf1a048",9763:"ccbd257f",9798:"9fe6a440",9885:"e6a2d30b",9893:"051845a5",9954:"a9303c5f",9985:"70c0c648"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},d="momento-docs:",r.l=(e,a,b,c)=>{if(f[e])f[e].push(a);else{var t,o;if(void 0!==b)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var d=f[e];if(delete f[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(b))),a)return a(b)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/ja/",r.gca=function(e){return e={16015150:"9798",17896441:"8401","700ba566":"54",abfc53e0:"164",ae2ccdab:"184",dc01436a:"245",fab06213:"282","924df60e":"311","626fbfd1":"338","06da040b":"362","2552e03d":"559",ca10f696:"585","4b93b5c4":"587","93b48d41":"592","5e8c322a":"594",b817e55f:"602","0aaa0fdc":"633","96422a8e":"670","7df93f80":"806","6481fae3":"939",c141421f:"957","50f05764":"976",c6522e74:"1051","7b7fffbe":"1064","24d265c4":"1081","0cddfb06":"1098","1dcf9a29":"1182",d08db822:"1205",a7456010:"1235","7abaa3fd":"1434","4c71f648":"1452","18ef01d0":"1464",c3af9f28:"1487",bd4bc387:"1494","9baec6c7":"1841",f6ccc656:"1955",fa2e647c:"1959",e0164697:"1963","67b91739":"1969",d7c924a9:"2024","36fdba0c":"2030","5d17f0bf":"2090","1a4e3797":"2138","78d83c18":"2175",dd75dd3b:"2188",b6dfeff2:"2364",b88618a5:"2366","96e91e0a":"2383","7a451a59":"2398","514ee296":"2524",c4d4e1e1:"2586","8eca53d6":"2700",b1139356:"2701","94918ed5":"2742",a9b57a6e:"2797","255b16e3":"2808",b3069e29:"2809",c660befb:"2825","7ea9e491":"2832","4d729bcd":"2872",b518d585:"2959","10641efb":"3040","071fc034":"3081",b83a730f:"3125",bd4773d3:"3159","589d973e":"3171",e3c88de7:"3190","18a4c0b7":"3335","4f089fee":"3422",a8081494:"3436","2caef42f":"3594",cb6820d2:"3834","3d0020de":"3841",c7b888d2:"3881","73f4ba55":"3910",a7d173ab:"3981","85a15465":"4116","3d74beb4":"4118","2444bb98":"4134",eff70aea:"4280","952836ce":"4316","7f8485c8":"4376","9f2fd51b":"4450","0b1626be":"4479",b1bc8559:"4522","1df93b7f":"4583","6d43f213":"4606","6e823bff":"4641","8c0960be":"4660","466b73a0":"4684",ed713f01:"4726",e4c839a7:"4829",ff97290f:"4854","0b673b57":"4903","3dc0e382":"4957","101ed19d":"4984",eb9d53e1:"5059","04811054":"5250","9241b000":"5265","154b27f7":"5287","1c1da36b":"5312","813ba4cc":"5372","6a2e2506":"5482","3c410eba":"5634",f9c6986a:"5671","300d1b68":"5685","2d0bfbab":"5694",afdab408:"5697","92dde59e":"5710",bd1c8c64:"5739",aba21aa0:"5742","828b8e9a":"5756","598e721d":"5956","35a1eb90":"6087",b0687173:"6121","1ec1a4fc":"6147",b3adc6e7:"6150","0bb9166a":"6256","6be3ce43":"6328","61807a90":"6423","722eec08":"6643","8a270c96":"6697",b1b7c436:"6847","137eacb7":"6982","8e9de881":"7043",cd780e22:"7094",a7bd4aaa:"7098","29e6f763":"7133","71ebd33f":"7138","4275bcea":"7142","8ed97a55":"7253","78038a03":"7319","9089baca":"7378","9c9b402a":"7381","84b3321b":"7616",ac5df9f9:"7624","8c44000d":"7816","3889f620":"7817",de0a69ba:"7999",b455233a:"8066",d39037fb:"8101","6da9e3c2":"8120",a070532d:"8151","54271fc2":"8295","50893c13":"8419","3a48dd49":"8466",bdbb6afd:"8528",ff747875:"8679",b2a13c8f:"8849","1fbd9f6d":"8863",f056ce88:"8912","405239d0":"8958","476b4f3c":"8960","55656f84":"8974","15231cc4":"8989",de6a326d:"9040",a94703ab:"9048","660da82b":"9076","9e264c5c":"9114","24d533d0":"9134","346e3509":"9228","6c8acfd7":"9259","9ad2df70":"9276","38f12deb":"9290","65b2fd3f":"9309","4c35d9db":"9319","8a5ae23b":"9322",ee63f739:"9325","6d2eee91":"9486","9168da95":"9492",ba5f89dc:"9603","50b6fcd5":"9632","5e95c892":"9647","3994cf5d":"9712","12b0a7a7":"9720","48e0bb60":"9730",f83eaef4:"9885","002f497b":"9893","31f5cca7":"9954",c28309ff:"9985"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,b)=>{var f=r.o(e,a)?e[a]:void 0;if(0!==f)if(f)b.push(f[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var d=new Promise(((b,d)=>f=e[a]=[b,d]));b.push(f[2]=d);var c=r.p+r.u(a),t=new Error;r.l(c,(b=>{if(r.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var d=b&&("load"===b.type?"missing":b.type),c=b&&b.target&&b.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+c+")",t.name="ChunkLoadError",t.type=d,t.request=c,f[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,b)=>{var f,d,c=b[0],t=b[1],o=b[2],n=0;if(c.some((a=>0!==e[a]))){for(f in t)r.o(t,f)&&(r.m[f]=t[f]);if(o)var i=o(r)}for(a&&a(b);n{"use strict";var e,a,b,f,d,c={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var b=t[e]={exports:{}};return c[e].call(b.exports,b,b.exports,r),b.exports}r.m=c,e=[],r.O=(a,b,f,d)=>{if(!b){var c=1/0;for(i=0;i=d)&&Object.keys(r.O).every((e=>r.O[e](b[o])))?b.splice(o--,1):(t=!1,d0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[b,f,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var c={};a=a||[null,b({}),b([]),b(b)];for(var t=2&f&&e;"object"==typeof t&&!~a.indexOf(t);t=b(t))Object.getOwnPropertyNames(t).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,r.d(d,c),d},r.d=(e,a)=>{for(var b in a)r.o(a,b)&&!r.o(e,b)&&Object.defineProperty(e,b,{enumerable:!0,get:a[b]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,b)=>(r.f[b](e,a),a)),[])),r.u=e=>"assets/js/"+({54:"700ba566",164:"abfc53e0",184:"ae2ccdab",245:"dc01436a",282:"fab06213",311:"924df60e",338:"626fbfd1",362:"06da040b",559:"2552e03d",585:"ca10f696",587:"4b93b5c4",592:"93b48d41",594:"5e8c322a",602:"b817e55f",633:"0aaa0fdc",670:"96422a8e",806:"7df93f80",939:"6481fae3",957:"c141421f",976:"50f05764",1051:"c6522e74",1064:"7b7fffbe",1081:"24d265c4",1098:"0cddfb06",1182:"1dcf9a29",1205:"d08db822",1235:"a7456010",1434:"7abaa3fd",1452:"4c71f648",1464:"18ef01d0",1487:"c3af9f28",1494:"bd4bc387",1841:"9baec6c7",1955:"f6ccc656",1959:"fa2e647c",1963:"e0164697",1969:"67b91739",2024:"d7c924a9",2030:"36fdba0c",2090:"5d17f0bf",2138:"1a4e3797",2175:"78d83c18",2188:"dd75dd3b",2364:"b6dfeff2",2366:"b88618a5",2383:"96e91e0a",2398:"7a451a59",2524:"514ee296",2586:"c4d4e1e1",2700:"8eca53d6",2701:"b1139356",2742:"94918ed5",2797:"a9b57a6e",2808:"255b16e3",2809:"b3069e29",2825:"c660befb",2832:"7ea9e491",2872:"4d729bcd",2959:"b518d585",3040:"10641efb",3081:"071fc034",3125:"b83a730f",3159:"bd4773d3",3171:"589d973e",3190:"e3c88de7",3335:"18a4c0b7",3422:"4f089fee",3436:"a8081494",3594:"2caef42f",3834:"cb6820d2",3841:"3d0020de",3881:"c7b888d2",3910:"73f4ba55",3981:"a7d173ab",4116:"85a15465",4118:"3d74beb4",4134:"2444bb98",4280:"eff70aea",4316:"952836ce",4376:"7f8485c8",4450:"9f2fd51b",4479:"0b1626be",4522:"b1bc8559",4583:"1df93b7f",4606:"6d43f213",4641:"6e823bff",4660:"8c0960be",4684:"466b73a0",4726:"ed713f01",4829:"e4c839a7",4854:"ff97290f",4903:"0b673b57",4957:"3dc0e382",4984:"101ed19d",5059:"eb9d53e1",5250:"04811054",5265:"9241b000",5287:"154b27f7",5312:"1c1da36b",5372:"813ba4cc",5482:"6a2e2506",5634:"3c410eba",5671:"f9c6986a",5685:"300d1b68",5694:"2d0bfbab",5697:"afdab408",5710:"92dde59e",5739:"bd1c8c64",5742:"aba21aa0",5756:"828b8e9a",5956:"598e721d",6087:"35a1eb90",6121:"b0687173",6147:"1ec1a4fc",6150:"b3adc6e7",6256:"0bb9166a",6328:"6be3ce43",6423:"61807a90",6643:"722eec08",6697:"8a270c96",6847:"b1b7c436",6982:"137eacb7",7043:"8e9de881",7094:"cd780e22",7098:"a7bd4aaa",7133:"29e6f763",7138:"71ebd33f",7142:"4275bcea",7253:"8ed97a55",7319:"78038a03",7378:"9089baca",7381:"9c9b402a",7616:"84b3321b",7624:"ac5df9f9",7816:"8c44000d",7817:"3889f620",7999:"de0a69ba",8066:"b455233a",8101:"d39037fb",8120:"6da9e3c2",8151:"a070532d",8295:"54271fc2",8401:"17896441",8419:"50893c13",8466:"3a48dd49",8528:"bdbb6afd",8679:"ff747875",8849:"b2a13c8f",8863:"1fbd9f6d",8912:"f056ce88",8958:"405239d0",8960:"476b4f3c",8974:"55656f84",8989:"15231cc4",9040:"de6a326d",9048:"a94703ab",9076:"660da82b",9114:"9e264c5c",9134:"24d533d0",9228:"346e3509",9259:"6c8acfd7",9276:"9ad2df70",9290:"38f12deb",9309:"65b2fd3f",9319:"4c35d9db",9322:"8a5ae23b",9325:"ee63f739",9486:"6d2eee91",9492:"9168da95",9603:"ba5f89dc",9632:"50b6fcd5",9647:"5e95c892",9712:"3994cf5d",9720:"12b0a7a7",9730:"48e0bb60",9798:"16015150",9885:"f83eaef4",9893:"002f497b",9954:"31f5cca7",9985:"c28309ff"}[e]||e)+"."+{54:"f5e0f93e",164:"f869a59b",184:"a4e517ac",245:"2ef1402c",282:"9065a9fc",311:"4b5814b3",338:"59494f63",362:"3b21f16c",375:"d50d4158",416:"79e6c1ae",518:"92b1244d",559:"28c4e7f0",585:"e1e33b8f",587:"e74cc61c",592:"85f21079",594:"d9bd9192",602:"43e90e9f",633:"3a1e95b5",670:"787009ad",802:"dcc6ccf3",806:"db249ac4",939:"ada671d9",957:"2136c8f3",976:"574d5494",1051:"b33fe48a",1064:"b5f1c78a",1081:"5812f8a6",1098:"3de260b7",1169:"883adae1",1176:"9a0aab73",1182:"99e89960",1205:"d2d2ca77",1235:"74362299",1245:"c78fa6b0",1378:"da701329",1434:"1d7b666e",1451:"eeddb009",1452:"33cef55a",1464:"927bcc0d",1487:"6a8270b4",1494:"65604c59",1497:"437ce67f",1566:"167fceb0",1590:"51c68563",1841:"df0df01e",1955:"2fe3d041",1959:"85fa0371",1963:"a656ed52",1969:"771d23af",2024:"7eecb101",2030:"630be57f",2034:"c3263f23",2090:"95206bc4",2130:"12d2e528",2138:"be1e2d7f",2175:"dfcff2eb",2188:"3c38817e",2237:"0d5f378f",2270:"4c7b7436",2364:"03353401",2366:"5e6e8361",2383:"9571bc27",2398:"8efe36f0",2412:"f8f7fb53",2524:"462846d1",2586:"7299d535",2700:"d9cfd5d1",2701:"6a380d4c",2742:"d7dde112",2797:"8bd8f3e5",2808:"0ff06564",2809:"f7fea258",2825:"e27fc602",2832:"406ae73f",2872:"8abd474c",2959:"5c738cb1",2966:"00631f0d",3040:"034536c6",3081:"3fb75e25",3125:"f7ec58b9",3159:"a51f58bb",3171:"72d78a7c",3190:"09928e7c",3335:"9435c495",3422:"d5cd329a",3436:"efe1855b",3594:"d6b688b8",3775:"5a596aa8",3834:"9bf7c2c6",3841:"612b9152",3881:"6d6a7945",3910:"19c0b3f6",3981:"7ffca418",4116:"bcbf437c",4118:"26327f81",4134:"8486582b",4280:"29c8cb7b",4316:"8dc0a8bb",4328:"624cf4bc",4376:"a68a0642",4450:"375d1b99",4479:"40673e5a",4522:"80c399fe",4583:"6c5e516f",4606:"58583818",4641:"6ae0db07",4660:"ad88dba6",4684:"4d775907",4726:"3d9c6000",4829:"49ecf29e",4854:"0fd24f46",4903:"2c531628",4957:"2400418c",4984:"b7b3a0c3",5059:"f0f4f075",5060:"8ee5bb77",5250:"ccf15da6",5265:"5033f385",5287:"c7cafa72",5312:"1c9f19b7",5372:"7a3f92d7",5394:"f5b26d62",5479:"58b8eec5",5481:"8227c55a",5482:"6fb2e1c9",5530:"6db93ac5",5634:"396124d8",5671:"5642e858",5685:"70a43cd7",5694:"c2ae3fb8",5697:"7d2c8f0f",5710:"2bf543aa",5739:"dd82431d",5742:"21608be8",5756:"bfa860aa",5956:"3ba6599f",6087:"cfe21d28",6121:"4723ead7",6126:"1406159b",6136:"da5eb7dd",6147:"9bdd09df",6150:"ea78bf9d",6256:"992b963c",6258:"cde8a5ac",6328:"f57322dc",6423:"3e2976c2",6530:"b54b8df1",6643:"07dfc224",6697:"85d8651e",6847:"d12eae71",6982:"a2e03dbc",7043:"5bbdb309",7094:"f0ffe81b",7098:"27fecdcf",7133:"30b21a86",7138:"a1e5cad0",7142:"24d0ce0c",7224:"1826f441",7253:"71fec98f",7256:"e4af7340",7319:"fcad4aa9",7378:"40305649",7381:"b96a5b10",7441:"cfe73e9c",7616:"88c3f228",7624:"bb911968",7816:"6b7d6707",7817:"583105dd",7999:"516df293",8066:"1059f651",8101:"97b36189",8120:"7f2a7900",8151:"ff51deb4",8158:"1af3c3c7",8295:"c50e9c3c",8401:"9c4d4dda",8419:"1464056f",8466:"dea2405c",8528:"9125971d",8554:"6c28e10d",8679:"7d4d5d68",8849:"839251d4",8863:"82d7ac3b",8912:"5d93e8ab",8913:"25f3c37e",8958:"02a8c952",8960:"4c2c15df",8974:"10ba6230",8989:"ecdcca0e",9024:"116fc2a0",9040:"9a533db0",9048:"2a1cd364",9076:"019becd4",9114:"7cb5247d",9134:"f065b2e6",9228:"fc54e323",9259:"d0d6265e",9276:"9b8d8d45",9290:"47c280aa",9309:"e2bc906a",9319:"07daba90",9322:"cbe587af",9325:"7f8628b9",9471:"51471f3b",9486:"9bd362ab",9492:"77f6d32d",9603:"8ebd4c01",9632:"cbc82be3",9647:"23f53dcf",9672:"44a6baae",9712:"b1035f84",9720:"2da6e381",9730:"4cf1a048",9763:"ccbd257f",9798:"9fe6a440",9885:"e6a2d30b",9893:"051845a5",9954:"a9303c5f",9985:"70c0c648"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},d="momento-docs:",r.l=(e,a,b,c)=>{if(f[e])f[e].push(a);else{var t,o;if(void 0!==b)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var d=f[e];if(delete f[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(b))),a)return a(b)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/ja/",r.gca=function(e){return e={16015150:"9798",17896441:"8401","700ba566":"54",abfc53e0:"164",ae2ccdab:"184",dc01436a:"245",fab06213:"282","924df60e":"311","626fbfd1":"338","06da040b":"362","2552e03d":"559",ca10f696:"585","4b93b5c4":"587","93b48d41":"592","5e8c322a":"594",b817e55f:"602","0aaa0fdc":"633","96422a8e":"670","7df93f80":"806","6481fae3":"939",c141421f:"957","50f05764":"976",c6522e74:"1051","7b7fffbe":"1064","24d265c4":"1081","0cddfb06":"1098","1dcf9a29":"1182",d08db822:"1205",a7456010:"1235","7abaa3fd":"1434","4c71f648":"1452","18ef01d0":"1464",c3af9f28:"1487",bd4bc387:"1494","9baec6c7":"1841",f6ccc656:"1955",fa2e647c:"1959",e0164697:"1963","67b91739":"1969",d7c924a9:"2024","36fdba0c":"2030","5d17f0bf":"2090","1a4e3797":"2138","78d83c18":"2175",dd75dd3b:"2188",b6dfeff2:"2364",b88618a5:"2366","96e91e0a":"2383","7a451a59":"2398","514ee296":"2524",c4d4e1e1:"2586","8eca53d6":"2700",b1139356:"2701","94918ed5":"2742",a9b57a6e:"2797","255b16e3":"2808",b3069e29:"2809",c660befb:"2825","7ea9e491":"2832","4d729bcd":"2872",b518d585:"2959","10641efb":"3040","071fc034":"3081",b83a730f:"3125",bd4773d3:"3159","589d973e":"3171",e3c88de7:"3190","18a4c0b7":"3335","4f089fee":"3422",a8081494:"3436","2caef42f":"3594",cb6820d2:"3834","3d0020de":"3841",c7b888d2:"3881","73f4ba55":"3910",a7d173ab:"3981","85a15465":"4116","3d74beb4":"4118","2444bb98":"4134",eff70aea:"4280","952836ce":"4316","7f8485c8":"4376","9f2fd51b":"4450","0b1626be":"4479",b1bc8559:"4522","1df93b7f":"4583","6d43f213":"4606","6e823bff":"4641","8c0960be":"4660","466b73a0":"4684",ed713f01:"4726",e4c839a7:"4829",ff97290f:"4854","0b673b57":"4903","3dc0e382":"4957","101ed19d":"4984",eb9d53e1:"5059","04811054":"5250","9241b000":"5265","154b27f7":"5287","1c1da36b":"5312","813ba4cc":"5372","6a2e2506":"5482","3c410eba":"5634",f9c6986a:"5671","300d1b68":"5685","2d0bfbab":"5694",afdab408:"5697","92dde59e":"5710",bd1c8c64:"5739",aba21aa0:"5742","828b8e9a":"5756","598e721d":"5956","35a1eb90":"6087",b0687173:"6121","1ec1a4fc":"6147",b3adc6e7:"6150","0bb9166a":"6256","6be3ce43":"6328","61807a90":"6423","722eec08":"6643","8a270c96":"6697",b1b7c436:"6847","137eacb7":"6982","8e9de881":"7043",cd780e22:"7094",a7bd4aaa:"7098","29e6f763":"7133","71ebd33f":"7138","4275bcea":"7142","8ed97a55":"7253","78038a03":"7319","9089baca":"7378","9c9b402a":"7381","84b3321b":"7616",ac5df9f9:"7624","8c44000d":"7816","3889f620":"7817",de0a69ba:"7999",b455233a:"8066",d39037fb:"8101","6da9e3c2":"8120",a070532d:"8151","54271fc2":"8295","50893c13":"8419","3a48dd49":"8466",bdbb6afd:"8528",ff747875:"8679",b2a13c8f:"8849","1fbd9f6d":"8863",f056ce88:"8912","405239d0":"8958","476b4f3c":"8960","55656f84":"8974","15231cc4":"8989",de6a326d:"9040",a94703ab:"9048","660da82b":"9076","9e264c5c":"9114","24d533d0":"9134","346e3509":"9228","6c8acfd7":"9259","9ad2df70":"9276","38f12deb":"9290","65b2fd3f":"9309","4c35d9db":"9319","8a5ae23b":"9322",ee63f739:"9325","6d2eee91":"9486","9168da95":"9492",ba5f89dc:"9603","50b6fcd5":"9632","5e95c892":"9647","3994cf5d":"9712","12b0a7a7":"9720","48e0bb60":"9730",f83eaef4:"9885","002f497b":"9893","31f5cca7":"9954",c28309ff:"9985"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,b)=>{var f=r.o(e,a)?e[a]:void 0;if(0!==f)if(f)b.push(f[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var d=new Promise(((b,d)=>f=e[a]=[b,d]));b.push(f[2]=d);var c=r.p+r.u(a),t=new Error;r.l(c,(b=>{if(r.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var d=b&&("load"===b.type?"missing":b.type),c=b&&b.target&&b.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+c+")",t.name="ChunkLoadError",t.type=d,t.request=c,f[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,b)=>{var f,d,c=b[0],t=b[1],o=b[2],n=0;if(c.some((a=>0!==e[a]))){for(f in t)r.o(t,f)&&(r.m[f]=t[f]);if(o)var i=o(r)}for(a&&a(b);n - + diff --git a/ja/cache.html b/ja/cache.html index a234fcdea..30f56e19c 100644 --- a/ja/cache.html +++ b/ja/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop.html b/ja/cache/develop.html index 6ff6bda95..5f71e615a 100644 --- a/ja/cache/develop.html +++ b/ja/cache/develop.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference.html b/ja/cache/develop/api-reference.html index 4d2171fdc..943fc8723 100644 --- a/ja/cache/develop/api-reference.html +++ b/ja/cache/develop/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/auth.html b/ja/cache/develop/api-reference/auth.html index 9e00a4b3c..32c4c9540 100644 --- a/ja/cache/develop/api-reference/auth.html +++ b/ja/cache/develop/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/collection-ttl.html b/ja/cache/develop/api-reference/collection-ttl.html index 586caf5df..538c387a7 100644 --- a/ja/cache/develop/api-reference/collection-ttl.html +++ b/ja/cache/develop/api-reference/collection-ttl.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/dictionary-collections.html b/ja/cache/develop/api-reference/dictionary-collections.html index c537e639d..bb5740785 100644 --- a/ja/cache/develop/api-reference/dictionary-collections.html +++ b/ja/cache/develop/api-reference/dictionary-collections.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/http-api.html b/ja/cache/develop/api-reference/http-api.html index e5ab24cc4..d00efcf3b 100644 --- a/ja/cache/develop/api-reference/http-api.html +++ b/ja/cache/develop/api-reference/http-api.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/list-collections.html b/ja/cache/develop/api-reference/list-collections.html index 5e4750df5..98d8de120 100644 --- a/ja/cache/develop/api-reference/list-collections.html +++ b/ja/cache/develop/api-reference/list-collections.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/response-objects.html b/ja/cache/develop/api-reference/response-objects.html index 9b76ebb70..be3f9e4f5 100644 --- a/ja/cache/develop/api-reference/response-objects.html +++ b/ja/cache/develop/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/set-collections.html b/ja/cache/develop/api-reference/set-collections.html index a8f046538..fe0734890 100644 --- a/ja/cache/develop/api-reference/set-collections.html +++ b/ja/cache/develop/api-reference/set-collections.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/api-reference/sorted-set-collections.html b/ja/cache/develop/api-reference/sorted-set-collections.html index 733e82e88..4fdcac8fd 100644 --- a/ja/cache/develop/api-reference/sorted-set-collections.html +++ b/ja/cache/develop/api-reference/sorted-set-collections.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/authentication.html b/ja/cache/develop/authentication.html index 653c76873..caa42f7c4 100644 --- a/ja/cache/develop/authentication.html +++ b/ja/cache/develop/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/authentication/api-keys.html b/ja/cache/develop/authentication/api-keys.html index 82f311c39..696797bdd 100644 --- a/ja/cache/develop/authentication/api-keys.html +++ b/ja/cache/develop/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/authentication/permissions.html b/ja/cache/develop/authentication/permissions.html index bf456923b..29101d054 100644 --- a/ja/cache/develop/authentication/permissions.html +++ b/ja/cache/develop/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/authentication/tokens.html b/ja/cache/develop/authentication/tokens.html index 4f9c67e66..dc68548c4 100644 --- a/ja/cache/develop/authentication/tokens.html +++ b/ja/cache/develop/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/basics/client-configuration-objects.html b/ja/cache/develop/basics/client-configuration-objects.html index 8c0b0fa5c..c1bb06093 100644 --- a/ja/cache/develop/basics/client-configuration-objects.html +++ b/ja/cache/develop/basics/client-configuration-objects.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/basics/datatypes.html b/ja/cache/develop/basics/datatypes.html index 48f7c9020..86971bffb 100644 --- a/ja/cache/develop/basics/datatypes.html +++ b/ja/cache/develop/basics/datatypes.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/basics/error-handling-production-readiness.html b/ja/cache/develop/basics/error-handling-production-readiness.html index 90b633386..d74dcfdfd 100644 --- a/ja/cache/develop/basics/error-handling-production-readiness.html +++ b/ja/cache/develop/basics/error-handling-production-readiness.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/guides/working-with-files-cache.html b/ja/cache/develop/guides/working-with-files-cache.html index 04a6a8f3e..a32bd1ab8 100644 --- a/ja/cache/develop/guides/working-with-files-cache.html +++ b/ja/cache/develop/guides/working-with-files-cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/guides/working-with-time-series-data.html b/ja/cache/develop/guides/working-with-time-series-data.html index eb9ee5237..cc12d7c67 100644 --- a/ja/cache/develop/guides/working-with-time-series-data.html +++ b/ja/cache/develop/guides/working-with-time-series-data.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/develop/language-support.html b/ja/cache/develop/language-support.html index c86909426..24184d701 100644 --- a/ja/cache/develop/language-support.html +++ b/ja/cache/develop/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/getting-started.html b/ja/cache/getting-started.html index 4afc5caa4..273caec23 100644 --- a/ja/cache/getting-started.html +++ b/ja/cache/getting-started.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/how-to/rate-limiter.html b/ja/cache/how-to/rate-limiter.html index 5bfadd2cf..965855734 100644 --- a/ja/cache/how-to/rate-limiter.html +++ b/ja/cache/how-to/rate-limiter.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/amazon-eventbridge.html b/ja/cache/integrations/amazon-eventbridge.html index 8ef797fbb..9a01d5e2e 100644 --- a/ja/cache/integrations/amazon-eventbridge.html +++ b/ja/cache/integrations/amazon-eventbridge.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/aws-secrets-manager.html b/ja/cache/integrations/aws-secrets-manager.html index 16178b5d0..d8c167161 100644 --- a/ja/cache/integrations/aws-secrets-manager.html +++ b/ja/cache/integrations/aws-secrets-manager.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/bulk-writing-from-redis-json-csv.html b/ja/cache/integrations/bulk-writing-from-redis-json-csv.html index f933537b0..8bc1a2d42 100644 --- a/ja/cache/integrations/bulk-writing-from-redis-json-csv.html +++ b/ja/cache/integrations/bulk-writing-from-redis-json-csv.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/cloudflare.html b/ja/cache/integrations/cloudflare.html index fe407641a..19cc62f10 100644 --- a/ja/cache/integrations/cloudflare.html +++ b/ja/cache/integrations/cloudflare.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/deno.html b/ja/cache/integrations/deno.html index 478814a11..d30029b8b 100644 --- a/ja/cache/integrations/deno.html +++ b/ja/cache/integrations/deno.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/drupal-integration.html b/ja/cache/integrations/drupal-integration.html index 150368978..9ad52f60b 100644 --- a/ja/cache/integrations/drupal-integration.html +++ b/ja/cache/integrations/drupal-integration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/fastly.html b/ja/cache/integrations/fastly.html index 080a101a7..479982618 100644 --- a/ja/cache/integrations/fastly.html +++ b/ja/cache/integrations/fastly.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/momento-cache-laravel-php.html b/ja/cache/integrations/momento-cache-laravel-php.html index 336761021..a4ac8bd31 100644 --- a/ja/cache/integrations/momento-cache-laravel-php.html +++ b/ja/cache/integrations/momento-cache-laravel-php.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/netlify-integration.html b/ja/cache/integrations/netlify-integration.html index 4b306e027..e6a8718f4 100644 --- a/ja/cache/integrations/netlify-integration.html +++ b/ja/cache/integrations/netlify-integration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/redis-client-compatibility.html b/ja/cache/integrations/redis-client-compatibility.html index 1a06565bf..dc878109c 100644 --- a/ja/cache/integrations/redis-client-compatibility.html +++ b/ja/cache/integrations/redis-client-compatibility.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/sequelize.html b/ja/cache/integrations/sequelize.html index b8c964828..44b5c5a84 100644 --- a/ja/cache/integrations/sequelize.html +++ b/ja/cache/integrations/sequelize.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/terraform.html b/ja/cache/integrations/terraform.html index 21ffe4be6..58bec1e83 100644 --- a/ja/cache/integrations/terraform.html +++ b/ja/cache/integrations/terraform.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/unity-integration.html b/ja/cache/integrations/unity-integration.html index 377f4641b..15cf3c32e 100644 --- a/ja/cache/integrations/unity-integration.html +++ b/ja/cache/integrations/unity-integration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/integrations/vercel-integration.html b/ja/cache/integrations/vercel-integration.html index 09f9a7fae..642b89dfb 100644 --- a/ja/cache/integrations/vercel-integration.html +++ b/ja/cache/integrations/vercel-integration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/introduction/common-caching-patterns.html b/ja/cache/introduction/common-caching-patterns.html index b6abfe709..553d5b52c 100644 --- a/ja/cache/introduction/common-caching-patterns.html +++ b/ja/cache/introduction/common-caching-patterns.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/introduction/common-caching-strategies.html b/ja/cache/introduction/common-caching-strategies.html index 87d06bc86..96676ae89 100644 --- a/ja/cache/introduction/common-caching-strategies.html +++ b/ja/cache/introduction/common-caching-strategies.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/courses/cache-concepts.html b/ja/cache/learn/courses/cache-concepts.html index 2ff8d4fc9..8c508bf75 100644 --- a/ja/cache/learn/courses/cache-concepts.html +++ b/ja/cache/learn/courses/cache-concepts.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html b/ja/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html index dabe288b2..d0f73f2da 100644 --- a/ja/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html +++ b/ja/cache/learn/courses/cache-concepts/cache-eviction-vs-cache-expiration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/courses/cache-concepts/common-caching-use-cases.html b/ja/cache/learn/courses/cache-concepts/common-caching-use-cases.html index c0e91a8c2..0eb3358f4 100644 --- a/ja/cache/learn/courses/cache-concepts/common-caching-use-cases.html +++ b/ja/cache/learn/courses/cache-concepts/common-caching-use-cases.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/courses/cache-concepts/time-to-live.html b/ja/cache/learn/courses/cache-concepts/time-to-live.html index 281d9dfda..b34196898 100644 --- a/ja/cache/learn/courses/cache-concepts/time-to-live.html +++ b/ja/cache/learn/courses/cache-concepts/time-to-live.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/courses/cache-concepts/why-use-serverless-services.html b/ja/cache/learn/courses/cache-concepts/why-use-serverless-services.html index 637853d78..daaacec78 100644 --- a/ja/cache/learn/courses/cache-concepts/why-use-serverless-services.html +++ b/ja/cache/learn/courses/cache-concepts/why-use-serverless-services.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/how-it-works/cache-eviction-vs-expiration.html b/ja/cache/learn/how-it-works/cache-eviction-vs-expiration.html index cb787dbb4..77f88e79e 100644 --- a/ja/cache/learn/how-it-works/cache-eviction-vs-expiration.html +++ b/ja/cache/learn/how-it-works/cache-eviction-vs-expiration.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/how-it-works/expire-data-with-ttl.html b/ja/cache/learn/how-it-works/expire-data-with-ttl.html index 8f32aa8d6..b3a9abc79 100644 --- a/ja/cache/learn/how-it-works/expire-data-with-ttl.html +++ b/ja/cache/learn/how-it-works/expire-data-with-ttl.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/learn/how-it-works/read-concern.html b/ja/cache/learn/how-it-works/read-concern.html index 6e2efe3a0..9ff410e85 100644 --- a/ja/cache/learn/how-it-works/read-concern.html +++ b/ja/cache/learn/how-it-works/read-concern.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/limits.html b/ja/cache/limits.html index 2c6b53651..3d7aae890 100644 --- a/ja/cache/limits.html +++ b/ja/cache/limits.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/manage/metrics_in_the_console.html b/ja/cache/manage/metrics_in_the_console.html index 985614857..69b987324 100644 --- a/ja/cache/manage/metrics_in_the_console.html +++ b/ja/cache/manage/metrics_in_the_console.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/patterns/api-caching.html b/ja/cache/patterns/api-caching.html index 7835f0efc..362cc4eee 100644 --- a/ja/cache/patterns/api-caching.html +++ b/ja/cache/patterns/api-caching.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cache/patterns/database-caching.html b/ja/cache/patterns/database-caching.html index b4ae84015..3a107a33e 100644 --- a/ja/cache/patterns/database-caching.html +++ b/ja/cache/patterns/database-caching.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cloud-linter.html b/ja/cloud-linter.html index ac7a28a6b..09d16a38a 100644 --- a/ja/cloud-linter.html +++ b/ja/cloud-linter.html @@ -9,7 +9,7 @@ - + diff --git a/ja/cloud-linter/getting-started.html b/ja/cloud-linter/getting-started.html index 8a628e03c..708664fc8 100644 --- a/ja/cloud-linter/getting-started.html +++ b/ja/cloud-linter/getting-started.html @@ -9,7 +9,7 @@ - + diff --git a/ja/index.html b/ja/index.html index 87bb1fe97..9d09b574b 100644 --- a/ja/index.html +++ b/ja/index.html @@ -9,7 +9,7 @@ - + diff --git a/ja/language_support.html b/ja/language_support.html index bc545e967..d094328bf 100644 --- a/ja/language_support.html +++ b/ja/language_support.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards.html b/ja/leaderboards.html index 3f7a854e5..1009e9ac5 100644 --- a/ja/leaderboards.html +++ b/ja/leaderboards.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/api-reference.html b/ja/leaderboards/api-reference.html index fd6cf227e..b97f0df92 100644 --- a/ja/leaderboards/api-reference.html +++ b/ja/leaderboards/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/api-reference/auth.html b/ja/leaderboards/api-reference/auth.html index 2aa1c60f9..b3a451ec7 100644 --- a/ja/leaderboards/api-reference/auth.html +++ b/ja/leaderboards/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/api-reference/response-objects.html b/ja/leaderboards/api-reference/response-objects.html index 3e77bc7ce..8c4edd30e 100644 --- a/ja/leaderboards/api-reference/response-objects.html +++ b/ja/leaderboards/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/language-support.html b/ja/leaderboards/language-support.html index 82534ef1f..88854919c 100644 --- a/ja/leaderboards/language-support.html +++ b/ja/leaderboards/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/limits.html b/ja/leaderboards/limits.html index 2846c2d47..f9db3106d 100644 --- a/ja/leaderboards/limits.html +++ b/ja/leaderboards/limits.html @@ -9,7 +9,7 @@ - + diff --git a/ja/leaderboards/patterns/map-id-to-string.html b/ja/leaderboards/patterns/map-id-to-string.html index 0e39af76b..e83000ff7 100644 --- a/ja/leaderboards/patterns/map-id-to-string.html +++ b/ja/leaderboards/patterns/map-id-to-string.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage.html b/ja/media-storage.html index e5508f86c..c39da6a76 100644 --- a/ja/media-storage.html +++ b/ja/media-storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/concurrency/account-level.html b/ja/media-storage/concurrency/account-level.html index c9cbd3f7a..50865f6c7 100644 --- a/ja/media-storage/concurrency/account-level.html +++ b/ja/media-storage/concurrency/account-level.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/concurrency/devices.html b/ja/media-storage/concurrency/devices.html index eae9adae4..9e1704d32 100644 --- a/ja/media-storage/concurrency/devices.html +++ b/ja/media-storage/concurrency/devices.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/core-concepts/abr-ladder.html b/ja/media-storage/core-concepts/abr-ladder.html index b97604fb0..0482ca293 100644 --- a/ja/media-storage/core-concepts/abr-ladder.html +++ b/ja/media-storage/core-concepts/abr-ladder.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/core-concepts/origin.html b/ja/media-storage/core-concepts/origin.html index 3b30f4a39..f19aae502 100644 --- a/ja/media-storage/core-concepts/origin.html +++ b/ja/media-storage/core-concepts/origin.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/core-concepts/segments.html b/ja/media-storage/core-concepts/segments.html index 025462532..de79274bc 100644 --- a/ja/media-storage/core-concepts/segments.html +++ b/ja/media-storage/core-concepts/segments.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/core-concepts/zero-buffer-rate.html b/ja/media-storage/core-concepts/zero-buffer-rate.html index 12a69dada..62ef8c6b4 100644 --- a/ja/media-storage/core-concepts/zero-buffer-rate.html +++ b/ja/media-storage/core-concepts/zero-buffer-rate.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/enhancements/heartbeats.html b/ja/media-storage/enhancements/heartbeats.html index 695312a6b..37b579122 100644 --- a/ja/media-storage/enhancements/heartbeats.html +++ b/ja/media-storage/enhancements/heartbeats.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/enhancements/live-reactions.html b/ja/media-storage/enhancements/live-reactions.html index 430e531e8..072c709fe 100644 --- a/ja/media-storage/enhancements/live-reactions.html +++ b/ja/media-storage/enhancements/live-reactions.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/enhancements/viewer-metrics.html b/ja/media-storage/enhancements/viewer-metrics.html index 226a11047..d4d5c2a0a 100644 --- a/ja/media-storage/enhancements/viewer-metrics.html +++ b/ja/media-storage/enhancements/viewer-metrics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/entitlements/about.html b/ja/media-storage/entitlements/about.html index 049bf5fb2..3f74c48a0 100644 --- a/ja/media-storage/entitlements/about.html +++ b/ja/media-storage/entitlements/about.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/entitlements/real-time-updates.html b/ja/media-storage/entitlements/real-time-updates.html index 65d60f02c..8b0246956 100644 --- a/ja/media-storage/entitlements/real-time-updates.html +++ b/ja/media-storage/entitlements/real-time-updates.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/overview.html b/ja/media-storage/overview.html index 84742f03f..52a14f11c 100644 --- a/ja/media-storage/overview.html +++ b/ja/media-storage/overview.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/performance/adaptive-bitrates/dash.html b/ja/media-storage/performance/adaptive-bitrates/dash.html index ffc0b8aaf..29945e071 100644 --- a/ja/media-storage/performance/adaptive-bitrates/dash.html +++ b/ja/media-storage/performance/adaptive-bitrates/dash.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/performance/adaptive-bitrates/hls.html b/ja/media-storage/performance/adaptive-bitrates/hls.html index 22bd3a79d..a6a4fe3b5 100644 --- a/ja/media-storage/performance/adaptive-bitrates/hls.html +++ b/ja/media-storage/performance/adaptive-bitrates/hls.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/performance/adaptive-bitrates/how-it-works.html b/ja/media-storage/performance/adaptive-bitrates/how-it-works.html index 279302b84..7ab569050 100644 --- a/ja/media-storage/performance/adaptive-bitrates/how-it-works.html +++ b/ja/media-storage/performance/adaptive-bitrates/how-it-works.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/performance/optimizing-delivery.html b/ja/media-storage/performance/optimizing-delivery.html index 77fda54d8..cab140352 100644 --- a/ja/media-storage/performance/optimizing-delivery.html +++ b/ja/media-storage/performance/optimizing-delivery.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/capture/rtmp.html b/ja/media-storage/streaming/capture/rtmp.html index 976067e02..cd75bf500 100644 --- a/ja/media-storage/streaming/capture/rtmp.html +++ b/ja/media-storage/streaming/capture/rtmp.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/decoding-video.html b/ja/media-storage/streaming/decoding-video.html index b26c147e9..cd1e63608 100644 --- a/ja/media-storage/streaming/decoding-video.html +++ b/ja/media-storage/streaming/decoding-video.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/live-streaming/glass-to-glass-latency.html b/ja/media-storage/streaming/live-streaming/glass-to-glass-latency.html index c7f6344b5..56303285f 100644 --- a/ja/media-storage/streaming/live-streaming/glass-to-glass-latency.html +++ b/ja/media-storage/streaming/live-streaming/glass-to-glass-latency.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/live-streaming/how-it-works.html b/ja/media-storage/streaming/live-streaming/how-it-works.html index dc29553e8..5dcdc0f8d 100644 --- a/ja/media-storage/streaming/live-streaming/how-it-works.html +++ b/ja/media-storage/streaming/live-streaming/how-it-works.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html b/ja/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html index 8ae6519b9..185a28612 100644 --- a/ja/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html +++ b/ja/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html @@ -9,7 +9,7 @@ - + @@ -24,6 +24,9 @@
  • Testing and troubleshooting the setup to ensure smooth playback.
  • 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.

    +

    Preparation

    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 @@

    HLS. It is commonly used for live sports, major live events, and 24/7 channels.

    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>
    +

    Channel settings

    +

    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.

    +

    MediaLive channel settings page fully configured

    +

    Input attachments

    +

    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:

    +

    MediaLive completed input page

    +

    Once configured, hit the Create input button, navigate back to the channel configuration page, and select the input we just created.

    +

    Output groups

    +

    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 segments
    • ttl - number of seconds to retain the playlist and segments before deletion
    -

    Applying 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.

    AWS MediaLive console with channel configuration filled out

    In the Manifest and Segments section, configure the following fields:

      @@ -104,10 +121,19 @@

      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.

      CloudFront behavior for variant playlists

      -

      4. Playback and troubleshooting

      -

      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.

      +

      4. Starting the stream

      +

      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!

      +

      MediaLive channel in a playing status

      +

      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.

      +

      5. Watching the stream

      +

      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!

      +

      HLS player streaming our content

      +

      6. Troubleshooting

      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.

      -

      MediaLive and Momento

      +

      MediaLive and Momento

      Verify the master manifest is accessible with player_api_key and returns the variant playlists correctly. Use the following curl command to test, or use the Momento console to view data in the namespace.

      $ curl "https://<momento_rest_endpoint>/cache/live-origin/playlist.m3u8?token=<player_api_key>"

      #EXTM3U
      #EXT-X-VERSION:3
      #EXT-X-INDEPENDENT-SEGMENTS
      #EXT-X-STREAM-INF:BANDWIDTH=2648800,AVERAGE-BANDWIDTH=1790800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=30.000
      playlist_480p30.m3u8?ttl_seconds=3600
      #EXT-X-STREAM-INF:BANDWIDTH=1394800,AVERAGE-BANDWIDTH=965800,CODECS="avc1.4d400d,mp4a.40.2",RESOLUTION=320x240,FRAME-RATE=30.000
      playlist_240p30.m3u8?ttl_seconds=3600
      #EXT-X-STREAM-INF:BANDWIDTH=4391200,AVERAGE-BANDWIDTH=2961200,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x720,FRAME-RATE=30.000
      playlist_720p30.m3u8?ttl_seconds=3600

      Verify that each variant playlist is accessible, and if you can download the last media segment listed in the variant playlists (aka the live point). Below are the curl commands to view the 480p manifest and the live point.

      @@ -147,7 +173,7 @@

      That's it!Discover how to use ffmpeg and an RTMP stream to stream to Momento.
    • Add real-time reactions to your streams.
    -

    We can't wait to see what you build. Happy coding!

    +

    We can't wait to see what you build. Happy coding!

    diff --git a/ja/media-storage/streaming/overview.html b/ja/media-storage/streaming/overview.html index 229d80110..cf0487336 100644 --- a/ja/media-storage/streaming/overview.html +++ b/ja/media-storage/streaming/overview.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/streaming/video-on-demand/media-storage.html b/ja/media-storage/streaming/video-on-demand/media-storage.html index f3d273b8d..5210eb56e 100644 --- a/ja/media-storage/streaming/video-on-demand/media-storage.html +++ b/ja/media-storage/streaming/video-on-demand/media-storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/media-storage/use-cases.html b/ja/media-storage/use-cases.html index c9ec83cf1..46bb62af2 100644 --- a/ja/media-storage/use-cases.html +++ b/ja/media-storage/use-cases.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform.html b/ja/platform.html index dd472bee8..8d688c41d 100644 --- a/ja/platform.html +++ b/ja/platform.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/connectivity/private-link.html b/ja/platform/connectivity/private-link.html index 42d5f181c..bc685f09a 100644 --- a/ja/platform/connectivity/private-link.html +++ b/ja/platform/connectivity/private-link.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/regions.html b/ja/platform/regions.html index 7e91a9727..ca01226bf 100644 --- a/ja/platform/regions.html +++ b/ja/platform/regions.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks.html b/ja/platform/sdks.html index 7f6879f7f..c92f1b453 100644 --- a/ja/platform/sdks.html +++ b/ja/platform/sdks.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dart.html b/ja/platform/sdks/dart.html index ece205144..afcc06c5e 100644 --- a/ja/platform/sdks/dart.html +++ b/ja/platform/sdks/dart.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dart/cache.html b/ja/platform/sdks/dart/cache.html index 75ee82cb7..c493cef67 100644 --- a/ja/platform/sdks/dart/cache.html +++ b/ja/platform/sdks/dart/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dart/topics.html b/ja/platform/sdks/dart/topics.html index 7e9f4d426..55b428a87 100644 --- a/ja/platform/sdks/dart/topics.html +++ b/ja/platform/sdks/dart/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dotnet.html b/ja/platform/sdks/dotnet.html index 906e0fb12..4ca5bd1e8 100644 --- a/ja/platform/sdks/dotnet.html +++ b/ja/platform/sdks/dotnet.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dotnet/cache.html b/ja/platform/sdks/dotnet/cache.html index f4792d98a..1e8007948 100644 --- a/ja/platform/sdks/dotnet/cache.html +++ b/ja/platform/sdks/dotnet/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dotnet/observability.html b/ja/platform/sdks/dotnet/observability.html index 0e2270c04..5810789b6 100644 --- a/ja/platform/sdks/dotnet/observability.html +++ b/ja/platform/sdks/dotnet/observability.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/dotnet/topics.html b/ja/platform/sdks/dotnet/topics.html index d1e40e0c1..0057e80b9 100644 --- a/ja/platform/sdks/dotnet/topics.html +++ b/ja/platform/sdks/dotnet/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/elixir.html b/ja/platform/sdks/elixir.html index a424efdf2..e39d6b784 100644 --- a/ja/platform/sdks/elixir.html +++ b/ja/platform/sdks/elixir.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/elixir/cache.html b/ja/platform/sdks/elixir/cache.html index 7ad712a9f..ac1731d8b 100644 --- a/ja/platform/sdks/elixir/cache.html +++ b/ja/platform/sdks/elixir/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/go.html b/ja/platform/sdks/go.html index 020d4343e..723b36bfd 100644 --- a/ja/platform/sdks/go.html +++ b/ja/platform/sdks/go.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/go/cache.html b/ja/platform/sdks/go/cache.html index 4f8507eb5..a4073605f 100644 --- a/ja/platform/sdks/go/cache.html +++ b/ja/platform/sdks/go/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/go/storage.html b/ja/platform/sdks/go/storage.html index 7c38ba99d..d12f29a2c 100644 --- a/ja/platform/sdks/go/storage.html +++ b/ja/platform/sdks/go/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/go/topics.html b/ja/platform/sdks/go/topics.html index 4172b02c2..791f2dfee 100644 --- a/ja/platform/sdks/go/topics.html +++ b/ja/platform/sdks/go/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/java.html b/ja/platform/sdks/java.html index 22e19089d..76ec777d7 100644 --- a/ja/platform/sdks/java.html +++ b/ja/platform/sdks/java.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/java/cache.html b/ja/platform/sdks/java/cache.html index 31e08f8d3..f5e1416a8 100644 --- a/ja/platform/sdks/java/cache.html +++ b/ja/platform/sdks/java/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/java/storage.html b/ja/platform/sdks/java/storage.html index d57d9a969..a2e5497e1 100644 --- a/ja/platform/sdks/java/storage.html +++ b/ja/platform/sdks/java/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/java/topics.html b/ja/platform/sdks/java/topics.html index b09daad8c..f58eba507 100644 --- a/ja/platform/sdks/java/topics.html +++ b/ja/platform/sdks/java/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/kotlin.html b/ja/platform/sdks/kotlin.html index 1c843abdf..84c705f7f 100644 --- a/ja/platform/sdks/kotlin.html +++ b/ja/platform/sdks/kotlin.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/kotlin/cache.html b/ja/platform/sdks/kotlin/cache.html index e8dcebca7..783660e49 100644 --- a/ja/platform/sdks/kotlin/cache.html +++ b/ja/platform/sdks/kotlin/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/kotlin/topics.html b/ja/platform/sdks/kotlin/topics.html index ed655cf64..f7f585c45 100644 --- a/ja/platform/sdks/kotlin/topics.html +++ b/ja/platform/sdks/kotlin/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs.html b/ja/platform/sdks/nodejs.html index abac74400..6fd241623 100644 --- a/ja/platform/sdks/nodejs.html +++ b/ja/platform/sdks/nodejs.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/cache.html b/ja/platform/sdks/nodejs/cache.html index 85cfba785..7588969ee 100644 --- a/ja/platform/sdks/nodejs/cache.html +++ b/ja/platform/sdks/nodejs/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/compression.html b/ja/platform/sdks/nodejs/compression.html index 12f057c8a..403dfa83b 100644 --- a/ja/platform/sdks/nodejs/compression.html +++ b/ja/platform/sdks/nodejs/compression.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/config-and-error-handling.html b/ja/platform/sdks/nodejs/config-and-error-handling.html index a938337fb..e442c61d3 100644 --- a/ja/platform/sdks/nodejs/config-and-error-handling.html +++ b/ja/platform/sdks/nodejs/config-and-error-handling.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/observability.html b/ja/platform/sdks/nodejs/observability.html index b99538302..50db656da 100644 --- a/ja/platform/sdks/nodejs/observability.html +++ b/ja/platform/sdks/nodejs/observability.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/storage.html b/ja/platform/sdks/nodejs/storage.html index a0600bb06..987430218 100644 --- a/ja/platform/sdks/nodejs/storage.html +++ b/ja/platform/sdks/nodejs/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/style-guide.html b/ja/platform/sdks/nodejs/style-guide.html index 987feff59..1076088a6 100644 --- a/ja/platform/sdks/nodejs/style-guide.html +++ b/ja/platform/sdks/nodejs/style-guide.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/nodejs/topics.html b/ja/platform/sdks/nodejs/topics.html index eaf1dc090..718290890 100644 --- a/ja/platform/sdks/nodejs/topics.html +++ b/ja/platform/sdks/nodejs/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/php.html b/ja/platform/sdks/php.html index d7316fcd6..032aadbb3 100644 --- a/ja/platform/sdks/php.html +++ b/ja/platform/sdks/php.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/php/cache.html b/ja/platform/sdks/php/cache.html index 4888db62b..a65b1d294 100644 --- a/ja/platform/sdks/php/cache.html +++ b/ja/platform/sdks/php/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/php/storage.html b/ja/platform/sdks/php/storage.html index d50c859a9..b1b553b43 100644 --- a/ja/platform/sdks/php/storage.html +++ b/ja/platform/sdks/php/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/python.html b/ja/platform/sdks/python.html index a4acbf587..b31fa9824 100644 --- a/ja/platform/sdks/python.html +++ b/ja/platform/sdks/python.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/python/cache.html b/ja/platform/sdks/python/cache.html index 08f453fd3..137355b82 100644 --- a/ja/platform/sdks/python/cache.html +++ b/ja/platform/sdks/python/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/python/topics.html b/ja/platform/sdks/python/topics.html index 58b768551..068dd795f 100644 --- a/ja/platform/sdks/python/topics.html +++ b/ja/platform/sdks/python/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/ruby.html b/ja/platform/sdks/ruby.html index de5a9295b..0f74f905c 100644 --- a/ja/platform/sdks/ruby.html +++ b/ja/platform/sdks/ruby.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/rust.html b/ja/platform/sdks/rust.html index 6613d17b7..11407a952 100644 --- a/ja/platform/sdks/rust.html +++ b/ja/platform/sdks/rust.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/rust/cache.html b/ja/platform/sdks/rust/cache.html index c9476e47d..96c1f687f 100644 --- a/ja/platform/sdks/rust/cache.html +++ b/ja/platform/sdks/rust/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/rust/config-and-error-handling.html b/ja/platform/sdks/rust/config-and-error-handling.html index 18888d720..37e39e3a1 100644 --- a/ja/platform/sdks/rust/config-and-error-handling.html +++ b/ja/platform/sdks/rust/config-and-error-handling.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/rust/storage.html b/ja/platform/sdks/rust/storage.html index 6ba2db293..6f406c58d 100644 --- a/ja/platform/sdks/rust/storage.html +++ b/ja/platform/sdks/rust/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/rust/topics.html b/ja/platform/sdks/rust/topics.html index 8e081d512..ace3e30bc 100644 --- a/ja/platform/sdks/rust/topics.html +++ b/ja/platform/sdks/rust/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/swift.html b/ja/platform/sdks/swift.html index ab5aaaee1..e93f9fbbb 100644 --- a/ja/platform/sdks/swift.html +++ b/ja/platform/sdks/swift.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/swift/cache.html b/ja/platform/sdks/swift/cache.html index fa07a605c..0acee10d3 100644 --- a/ja/platform/sdks/swift/cache.html +++ b/ja/platform/sdks/swift/cache.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/swift/topics.html b/ja/platform/sdks/swift/topics.html index 0bf6617c1..6f0f95ed8 100644 --- a/ja/platform/sdks/swift/topics.html +++ b/ja/platform/sdks/swift/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/unity.html b/ja/platform/sdks/unity.html index 6b23386f4..ab1e0019c 100644 --- a/ja/platform/sdks/unity.html +++ b/ja/platform/sdks/unity.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/unreal.html b/ja/platform/sdks/unreal.html index 75431ba5a..7c7e1956f 100644 --- a/ja/platform/sdks/unreal.html +++ b/ja/platform/sdks/unreal.html @@ -9,7 +9,7 @@ - + diff --git a/ja/platform/sdks/web.html b/ja/platform/sdks/web.html index 5e2803ca9..be405f238 100644 --- a/ja/platform/sdks/web.html +++ b/ja/platform/sdks/web.html @@ -9,7 +9,7 @@ - + diff --git a/ja/search.html b/ja/search.html index 5e0c429e6..16a5f1b66 100644 --- a/ja/search.html +++ b/ja/search.html @@ -9,7 +9,7 @@ - + diff --git a/ja/storage.html b/ja/storage.html index b712c5e26..a3ca31f4f 100644 --- a/ja/storage.html +++ b/ja/storage.html @@ -9,7 +9,7 @@ - + diff --git a/ja/storage/develop.html b/ja/storage/develop.html index c73c653ba..a1fb1636a 100644 --- a/ja/storage/develop.html +++ b/ja/storage/develop.html @@ -9,7 +9,7 @@ - + diff --git a/ja/storage/develop/api-reference.html b/ja/storage/develop/api-reference.html index 192f8ed44..200b2ed87 100644 --- a/ja/storage/develop/api-reference.html +++ b/ja/storage/develop/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/ja/storage/develop/api-reference/language-support.html b/ja/storage/develop/api-reference/language-support.html index ab1966660..196d0a2ac 100644 --- a/ja/storage/develop/api-reference/language-support.html +++ b/ja/storage/develop/api-reference/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics.html b/ja/topics.html index 957f4c61d..de8b7e6ce 100644 --- a/ja/topics.html +++ b/ja/topics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/api-reference.html b/ja/topics/api-reference.html index 0085d2d7b..1e9b436d8 100644 --- a/ja/topics/api-reference.html +++ b/ja/topics/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/api-reference/auth.html b/ja/topics/api-reference/auth.html index 1e7ff73ee..ccbcf186a 100644 --- a/ja/topics/api-reference/auth.html +++ b/ja/topics/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/api-reference/http-api.html b/ja/topics/api-reference/http-api.html index eed7ae8a5..926bd9c6b 100644 --- a/ja/topics/api-reference/http-api.html +++ b/ja/topics/api-reference/http-api.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/api-reference/response-objects.html b/ja/topics/api-reference/response-objects.html index 4cd793e43..84615ad83 100644 --- a/ja/topics/api-reference/response-objects.html +++ b/ja/topics/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/api-reference/webhooks.html b/ja/topics/api-reference/webhooks.html index 89edbccdd..703986035 100644 --- a/ja/topics/api-reference/webhooks.html +++ b/ja/topics/api-reference/webhooks.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop.html b/ja/topics/develop.html index 1811a0445..350d39a80 100644 --- a/ja/topics/develop.html +++ b/ja/topics/develop.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/authentication.html b/ja/topics/develop/authentication.html index 2459ed3fb..5ed3acfc7 100644 --- a/ja/topics/develop/authentication.html +++ b/ja/topics/develop/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/authentication/api-keys.html b/ja/topics/develop/authentication/api-keys.html index e301a09c1..49948b152 100644 --- a/ja/topics/develop/authentication/api-keys.html +++ b/ja/topics/develop/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/authentication/permissions.html b/ja/topics/develop/authentication/permissions.html index 64fb5901c..002736057 100644 --- a/ja/topics/develop/authentication/permissions.html +++ b/ja/topics/develop/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/authentication/tokens.html b/ja/topics/develop/authentication/tokens.html index 5d7ddcd8c..2ef2174b4 100644 --- a/ja/topics/develop/authentication/tokens.html +++ b/ja/topics/develop/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html b/ja/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html index 9c1453411..36448bdd1 100644 --- a/ja/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html +++ b/ja/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/develop/language-support.html b/ja/topics/develop/language-support.html index 197acc932..fd1134b26 100644 --- a/ja/topics/develop/language-support.html +++ b/ja/topics/develop/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/integrations/aws-secrets-manager.html b/ja/topics/integrations/aws-secrets-manager.html index 52e59c761..a99745d5b 100644 --- a/ja/topics/integrations/aws-secrets-manager.html +++ b/ja/topics/integrations/aws-secrets-manager.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/integrations/lambda-handler.html b/ja/topics/integrations/lambda-handler.html index 7210502b0..f96615f09 100644 --- a/ja/topics/integrations/lambda-handler.html +++ b/ja/topics/integrations/lambda-handler.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/limits.html b/ja/topics/limits.html index 71ba7bb3e..d499099cb 100644 --- a/ja/topics/limits.html +++ b/ja/topics/limits.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/metrics.html b/ja/topics/metrics.html index 508c5a3e7..277c8267c 100644 --- a/ja/topics/metrics.html +++ b/ja/topics/metrics.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/patterns/instant-messaging.html b/ja/topics/patterns/instant-messaging.html index b3e54a823..bd7a522a5 100644 --- a/ja/topics/patterns/instant-messaging.html +++ b/ja/topics/patterns/instant-messaging.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/patterns/running-background-tasks.html b/ja/topics/patterns/running-background-tasks.html index 7e30be885..f40f59f44 100644 --- a/ja/topics/patterns/running-background-tasks.html +++ b/ja/topics/patterns/running-background-tasks.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/patterns/token_id_webhook.html b/ja/topics/patterns/token_id_webhook.html index 2b1adf52b..08616c67b 100644 --- a/ja/topics/patterns/token_id_webhook.html +++ b/ja/topics/patterns/token_id_webhook.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/webhooks/creating-a-webhook.html b/ja/topics/webhooks/creating-a-webhook.html index de6603e52..c6d4b2d62 100644 --- a/ja/topics/webhooks/creating-a-webhook.html +++ b/ja/topics/webhooks/creating-a-webhook.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/webhooks/overview.html b/ja/topics/webhooks/overview.html index ec11047b1..aa04b2c1f 100644 --- a/ja/topics/webhooks/overview.html +++ b/ja/topics/webhooks/overview.html @@ -9,7 +9,7 @@ - + diff --git a/ja/topics/webhooks/security.html b/ja/topics/webhooks/security.html index 27144a8b9..f054a14d8 100644 --- a/ja/topics/webhooks/security.html +++ b/ja/topics/webhooks/security.html @@ -9,7 +9,7 @@ - + diff --git a/language_support.html b/language_support.html index 51f5a8f52..3943fb3a3 100644 --- a/language_support.html +++ b/language_support.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards.html b/leaderboards.html index f50e95337..2ed24734b 100644 --- a/leaderboards.html +++ b/leaderboards.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/api-reference.html b/leaderboards/api-reference.html index 41774a33b..586ad0872 100644 --- a/leaderboards/api-reference.html +++ b/leaderboards/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/api-reference/auth.html b/leaderboards/api-reference/auth.html index 57718abba..bc8d6bcaa 100644 --- a/leaderboards/api-reference/auth.html +++ b/leaderboards/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/api-reference/response-objects.html b/leaderboards/api-reference/response-objects.html index 82f4588e4..25306ebe3 100644 --- a/leaderboards/api-reference/response-objects.html +++ b/leaderboards/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/language-support.html b/leaderboards/language-support.html index 203ee2c13..15eb90556 100644 --- a/leaderboards/language-support.html +++ b/leaderboards/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/limits.html b/leaderboards/limits.html index 166448aa5..ac1802405 100644 --- a/leaderboards/limits.html +++ b/leaderboards/limits.html @@ -9,7 +9,7 @@ - + diff --git a/leaderboards/patterns/map-id-to-string.html b/leaderboards/patterns/map-id-to-string.html index ebdf786a7..490ed5223 100644 --- a/leaderboards/patterns/map-id-to-string.html +++ b/leaderboards/patterns/map-id-to-string.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage.html b/media-storage.html index 4fd047f6f..bc138ee25 100644 --- a/media-storage.html +++ b/media-storage.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/concurrency/account-level.html b/media-storage/concurrency/account-level.html index cabbed66f..545f76a7b 100644 --- a/media-storage/concurrency/account-level.html +++ b/media-storage/concurrency/account-level.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/concurrency/devices.html b/media-storage/concurrency/devices.html index ea99f5c04..3e5b5258f 100644 --- a/media-storage/concurrency/devices.html +++ b/media-storage/concurrency/devices.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/core-concepts/abr-ladder.html b/media-storage/core-concepts/abr-ladder.html index c23a984b9..7971c1ef7 100644 --- a/media-storage/core-concepts/abr-ladder.html +++ b/media-storage/core-concepts/abr-ladder.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/core-concepts/origin.html b/media-storage/core-concepts/origin.html index 24dbe161f..897cc39e4 100644 --- a/media-storage/core-concepts/origin.html +++ b/media-storage/core-concepts/origin.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/core-concepts/segments.html b/media-storage/core-concepts/segments.html index 67589a927..cf1484edb 100644 --- a/media-storage/core-concepts/segments.html +++ b/media-storage/core-concepts/segments.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/core-concepts/zero-buffer-rate.html b/media-storage/core-concepts/zero-buffer-rate.html index d1d73c82c..f7e743d1c 100644 --- a/media-storage/core-concepts/zero-buffer-rate.html +++ b/media-storage/core-concepts/zero-buffer-rate.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/enhancements/heartbeats.html b/media-storage/enhancements/heartbeats.html index bd4983748..631afc8ae 100644 --- a/media-storage/enhancements/heartbeats.html +++ b/media-storage/enhancements/heartbeats.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/enhancements/live-reactions.html b/media-storage/enhancements/live-reactions.html index 6f4e7f2f2..6e816dbe9 100644 --- a/media-storage/enhancements/live-reactions.html +++ b/media-storage/enhancements/live-reactions.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/enhancements/viewer-metrics.html b/media-storage/enhancements/viewer-metrics.html index 14f0f33bb..b02c78f58 100644 --- a/media-storage/enhancements/viewer-metrics.html +++ b/media-storage/enhancements/viewer-metrics.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/entitlements/about.html b/media-storage/entitlements/about.html index b974ae741..aa1d3865a 100644 --- a/media-storage/entitlements/about.html +++ b/media-storage/entitlements/about.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/entitlements/real-time-updates.html b/media-storage/entitlements/real-time-updates.html index dc62e053b..c2fb899a8 100644 --- a/media-storage/entitlements/real-time-updates.html +++ b/media-storage/entitlements/real-time-updates.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/overview.html b/media-storage/overview.html index 862a1e081..068782558 100644 --- a/media-storage/overview.html +++ b/media-storage/overview.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/performance/adaptive-bitrates/dash.html b/media-storage/performance/adaptive-bitrates/dash.html index 9ca2d626f..874640ab6 100644 --- a/media-storage/performance/adaptive-bitrates/dash.html +++ b/media-storage/performance/adaptive-bitrates/dash.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/performance/adaptive-bitrates/hls.html b/media-storage/performance/adaptive-bitrates/hls.html index 543bef407..b953e38eb 100644 --- a/media-storage/performance/adaptive-bitrates/hls.html +++ b/media-storage/performance/adaptive-bitrates/hls.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/performance/adaptive-bitrates/how-it-works.html b/media-storage/performance/adaptive-bitrates/how-it-works.html index 54ced6563..3ed87ffa2 100644 --- a/media-storage/performance/adaptive-bitrates/how-it-works.html +++ b/media-storage/performance/adaptive-bitrates/how-it-works.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/performance/optimizing-delivery.html b/media-storage/performance/optimizing-delivery.html index aff8ecba1..dc96a54f7 100644 --- a/media-storage/performance/optimizing-delivery.html +++ b/media-storage/performance/optimizing-delivery.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/capture/rtmp.html b/media-storage/streaming/capture/rtmp.html index 382660695..70ac49704 100644 --- a/media-storage/streaming/capture/rtmp.html +++ b/media-storage/streaming/capture/rtmp.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/decoding-video.html b/media-storage/streaming/decoding-video.html index dfd86a097..c474a6e8b 100644 --- a/media-storage/streaming/decoding-video.html +++ b/media-storage/streaming/decoding-video.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/live-streaming/glass-to-glass-latency.html b/media-storage/streaming/live-streaming/glass-to-glass-latency.html index 6f48a706a..52f382113 100644 --- a/media-storage/streaming/live-streaming/glass-to-glass-latency.html +++ b/media-storage/streaming/live-streaming/glass-to-glass-latency.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/live-streaming/how-it-works.html b/media-storage/streaming/live-streaming/how-it-works.html index 2e3a1bc0f..3f354cf7c 100644 --- a/media-storage/streaming/live-streaming/how-it-works.html +++ b/media-storage/streaming/live-streaming/how-it-works.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html b/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html index ef13b082c..dcae7aa73 100644 --- a/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html +++ b/media-storage/streaming/live-streaming/how-to-medialive-cloudfront.html @@ -9,7 +9,7 @@ - + @@ -24,6 +24,9 @@
  • Testing and troubleshooting the setup to ensure smooth playback.
  • 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.

    +

    Preparation

    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 @@

    HLS. It is commonly used for live sports, major live events, and 24/7 channels.

    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.

    tip

    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>
    +

    Channel settings

    +

    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.

    +

    MediaLive channel settings page fully configured

    +

    Input attachments

    +

    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:

    +

    MediaLive completed input page

    +

    Once configured, hit the Create input button, navigate back to the channel configuration page, and select the input we just created.

    +

    Output groups

    +

    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 segments
    • ttl - number of seconds to retain the playlist and segments before deletion
    -

    Applying 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.

    AWS MediaLive console with channel configuration filled out

    In the Manifest and Segments section, configure the following fields:

      @@ -104,8 +121,17 @@

      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.

      CloudFront behavior for variant playlists

      -

      4. Playback and troubleshooting

      -

      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.

      +

      4. Starting the stream

      +

      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!

      +

      MediaLive channel in a playing status

      +

      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.

      +

      5. Watching the stream

      +

      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!

      +

      HLS player streaming our content

      +

      6. Troubleshooting

      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.

      MediaLive and Momento

      Verify the master manifest is accessible with player_api_key and returns the variant playlists correctly. Use the following curl command to test, or use the Momento console to view data in the namespace.

      @@ -147,7 +173,7 @@

      That's it!Discover how to use ffmpeg and an RTMP stream to stream to Momento.
    • Add real-time reactions to your streams.
    -

    We can't wait to see what you build. Happy coding!

    +

    We can't wait to see what you build. Happy coding!

    diff --git a/media-storage/streaming/overview.html b/media-storage/streaming/overview.html index 2ca2985dd..279cf7389 100644 --- a/media-storage/streaming/overview.html +++ b/media-storage/streaming/overview.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/streaming/video-on-demand/media-storage.html b/media-storage/streaming/video-on-demand/media-storage.html index dc9a0ebdc..c89e28406 100644 --- a/media-storage/streaming/video-on-demand/media-storage.html +++ b/media-storage/streaming/video-on-demand/media-storage.html @@ -9,7 +9,7 @@ - + diff --git a/media-storage/use-cases.html b/media-storage/use-cases.html index e0302f027..54088f71c 100644 --- a/media-storage/use-cases.html +++ b/media-storage/use-cases.html @@ -9,7 +9,7 @@ - + diff --git a/platform.html b/platform.html index 286e4db53..12a53b549 100644 --- a/platform.html +++ b/platform.html @@ -9,7 +9,7 @@ - + diff --git a/platform/connectivity/private-link.html b/platform/connectivity/private-link.html index efa647a10..01114f46a 100644 --- a/platform/connectivity/private-link.html +++ b/platform/connectivity/private-link.html @@ -9,7 +9,7 @@ - + diff --git a/platform/regions.html b/platform/regions.html index 47120951a..a6da204cd 100644 --- a/platform/regions.html +++ b/platform/regions.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks.html b/platform/sdks.html index 6f3913819..dff1c6b12 100644 --- a/platform/sdks.html +++ b/platform/sdks.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dart.html b/platform/sdks/dart.html index 917309a81..c1aaf80ae 100644 --- a/platform/sdks/dart.html +++ b/platform/sdks/dart.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dart/cache.html b/platform/sdks/dart/cache.html index 483a6716f..9dfcd4dc9 100644 --- a/platform/sdks/dart/cache.html +++ b/platform/sdks/dart/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dart/topics.html b/platform/sdks/dart/topics.html index a12d3fc40..20e8cb8b0 100644 --- a/platform/sdks/dart/topics.html +++ b/platform/sdks/dart/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dotnet.html b/platform/sdks/dotnet.html index 959b4a8fd..adab8488b 100644 --- a/platform/sdks/dotnet.html +++ b/platform/sdks/dotnet.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dotnet/cache.html b/platform/sdks/dotnet/cache.html index 7bed6da5b..f435f1260 100644 --- a/platform/sdks/dotnet/cache.html +++ b/platform/sdks/dotnet/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dotnet/observability.html b/platform/sdks/dotnet/observability.html index c7db8a884..47e440fb7 100644 --- a/platform/sdks/dotnet/observability.html +++ b/platform/sdks/dotnet/observability.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/dotnet/topics.html b/platform/sdks/dotnet/topics.html index 730e52b29..40e7d969a 100644 --- a/platform/sdks/dotnet/topics.html +++ b/platform/sdks/dotnet/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/elixir.html b/platform/sdks/elixir.html index af4c3f0fc..bcb5f5a02 100644 --- a/platform/sdks/elixir.html +++ b/platform/sdks/elixir.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/elixir/cache.html b/platform/sdks/elixir/cache.html index f334eff09..cf4cd2dfb 100644 --- a/platform/sdks/elixir/cache.html +++ b/platform/sdks/elixir/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/go.html b/platform/sdks/go.html index 26c172fd3..5f5cba7c4 100644 --- a/platform/sdks/go.html +++ b/platform/sdks/go.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/go/cache.html b/platform/sdks/go/cache.html index 9cea59e49..fc4689afb 100644 --- a/platform/sdks/go/cache.html +++ b/platform/sdks/go/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/go/storage.html b/platform/sdks/go/storage.html index f76ac537c..a77add47c 100644 --- a/platform/sdks/go/storage.html +++ b/platform/sdks/go/storage.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/go/topics.html b/platform/sdks/go/topics.html index 989562f23..9daeaac80 100644 --- a/platform/sdks/go/topics.html +++ b/platform/sdks/go/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/java.html b/platform/sdks/java.html index e7023aee4..a8e39de2a 100644 --- a/platform/sdks/java.html +++ b/platform/sdks/java.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/java/cache.html b/platform/sdks/java/cache.html index 517716a42..57010f3f3 100644 --- a/platform/sdks/java/cache.html +++ b/platform/sdks/java/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/java/storage.html b/platform/sdks/java/storage.html index fbe0fbe76..4d73827f2 100644 --- a/platform/sdks/java/storage.html +++ b/platform/sdks/java/storage.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/java/topics.html b/platform/sdks/java/topics.html index a688497e0..ec85024ec 100644 --- a/platform/sdks/java/topics.html +++ b/platform/sdks/java/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/kotlin.html b/platform/sdks/kotlin.html index 7a774fb31..3f8ca199e 100644 --- a/platform/sdks/kotlin.html +++ b/platform/sdks/kotlin.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/kotlin/cache.html b/platform/sdks/kotlin/cache.html index 7efeaa786..35c47e57b 100644 --- a/platform/sdks/kotlin/cache.html +++ b/platform/sdks/kotlin/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/kotlin/topics.html b/platform/sdks/kotlin/topics.html index bcfe2e7aa..fdfda23ec 100644 --- a/platform/sdks/kotlin/topics.html +++ b/platform/sdks/kotlin/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs.html b/platform/sdks/nodejs.html index 2ee745f22..0318ed14a 100644 --- a/platform/sdks/nodejs.html +++ b/platform/sdks/nodejs.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/cache.html b/platform/sdks/nodejs/cache.html index 85796a736..911769afd 100644 --- a/platform/sdks/nodejs/cache.html +++ b/platform/sdks/nodejs/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/compression.html b/platform/sdks/nodejs/compression.html index 5b98598d8..bba5ccd71 100644 --- a/platform/sdks/nodejs/compression.html +++ b/platform/sdks/nodejs/compression.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/config-and-error-handling.html b/platform/sdks/nodejs/config-and-error-handling.html index 3ee967e02..424353fcf 100644 --- a/platform/sdks/nodejs/config-and-error-handling.html +++ b/platform/sdks/nodejs/config-and-error-handling.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/observability.html b/platform/sdks/nodejs/observability.html index 4ecccb6dc..8ddd4e6ce 100644 --- a/platform/sdks/nodejs/observability.html +++ b/platform/sdks/nodejs/observability.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/storage.html b/platform/sdks/nodejs/storage.html index fb7ffe402..770d7bb93 100644 --- a/platform/sdks/nodejs/storage.html +++ b/platform/sdks/nodejs/storage.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/style-guide.html b/platform/sdks/nodejs/style-guide.html index fbfcf2619..a28d470a5 100644 --- a/platform/sdks/nodejs/style-guide.html +++ b/platform/sdks/nodejs/style-guide.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/nodejs/topics.html b/platform/sdks/nodejs/topics.html index b8bff35fd..fa2416317 100644 --- a/platform/sdks/nodejs/topics.html +++ b/platform/sdks/nodejs/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/php.html b/platform/sdks/php.html index ce890ac54..95acb05fe 100644 --- a/platform/sdks/php.html +++ b/platform/sdks/php.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/php/cache.html b/platform/sdks/php/cache.html index 065388f6a..38c2fb41c 100644 --- a/platform/sdks/php/cache.html +++ b/platform/sdks/php/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/php/storage.html b/platform/sdks/php/storage.html index 8e174f5b1..8be343975 100644 --- a/platform/sdks/php/storage.html +++ b/platform/sdks/php/storage.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/python.html b/platform/sdks/python.html index 4f7009541..3d2d9dab1 100644 --- a/platform/sdks/python.html +++ b/platform/sdks/python.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/python/cache.html b/platform/sdks/python/cache.html index 98ea660ff..c94d18217 100644 --- a/platform/sdks/python/cache.html +++ b/platform/sdks/python/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/python/topics.html b/platform/sdks/python/topics.html index 91ef6e4fd..afb0f6401 100644 --- a/platform/sdks/python/topics.html +++ b/platform/sdks/python/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/ruby.html b/platform/sdks/ruby.html index 6ababb3ad..d6a7122b0 100644 --- a/platform/sdks/ruby.html +++ b/platform/sdks/ruby.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/rust.html b/platform/sdks/rust.html index 29f092495..e0c852ff9 100644 --- a/platform/sdks/rust.html +++ b/platform/sdks/rust.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/rust/cache.html b/platform/sdks/rust/cache.html index 4bfcfa424..30bb0ae72 100644 --- a/platform/sdks/rust/cache.html +++ b/platform/sdks/rust/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/rust/config-and-error-handling.html b/platform/sdks/rust/config-and-error-handling.html index 62846e539..93214aeed 100644 --- a/platform/sdks/rust/config-and-error-handling.html +++ b/platform/sdks/rust/config-and-error-handling.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/rust/storage.html b/platform/sdks/rust/storage.html index 0b20fddf3..c278fc5fe 100644 --- a/platform/sdks/rust/storage.html +++ b/platform/sdks/rust/storage.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/rust/topics.html b/platform/sdks/rust/topics.html index a1c43635b..146db0ab0 100644 --- a/platform/sdks/rust/topics.html +++ b/platform/sdks/rust/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/swift.html b/platform/sdks/swift.html index d7f3a75c5..a893aba5f 100644 --- a/platform/sdks/swift.html +++ b/platform/sdks/swift.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/swift/cache.html b/platform/sdks/swift/cache.html index ae71046a6..f66cdc521 100644 --- a/platform/sdks/swift/cache.html +++ b/platform/sdks/swift/cache.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/swift/topics.html b/platform/sdks/swift/topics.html index 58aa2929e..08a4aa61b 100644 --- a/platform/sdks/swift/topics.html +++ b/platform/sdks/swift/topics.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/unity.html b/platform/sdks/unity.html index e43c5907c..488253b24 100644 --- a/platform/sdks/unity.html +++ b/platform/sdks/unity.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/unreal.html b/platform/sdks/unreal.html index 7abc072cd..736c7d92f 100644 --- a/platform/sdks/unreal.html +++ b/platform/sdks/unreal.html @@ -9,7 +9,7 @@ - + diff --git a/platform/sdks/web.html b/platform/sdks/web.html index 43410ee98..c064bb44b 100644 --- a/platform/sdks/web.html +++ b/platform/sdks/web.html @@ -9,7 +9,7 @@ - + diff --git a/search.html b/search.html index 99e287aab..128aaeee2 100644 --- a/search.html +++ b/search.html @@ -9,7 +9,7 @@ - + diff --git a/storage.html b/storage.html index 07bdeab09..25e8d6314 100644 --- a/storage.html +++ b/storage.html @@ -9,7 +9,7 @@ - + diff --git a/storage/develop.html b/storage/develop.html index 847e1dd83..bdfa09f0b 100644 --- a/storage/develop.html +++ b/storage/develop.html @@ -9,7 +9,7 @@ - + diff --git a/storage/develop/api-reference.html b/storage/develop/api-reference.html index 63ce996c9..3fe22b90f 100644 --- a/storage/develop/api-reference.html +++ b/storage/develop/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/storage/develop/api-reference/language-support.html b/storage/develop/api-reference/language-support.html index 7ade179f7..de9beadd6 100644 --- a/storage/develop/api-reference/language-support.html +++ b/storage/develop/api-reference/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/topics.html b/topics.html index 3e072731f..6d9e19559 100644 --- a/topics.html +++ b/topics.html @@ -9,7 +9,7 @@ - + diff --git a/topics/api-reference.html b/topics/api-reference.html index 87af0ed84..925a0a98c 100644 --- a/topics/api-reference.html +++ b/topics/api-reference.html @@ -9,7 +9,7 @@ - + diff --git a/topics/api-reference/auth.html b/topics/api-reference/auth.html index 409e6dbc7..1a2eeccfe 100644 --- a/topics/api-reference/auth.html +++ b/topics/api-reference/auth.html @@ -9,7 +9,7 @@ - + diff --git a/topics/api-reference/http-api.html b/topics/api-reference/http-api.html index a7c6169bd..d6b037240 100644 --- a/topics/api-reference/http-api.html +++ b/topics/api-reference/http-api.html @@ -9,7 +9,7 @@ - + diff --git a/topics/api-reference/response-objects.html b/topics/api-reference/response-objects.html index 40bbf47db..42a1f02f7 100644 --- a/topics/api-reference/response-objects.html +++ b/topics/api-reference/response-objects.html @@ -9,7 +9,7 @@ - + diff --git a/topics/api-reference/webhooks.html b/topics/api-reference/webhooks.html index 7c34ef6e2..4eddf3f0e 100644 --- a/topics/api-reference/webhooks.html +++ b/topics/api-reference/webhooks.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop.html b/topics/develop.html index d3323422c..3ff73114a 100644 --- a/topics/develop.html +++ b/topics/develop.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/authentication.html b/topics/develop/authentication.html index f070bfe01..037921e20 100644 --- a/topics/develop/authentication.html +++ b/topics/develop/authentication.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/authentication/api-keys.html b/topics/develop/authentication/api-keys.html index c7c1c8b01..2b06910ad 100644 --- a/topics/develop/authentication/api-keys.html +++ b/topics/develop/authentication/api-keys.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/authentication/permissions.html b/topics/develop/authentication/permissions.html index 8ffd9b2fe..23daf800e 100644 --- a/topics/develop/authentication/permissions.html +++ b/topics/develop/authentication/permissions.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/authentication/tokens.html b/topics/develop/authentication/tokens.html index ee1936af4..5c4365f33 100644 --- a/topics/develop/authentication/tokens.html +++ b/topics/develop/authentication/tokens.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html b/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html index c0d52d68f..e133653d3 100644 --- a/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html +++ b/topics/develop/guides/building-and-deploying-topics-listeners-on-aws.html @@ -9,7 +9,7 @@ - + diff --git a/topics/develop/language-support.html b/topics/develop/language-support.html index 5ff5c1f13..5a45cdd02 100644 --- a/topics/develop/language-support.html +++ b/topics/develop/language-support.html @@ -9,7 +9,7 @@ - + diff --git a/topics/integrations/aws-secrets-manager.html b/topics/integrations/aws-secrets-manager.html index 6fc198bfd..2ba6a6886 100644 --- a/topics/integrations/aws-secrets-manager.html +++ b/topics/integrations/aws-secrets-manager.html @@ -9,7 +9,7 @@ - + diff --git a/topics/integrations/lambda-handler.html b/topics/integrations/lambda-handler.html index d638b0c95..21cf6f8c1 100644 --- a/topics/integrations/lambda-handler.html +++ b/topics/integrations/lambda-handler.html @@ -9,7 +9,7 @@ - + diff --git a/topics/limits.html b/topics/limits.html index b5e6f38af..25e0b8bdf 100644 --- a/topics/limits.html +++ b/topics/limits.html @@ -9,7 +9,7 @@ - + diff --git a/topics/metrics.html b/topics/metrics.html index 13d4bd69d..9b183349d 100644 --- a/topics/metrics.html +++ b/topics/metrics.html @@ -9,7 +9,7 @@ - + diff --git a/topics/patterns/instant-messaging.html b/topics/patterns/instant-messaging.html index cf0f88218..7ece599c4 100644 --- a/topics/patterns/instant-messaging.html +++ b/topics/patterns/instant-messaging.html @@ -9,7 +9,7 @@ - + diff --git a/topics/patterns/running-background-tasks.html b/topics/patterns/running-background-tasks.html index db13c06f7..c1556130d 100644 --- a/topics/patterns/running-background-tasks.html +++ b/topics/patterns/running-background-tasks.html @@ -9,7 +9,7 @@ - + diff --git a/topics/patterns/token_id_webhook.html b/topics/patterns/token_id_webhook.html index aeb256e2e..a7f1d11a7 100644 --- a/topics/patterns/token_id_webhook.html +++ b/topics/patterns/token_id_webhook.html @@ -9,7 +9,7 @@ - + diff --git a/topics/webhooks/creating-a-webhook.html b/topics/webhooks/creating-a-webhook.html index 5203298f1..56d99d17e 100644 --- a/topics/webhooks/creating-a-webhook.html +++ b/topics/webhooks/creating-a-webhook.html @@ -9,7 +9,7 @@ - + diff --git a/topics/webhooks/overview.html b/topics/webhooks/overview.html index f766aaf87..5ab72e8e9 100644 --- a/topics/webhooks/overview.html +++ b/topics/webhooks/overview.html @@ -9,7 +9,7 @@ - + diff --git a/topics/webhooks/security.html b/topics/webhooks/security.html index 1ca28e12c..bff26b69d 100644 --- a/topics/webhooks/security.html +++ b/topics/webhooks/security.html @@ -9,7 +9,7 @@ - +