MediaLiveとNLBでRTMPSによるストリーミングをしてみた

MediaLiveではRTMPの入力に対応していますが、暗号化されたRTMPSには対応していません。RTMPSをNLBでTLS終端させ、RTMPとしてMediaLiveに入力するアーキテクチャでRTMPSによるストリーミングが可能です。
2022.10.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

清水です。AWS Media Blogで「AWSでRTMPSストリーミングを行う」という大変興味深いエントリがポストされていました。

AWS Elemental MediaLiveとAWS Elemental MediaPackageを利用したライブ動画配信の構成なのですが、Streaming Software(OBS Studio)からAWSへの入力をRTMPSでできるようにしています。

RTMPS Streaming with AWS | AWS Media Blog

AWS Elemental MediaLiveでは一般的なRTMPでのライブソースの入力に対応しています。YouTube LiveやFacebook Live、Twitchなど多くの動画配信プラットフォームと同じ形式ですね。(なお、MediaLiveでは一般的なRTMPでの入力方式であるRTMP pushのほか、RTMP pullについてもサポートしています。)

ところで、RTMPにはSSL/TLSを用いて暗号化を行うRTMPSという拡張仕様があります。動画配信プラットフォームの多くではこのRTMPS形式にも対応していたのですが、MediaLiveのRTMP入力形式ではRTMPのみの対応でRTMPSには非対応という状況でした。(ただし、MediaLiveでは暗号化が一切できないわけではなく、他プロトコルを使ったりAWS Elemental MediaConnectと連携するなどといった手段で入力ストリームの暗号化には対応していました。)

今回「MediaLive自体がRTMPSでの入力に対応した」というわけではないのですが、AWS Media BlogのエントリではMediaLive Inputの前段にNLB (Network Load Balancer)を配置、Streaming SoftwareからのRTMPS通信をNLBでTLS終端させてMediaLiveにRTMPで渡す構成を紹介しています。個人的にRTMPSがRTMPをSSL/TLSで暗号化したもの、という理解はしていたのですが、NLBでTLS終端させるという手段があったか!と、このAWS Media Blogのエントリを読んで驚愕しました。本エントリでは、この「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」という構成を実際に検証してみたのでまとめてみたいと思います。

Architecture Deep Dive

アーキテクチャの概要は冒頭で引用したAWS Media Blogのエントリの通りとなりますが、この構成についてもう少し深追いしてみます。NLBでRTMPSのTLSを終端させてRTMPとしてMediaLiveの入力とする、ということに変わりはないのですが、NLBの配置やMediaLive Inputに用いるVPCの構成についてもまとめると以下のようになります。

Streaming SoftwareからのRTMPSの入力はインターネットを介して行われる想定です。そのため、Public Subnetに配置したNLBでRTMPSの入力を受け付けます。NLBでTLSを終端させたあとの、MediaLiveへのInputはインターネットを介すべきではありません。MediaLiveのInputリソースはVPC Mode(VPC Input)で作成します。このMediaLiveのVPC ModeのInput(VPC Input)についてはインターネットへの経路は必要ないため、Private Subnetに配置することとしました。このPrivate SubnetにはNAT Gatewayへの経路もなく、インターネットとの通信は不可の状況です。

MediaLiveのOutput以降については、RTMPS入力とは分離して設計することが可能であるため、通常のRTMP入力などと同じようにMediaPackageのほか、MediaLiveで利用できる任意のOutputが選択可能となります。

Streaming SoftwareからNLBへの接続の部分についても確認しておきましょう。NLBでのTLS終端のため、独自ドメインならびにSSL/TLS証明書を準備します。Streaming Softwareからはこの独自ドメイン(例としてlive.example.com)に対してRTMPSで映像を打ち上げます。この独自ドメインlive.example.comにはDNSでNLBへのレコードを登録しておきます。またNLBにはlive.example.comに対応した証明書を設定しておき、live.example.comで接続した際のTLS終端ができるようにしておきます。ここで証明書の発行、管理にはAWS Certificate Manager (ACM)を使用し、またドメインについてのDNS管理にはAmazon Route 53を使う、という構成になっています。

MediaLiveとNLBでRTMPSによるストリーミング環境を構築する

では実際に上記アーキテクチャを実装していき、MediaLiveとNLBによるRTMPSストリーミングをやってみたいと思います。今回は動作検証ということで、MediaLiveはSINGLE_PIPELINEオプションを使用した冗長性を持たない構成としました。Input Failoverについても設定せず、1つのChannelに1つのInputのみが紐付いている状態です。またNLBについても冗長性を持たせず、1つのAZのみを使用する構成としています。

