新卒２年目が低遅延動画配信システムをAWSで構築して、既存の配信技術と比較してみた

# はじめに

本記事では、動画配信の低遅延化を実現する技術であるLow Latency HLS (LL-HLS)について解説し、AWSを用いた実装方法と検証結果を共有します。

私は2024年にエンジニアとして新卒入社し、2025年1月から動画配信システムの開発に携わっています。業務でLL-LHSを導入できないかとプライベートで調査を行ったものをまとめたものです。

動画配信技術は書籍等での情報が限られており、体系的な資料も少ないため、基礎知識から実装、検証結果まで包括的に解説します。

# 動画配信の基礎知識

## そもそも動画配信技術とは？

動画配信技術は用途や要件に応じて複数の規格が存在します。現在広く使用されている主要な技術を紹介します。

### RTMP（Real Time Message Protocol）
- 2002年にAdobeが開発
- Adobe Flash Playerとの高い互換性を持つ
- 現在は新しい技術への移行が進んでいる

### HLS（HTTP Live Streaming）
- 2009年にAppleが開発
- HTTP通信を利用した配信方式
- YouTube、Twitchなどの大規模配信サービスで採用
- オンデマンド配信とライブ配信の両方に対応

### WebRTC（Web Real Time Communication）
- 2011年にGoogleが主導して開発
- ブラウザ間の直接通信を実現
- Zoom、Google Meetなどのビデオ会議システムで採用

![スクリーンショット 2025-03-05 0.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/a58144f9-c6f0-4f60-80d9-ede7dd2d2a0d.png)
引用元：https://qiita.com/khayama/items/fe10e2068b53584cfbd6

## HLSの仕組み

HLS(HTTP Live Streaming)は、動画ファイルを一定の長さのセグメントに分割し、HTTP通信でクライアントに配信する技術です。クライアント側のプレイヤーは、セグメントの再生順序や時間情報が記載されたマニフェストファイルを参照して、連続的な再生を実現します。