VPCならびにサブネットの詳細構成は以下となります。今回、PrivateSubnetはNAT Gatewayなどへの経路を持たず、インターネットへの接続不可のサブネットとしています。また本エントリではVPCやサブネットの作成についての手順については省略し、Security Groupの作成から進めます。

Security Groupの作成

まずはSecurity Groupの作成から進めます。今回の構成でVPC内に配置するリソースはNLBとMediaLive VPC Inputがありますが、NLBについてはSecurity Groupを設定できません。後続のリソース、今回であればMediaLiveのVPC InputへアタッチするSecurity Groupで通信を制御する必要があります。またNLBを含んだ構成でのSecurity Groupルール設定についてはいくつか考慮する必要があります。詳細は以下のブログエントリなどを参照ください。

MediaLiveのVPC InputにアタッチするSecurity Groupについては、Inbound ruleでMediaLive VPC Inputへの入力となるRTMP1935ポートへの通信を許可するよう設定します。IPアドレスによるアクセス制限を実施したいため、Streaming Softwareのアクセス元となるIPアドレスを通信許可対象として設定します。(後述しますが、この他にNLB Target GroupでのクライアントIPアドレス保持についても設定が必要です。)またNLBからのHealth Check用の通信を許可するため、使用するVPCのCIDR(10.100.0.0/16)を通信許可対象のIPアドレスとして指定しました。(今回は使用するVPC全体を許可対象としましたが、より厳密に制御するのであれば、NLB配置のサブネットのみとすることも可能です。)Outbound ruleについてはデフォルトのままとしています。

MediaLiveでVPC Inputの作成

続いてMediaLiveでVPC Input(RTMPのVPC modeのInput)を作成します。MediaLiveのマネジメントコンソール、Inputsの画面の[Create input]ボタンで進みます。Input nameを適切に設定し(今回はrtmps-medialive-inputとしました)、Input typeではRTMP (push)を選択します。

Network modeではVPCを選択します。VPC settingsの項目でSubnetとSecurity Groupを選択します。Subnetは構築済みのPrivate Subnet、Security Groupは先ほど作成したものですね。なおSubnet設定の箇所に「2つの異なるAZのSubnetを指定する」ように記載されていますが、後述のとおりInput classをSINGLE_INPUTとしてAZを1つのみ使用する設定であれば、1つののSubnetのみの指定でも問題ないようでした。

Input destinationsのInput class指定ではSINGLE_INPUTを選択しました。後ほど作成するMediaLive ChannelのPipelineもSINGLE_PIPELINEを選択するようにします。今回は動作検証目的であるため、Pipelineの冗長性は不要としました。

MediaLiveのVPC Inputが作成できました。Endpointsに表示されているIPv4アドレスは後ほどNLB作成時に使用しますので控えておきましょう。Input security groupsの項目は空欄となっていますが、こちらはVPC ModeでないInputに対応するSecurity groupとなります。実際にこのVPC InputにアタッチされているSecurity Groupについては、Network interface IDをもとにEC2のマネジメントコンソールでNetwork Interfaceの詳細を参照することで確認することができます。

NLBの作成

MediaLiveのInputが作成できたので、続いてNLBの作成に進みます。まずTarget Groupを作成し、その後NLB本体の作成を行います。

Target Groupの作成

EC2のマネジメントコンソール、Target Groupsの項目の[Create target group]ボタンから進みます。Basic configrationではIP addressを指定します。

Target Group nameはrtmps-nlb-targetgroupとしました。このTarget GroupではRTMPSを受けるのではなく、TLS終端後のRTMPを扱いますのでProtocol:PortはTCP:1935と設定します。VPCはMediaLive VPC Inputを作成したVPCを指定、Health checksの項目についてはデフォルトのまま、[Next]ボタンで次ページに進みます。

Register targetsの項目で、先ほど作成したMediaLive VPC InputのIPアドレスを入力します。その後[Include as pending below]ボタンを押下することでページ下部のTargetsに追加されます。

Target Groupが作成できました。

Attributesのタグを確認します。クライアントIPアドレスの保持機能が無効(Off)になっているので、こちらを有効(On)にしておきます。これでSecurity GroupでのIPアドレスによるアクセス制限が可能になります。

NLB本体

続いてNLB本体の作成です。マネジメントコンソールLoad Balancersのページから[Create Load Balancer]ボタンで進み、Network Load Balancerを選択します。

名称はrtmps-nlbとしました。SchemeはInternet-facing、IP address typeはIPv4で進みます。

Network mappingではMediaLive VPC Inputを作成したのと同じVPCを指定します。またSbunetについて、NLBについてはPublic Subnetに配置しますので該当のSubnetを指定します。

Listeners and routingの項目では、Protocol:PortでTLS:443を指定します。ここでRTMPSを受け付けてTLS終端を行い、先ほど作成したTarget Group rtmps-nlb-targetgroupにルーティングします。

Secure listener settingsの箇所、今回使用する独自ドメインに対応したACM証明書を指定します。(ACM証明書の取得などについては本エントリでは手順を省略します。)またALPN policyではHTTP2Preferredを選択します。

作成できました。作成直後はStateがProvisioningですが、作成が完了するとActiveとなります。

Route 53でDNSレコード登録

今回作成したNLBを独自ドメインで利用するため、Route 53でDNSレコードを登録しておきます。Route 53のレコード登録画面でサブドメインを指定、Record typeはAレコードとしてAliasを設定します。A ALIASレコードの利用ですね。(CNAMEでの登録も可能ですが、A ALIASのほうがパフォーマンスがよく、コストも抑えることができます。)

Route traffic toの項目でNLBへのAliasを選択、該当のリージョン(今回はap-northeast-1)とNLB(先ほど作成したもの)を選択してDNSレコードを登録します。

MediaLiveのOutput以降のリソースの作成

本エントリの主題である「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」部分までの構築が終わりました。MediaLiveのOutput以降のリソースについては任意のものが利用可能となりますが、今回はMediaLiveのWorkflow wizardを使ってMediaPackage、CloudFrontのリソースを作成、HLSで実際にRTMPSで打ち上げた映像を視聴確認できるようにします。

MediaLiveのマネジメントコンソール、Workflow wizardの画面から[Create workflow]ボタンで進みます。Workflow nameはrtmps-medialive-workflowとしました。channel classはSINGLE_PIPELINEを選択、IAM roleについても指定します。

input typeはRTMP (push)を選択し、User an existing inputで作成済みのrtmps-medialive-inputを指定します。

OutputはMediaPackageを選択します。Channelを新規に作成し、Video renditionsは検証用途ですので720p30の1つのみとしました。

Workflowが作成できました。

MediaLiveとNLBでRTMPSによるストリーミング環境を行う

Streaming Softwareから受け取ったRTMPSをTLS終端させるNLB、NLBからRTMPで映像を受け取るMediaLive、そして視聴用のリソース(MediaPackageとCloudFront)の作成ができました。それでは実際にStreaming SoftwareからRTMPSで映像を打ち上げて、ストリーミングでの映像視聴ができるか確認してみたいと思います。

MediaLive ChannelのStart

MediaLiveのWorkflow wizardでリソースを作成した直後は、Channelは停止しているIdleの状態です。

そのため、NLB Target GroupのHealth statusとしてもunhealthyとなりHealth Checkに失敗している状態となります。

WorkflowをStartさせます。(連動して、MediaLive ChannelがStartします。)それぞれがRunning状態になり、その後NLB Target Groupを確認してみると、Health statusがhealthyとなり、Health Checkに成功していることが確認できます。これで準備完了です。

Streaming SoftwareからRTMPSで映像を打ち上げ

AWS側の準備ができたので、続いてStreaming SoftwareからRTMPSで映像を打ち上げます。Streaming Softwareとして、今回はiPhone XS上のZixi ONAIRを使用しました。RTMP SettingsのURLをrtmps://ではじめることで、RTMPSを指定します。

打ち上げた映像のストリーミング視聴確認

実際にRTMPSで打ち上げた映像を、ストリーミング視聴してみます。今回はHLS形式で確認し、再生PlayerにはmacOS上のSafariブラウザを使用しました。

再生用EndpointをAWSマネジメントコンソールから確認していきます。MediaLive WorkflowのMediaPackage HLS Endpointの「Link to resource」に続くリンクをクリックして、MediaPackageの画面に遷移します。

CloudFront URLをコピーして、Safariブラウザで開きます。

問題なく視聴できていますね!

まとめ

AWS Media Blogで紹介されていた「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」方法を、実際に構築して確認してみました。NLBそしてMediaLiveのVPC対応を上手に活用したソリューションだなと思います。MediaLive InputはVPC Modeである必要があること、VPC内での各リソースの配置、NLBがSecurity Groupを持たずMediaLive VPC InputにアタッチするSecurity GroupでIPアドレスなどのアクセス制限を行う必要があること、などに注意しておきましょう。

また今回は動作検証目的として、MediaLiveをSingle Pipeline構成、NLBも単一AZとしました。本番構成では冗長化が必須です。MediaLiveで冗長構成をとった際のNLB側の構成について、例えばMulti-AZ構成としたほうが良いのかなど、検討しておきたいと思いました。