HLSはAppleが開発した技術なので、英語ですが[Appleの公式のドキュメント](https://developer.apple.com/documentation/http-live-streaming)がわかりやすく参考になります。

![スクリーンショット 2025-03-03 21.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/2b35b589-cba1-47b7-a122-ba78032a0625.png)
引用元：https://developer.apple.com/documentation/http-live-streaming

## LL-HLSの概要

LL-HLS（Low Latency HTTP Live Streaming）は、2019年にAppleが発表したHLSの拡張規格です。従来のHLSで発生する10〜30秒の遅延を、2〜5秒程度まで短縮することを目的としています。

- 主な特徴
    - 従来のセグメント（2〜6秒）をさらに細かいパーシャルセグメント（0.1〜0.5秒）に分割
    - 従来のHLSとの後方互換性を維持
        - LL-HLSに対応していないクライアントでもHLSとして再生することが可能

- 対応環境
    - iOS 15.0以上
    - Android 2.16.1以上
    - 主要な動画プレイヤーライブラリ（hls.jsなど）

LL-LHSはHLSで分割した動画ファイル（セグメント）をさらに細かくしたパーシャルセグメントを作ります。

![スクリーンショット 2025-04-30 0.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/30d07780-20a3-4f21-a690-721f665b0cf2.png)
引用元：https://medium.com/@OvenMediaEngine/low-latency-hls-the-era-of-flexible-low-latency-streaming-ec675aa61378

従来のHLSよりもより細かく・頻繁に更新されることで遅延を短縮します。さらに、更新されたデータもCDNのキャッシュを効率よく使用できるように設計されています。

これにより、HLS（左）よりもLL-LHS（右）は単純に比較しただけで10秒程度遅延を短くすることができます。（他にも動画遅延が起こる原因は多々あるので、この議論はあくまでも単純化したものです。）
詳しい仕様は、[Apple WWD 19の動画](https://developer.apple.com/jp/videos/play/wwdc2019/502/)の動画で詳しく解説されています。

![スクリーンショット 2025-05-14 12.29.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/05ecd1de-c85f-4ca1-93a2-dc8a104d3b90.png)

# 今回の目的

現在の業務システムでは、AWS MediaLive 及び、AWS MediaPackageを使用してHLS形式でライブ配信を行っています。月間アクティブユーザーが50万人を超えるサービスで、1回の配信で数千人から数万人規模の視聴があります。

現状では数十秒程度の遅延が発生しており、以下の課題があります：

- 視聴者とのコメントによる円滑なインタラクティブなコミュニケーションが困難
- 番組開始時の待機映像（ふた映像）が長くなり、視聴者の離脱につながる可能性がある

本検証では、LL-HLSの導入による遅延時間の短縮効果を確認し、実際の業務で使う際の課題を明らかにすることを目的としています。

# 検証内容

本検証ではローカル環境でNTP時計の時間を表示させ、実際にリアルタイムに配信されているHLS配信・LL-HLS配信の時間を比較し、どれくらい遅延があるかを検証しました。

NTP時計は[NTP時計（ミリ秒）](https://narikakun.net/tool/ntp_ms.html)を使用しました。

また、配信切り替えソフト（OBS）で画面を切り替えた際にHLS配信・LL-HLS配信の画面でどれくらい切り替えのラグが発生するかを実際のスタジオからの配信を模擬する形で検証しました。

- 検証①：NPT時計を用いた遅延時間の比較
- 検証②：画面切り替え時のラグ

# （時間がない人用）：結果

## 遅延時間の比較

| **設定** | **HLS** | **LL-HLS** |
| --- | --- | --- |
| 初期設定 | 30.2秒 | 25.7秒 |
| 最適化後 | 26.3秒 | 7.0秒 |

## 画面切り替え時のラグ

OBSでのシーン切り替え（フェード効果300ms）を行った際の遅延

- HLS：26秒
- LL-HLS：7秒

# 検証環境の構築

## システム構成

業務に近い形での配信環境を模擬するために、スタジオからのライブ配信を仮定し、配信はCDNも含めた以下の構成で検証します。

また、LL-HLS配信を導入するにあたり、いきなりLL-HLS配信に全切り替えすることは現実的ではないです。そのため、同じ映像入力をHLS配信、LL-LHS配信の２つの異なるエンドポイントで出力するように設計しました。

検証環境は以下のコンポーネントで構成されています。

- AWS Elemental MediaLive：エンコーディングサービス
- AWS Elemental MediaPackage：パッケージングサービス
- Amazon CloudFront：コンテンツ配信ネットワーク（CDN）
- OBS Studio：配信ソフトウェア

![HLS.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/411bc613-0bc3-4a35-96d7-08404a448d9e.png)

## HLS配信システムの構築

AWS Elemental MediaPackageのv1で、`ll-hls-test`というチャンネルを作成しました。オリジンエンドポイントに対応するCloudFrontも作成しました。

![スクリーンショット 2025-04-26 17.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/0abed241-6b03-4f8b-b408-8cf359c57f07.png)

次に、AWS Elemental MediaLiveの設定を行います。こちらも同様にチャンネルを新規で作成します。この際に、出力グループを先ほど作成した、Media Packageのチャンネル`ll-hls-test` に設定しておきます。
MediaPackage v1を使用しているので、送信先を”HLS出力を使用します”の方にしておく必要があります。

今回は簡単のために、出力を1080pのみに設定しました。

このチャンネルにデフォルトの`MediaLiveAccessRole`を付与する必要があるので注意してください。

![スクリーンショット 2025-04-26 17.53.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/240068be-9301-4f67-a9ae-4d6f6df8c561.png)

入力アタッチメントはRTMP（プッシュ）形式で設定しました。
詳しくは、[【初心者】AWS Elemental MediaLive + MediaPackage を使ってみる（PCからのライブ配信）](https://qiita.com/mksamba/items/8d12957473d1cf06e7d6)を参照してください。
ここでは入力として、 `hls-test-input-obs` を作成しました。このエンドポイントに向けて、OBSの映像を出力させます。

![スクリーンショット 2025-04-26 18.03.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/948e58ae-8e4e-4550-8c74-fffed6abcae7.png)

OBS側の設定を行います。OBSにはオープンソースのOBS Studioを使用しました。
`hls-test-input-obs` のエンドポイントを配信情報に設定します。

![スクリーンショット 2025-04-26 17.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/ab7a94c4-85ad-4469-8d25-6fc0cd160fad.png)


## LL-HLS配信システムの追加

AWS Elemental MediaPackageのライブ v2にチャンネルグループ、チャンネルを新設します。今回は`ll-hls-test-2`グループ内に、`ll-hls-test-channel`を作りました。
2023年からライブ v2が新たにできて、LL-HLS配信はv2のみの対応になっています。

v2では、マニフェストファイルごとにオリジンエンドポイントを作成するようになっています。今回は`ll-hls-index`というマニフェストを作成して、これに対応するCloudFrontを作成しました。

![スクリーンショット 2025-05-13 12.52.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/dc4dc079-416f-405e-88a2-366cbf40eb05.png)
![スクリーンショット 2025-05-13 13.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/aadba110-a9b6-489d-bf3a-92564e67d8bb.png)

デフォルトではMediaPackageのエンドポイントポリシーが「ポリシーをアタッチしない」になっているので、パブリックに向けて公開したい場合は「パブリックポリシーをアタッチする」に変更してください。

![スクリーンショット 2025-04-27 9.07.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/d839c4a8-d388-465d-8d22-d9c58188ac36.png)

次に、MediaLiveの設定ですが、先ほど作成した`lhs-test`チャンネルの出力グループにLL-HLS用のMediaPackageのグループを追加します。
MediaPackage v2を使用しているので、送信先を”CMAFインジェスと出力をします”の方を選択するように注意してください。

![スクリーンショット 2025-04-27 0.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/89bb80c3-43ca-48f1-9750-509247d458d1.png)

CMAF出力の場合は映像と音声を別々の出力に設定しなければいけません。デフォルトの設定では1出力に対して、映像と音声が設定されている状態になり、画像のようなエラーが出ます。今回は簡単のために、映像のみを出力の設定にしました。

![スクリーンショット 2025-05-14 17.29.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/985ee7d3-ce64-446c-a137-386c3f310955.png)

# 結果

## 検証①（初期設定）

初期設定の場合は、以下のような結果になりました。

画像の右上がLL-HLS、右下がHLS、左側がOBSの画面です。

LL-HLS配信では3-5秒程度の遅延に抑えられるとのことでしたが、初期設定ではHLS配信よりも5秒程度早くなる結果しか得られませんでした。

|  | HLS | LL-HLS |
| --- | --- | --- |
| 遅延秒数（初期設定） | 30.2秒 | 25.7秒 |

![スクリーンショット 2025-05-14 11.48.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/4e1de85f-895d-4430-9775-062cec85f5a9.png)

## 検証①（最適化後）

LL-HLS配信設定のパラメータを調整して、さらに低遅延になるように調整します。
前述の通り、LL-HLS配信はHLS配信よりも動画ファイルのセグメントを小さくすることで、遅延を短くしています。

そこでMediaPackageのセグメント期間を10秒→1秒に変更します。

![スクリーンショット 2025-05-14 17.29.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/b06460f5-8b60-4871-99fe-b18b2f077a50.png)

また、セグメント長を短くするために、MediaLiveの出力設定の「GOPの構造」のGOPサイズ単位をFRAMES、GOPサイズを1, Bフレーム数を0に変更しました。（MediaLiveの出力にMediaPackageを選択していると、セグメント長などを細かく設定することができません。）

![スクリーンショット 2025-05-14 17.31.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/a326972e-e898-4c01-8a7b-528ea24850e4.png)

最適化後の結果が以下の通りです。
最適化の結果、LL-HLS配信の遅延が7.0秒に抑えられました。HLS配信の遅延よりも19秒程度早くなりました。
HLS配信の方も26.3秒とチューニング前よりも約4秒下がる結果になりました。ネットワークの回線状況によるものだと考えられます。

|  | HLS | LL-HLS |
| --- | --- | --- |
| 遅延秒数（最適化後） | 26.3秒 | 7.0秒 |

![スクリーンショット 2025-05-14 11.54.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/c47e42d7-b760-46c5-8560-a5c685ef8b9b.png)

## 検証②（最適化後）

ストップウォッチが6秒時点で、OBSのシーンを変更した時に、HLS配信、LL-HLS配信でどれだけ切り替えに時間がかかるか検証しました。
結果は以下の通りです。

|  | HLS | LL-HLS |
| --- | --- | --- |
| 切り替えのラグ（最適化後） | 26秒 | 7秒 |

先ほどと同様に、画像の右上がLL-HLS、右下がHLS、左側がOBSの画面です。
13秒時点でLL-HLSの画面が切り替わり、32秒時点でHLSの画面が切り替わりました。

![スクリーンショット 2025-05-14 11.56.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/eb8329be-3536-4408-ad29-50d9782d9dfe.png)
![スクリーンショット 2025-05-14 11.59.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/9e25fa00-5275-45aa-a9b7-b0a78b673226.png)

## コスト考察

最後に導入にあたってのコストについて議論します。

- MediaPackage v2の利用自体に追加コストは発生しない
- 検証期間中は既存のHLS配信と並行して運用するため、一時的に配信コストが2倍になる
- セグメント長の短縮によりCloudFrontへのアクセス頻度が増加し、CDNコストが上昇する可能性がある

既存のHLS配信をLL-LHS配信に切り替えるにあたって、MediaPackage v2を使用するのに追加のコストはかかりません。そのため、検証期間のみHLS配信の2倍の配信費用がかかると考えれば良いと思います。

https://aws.amazon.com/jp/about-aws/whats-new/2023/05/aws-elemental-mediapackage-low-latency-hls/?t

ただし、LL-LHS配信に切り替えることで、動画のセグメントが短くなるため、CloudFrontへのアクセス頻度が増えることでCloudFrontの費用が増加する可能性があります。

今回の検証では短時間の配信かつ、アクセス数が1なので費用が増大することは確認できませんでしたが、大規模なサービスで使用する場合はこのあたりのコストの増加を考慮する必要があるかもしれません。

## <font color="red">**（2025/5/23追記） OBSの配信出力設定による影響**</font>
@nnkanegon にコメントいただき、追記しました。

本記事ではOBS Studioの出力設定の「キーフレーム間隔」をデフォルトの「0=自動」設定にしていました。@nnkanegonによると、この設定では配信される.tsファイル（セグメントファイル）が6~8秒単位で生成されるとのことです。
OBSのキーフレーム間隔を1sに設定すると、HLS配信でも遅延が5秒以内になったそうです。

![スクリーンショット 2025-05-23 14.12.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348580/03850b35-6e4d-45a3-81df-94e80d9a4a8e.png)


以下が@nnkanegonさんの[記事の抜粋](https://qiita.com/nnkanegon/items/5814b7d1210902321e96)です。他の方の参考になれば幸いです。

> キーフレーム間隔は「出力モード」を「詳細」に切り替えないと設定欄が表示されないので注意してください。
OBS ではキーフレーム間隔の初期値が (0=自動) となっています。このまま配信を行うと、配信から視聴まで 30 秒程度の遅延が発生します。1 秒とすることで遅延を数秒程度まで抑えられます。キーフレームは画質に影響するようですが、今回は低遅延を優先して 1 秒に設定します。
必要があれば、解像度、ビットレート、CPU使用のプリセットなども設定します。


本記事のケースでは、おそらくOBS側での出力がデフォルトのままであったので、後続のMediaLiveとMediaPackageの設定でセグメントファイルを短く設定していても反映されずに、HLS配信で遅延が30秒程度出てしまったのだと考えられます。
私もこの部分を考慮して、今後、再検証してみたいと思います。


# 結論と今後の展望

本検証により、LL-HLSの導入で遅延時間を約7秒まで短縮できることを確認しました。これは従来のHLS配信と比較して約19秒の改善となります。

- 今後の課題と展望
    - CMAFインジェストグループの詳細な設定によるさらなる遅延短縮の可能性検討
    - 大規模配信時のCDNコストの詳細な試算
    - 実際の業務システムに組み込んだ時の遅延の評価
    - クライアント側の再生環境の互換性検証