WWDC Quick Look 💓 By SwiftGGTeam
Deliver reliable streams with HLS Content Steering

Deliver reliable streams with HLS Content Steering

元の動画を見る

ハイライト

HLS コンテンツ ステアリングは、2022 年にパスウェイ クローン作成機能を追加します。ステアリング サーバーは、メイン プレイリストを再発行することなく、既存のクライアントに新しい CDN を動的にアナウンスできます。バケットベースのステートレス ルールでは、12 個の均一なランダム バケットを使用して正確なグローバル トラフィック スケジューリングを実現でき、ストリーミング メディアの運用とメンテナンスを「プレイリストの変更とプッシュの再開」から「リアルタイムで有効にする JSON ルールの変更」に進化させることができます。


主要内容

ストリーミング メディア配信には古い問題があります。それは、CDN がダウンしたらどうするかということです。従来のアプローチでは、メイン プレイリスト (マルチバリアント プレイリスト) を変更し、問題のある CDN 回線を削除し、予備の CDN 回線を追加して、次のクライアント要求が有効になるまで待機します。このプロセスは遅く、クライアントのリロードが必要で、「米国ユーザーの 30% をグレースケール検証のために新しい CDN に誘導する」などのきめ細かいトラフィック スケジュール設定を行うことができません。 (02:15)

HLS コンテンツ ステアリングはこの問題を解決します。その中心となるアイデアは、CDN をパスウェイに抽象化することです。各パスウェイは、同じ構造と同じコンテンツを持つバリアント フローのセットに対応します。クライアントは CDN の物理アドレスを気にする必要はありません。必要なのは、ステアリング サーバーからパスウェイの優先順位リストを取得し、それらを順番に試行することだけです。 (04:30)

Zheng Naiwei は、このセッションで 2 つのことについて話しました。1 つは、2021 年に導入されたコンテンツ ステアリング インフラストラクチャがどのように機能するか、もう 1 つは、2022 パスウェイ クローンとバケットベースのルールの 2 つの新機能です。前者は「メイン プレイリストを変更せずに新しい CDN を追加する方法」を解決し、後者は「グローバル トラフィック スケジューリングにステートレスな方法を使用する方法」を解決します。 (06:00)

Pathway Cloning は巧妙に設計されています。 CDN が動的に作成される場合 (たとえば、特定の地域のエッジ ノードがオンラインになったばかりの場合)、古いプレイリストを既に取得しているすべてのクライアントはその存在を知りません。従来のアプローチでは、次回クライアントがメイン プレイリストをリクエストするときに新しい CDN が追加されるのを待ちますが、これはすべての既存ユーザーがリロードを実行する必要があることを意味します。パスウェイ クローン作成により、ステアリング サーバーはステアリング マニフェストでクローン作成ルールを宣言できます。既存のパスウェイ (BASE-ID) に基づいて、HOST とパラメータを変更して新しいパスウェイ (ID) を生成します。それを受信した後、クライアントは URI の置換を完了し、新しい CDN にシームレスに切り替えます。 (12:30)

バケットベースのルールも重要なポイントです。ステアリング サーバーは、「どのクライアントがどの CDN に移動するか」を決定する必要がありますが、各クライアントの状態を維持することはできません。つまり、スケーラブルではありません。方法としては、RELOAD-URIにバケット番号として1から12までのランダムな整数を埋め込む。各クライアントには最初のリクエストでバケットがランダムに割り当てられ、後続のすべてのステアリング マニフェスト リクエストにはこの番号が含まれます。サーバーは、トラフィック分散の任意の割合を達成するために、バケット番号に基づいて異なる Pathway 優先順位リストを返すだけで済みます。 50/50 は、1 ~ 6 が CDN1 に送られ、7 ~ 12 が CDN2 に送られることを意味します。 10/30/60 は、1 が CDN1 に、2 ~ 4 が CDN2 に、5 ~ 12 が CDN3 に送られることを意味します。完全にステートレスで水平方向にスケーラブルです。 (18:00)


詳細

コンテンツ ステアリング インフラストラクチャのレビュー

(03:00) Content Steering には、Pathway、Steering Server、Steering Manifest という 3 つのコア概念しかありません。

パスウェイ は、同じ構造を持つ一連のバリアント フローの論理グループであり、通常は CDN に対応します。メインプレイリストで使用PATHWAY-ID各バリアント フローがどのパスウェイに属しているかをマークします。

#EXT-X-CONTENT-STEERING: SERVER-URI="/steering", PATHWAY-ID="CDN1"
#EXT-X-STREAM-INF: PATHWAY-ID="CDN1", BANDWIDTH=6000000
https://cdn1.example.com/high.m3u8
#EXT-X-STREAM-INF: PATHWAY-ID="CDN1", BANDWIDTH=3000000
https://cdn1.example.com/low.m3u8
#EXT-X-STREAM-INF: PATHWAY-ID="CDN2", BANDWIDTH=6000000
https://cdn2.example.com/high.m3u8
#EXT-X-STREAM-INF: PATHWAY-ID="CDN2", BANDWIDTH=3000000
https://cdn2.example.com/low.m3u8

SERVER-URI定期的にクライアントを送信するステアリング サーバーを指すアドレス (デフォルトは 300 秒ごと、またはRELOAD-URI) 内のパラメーターを使用して、このアドレスからステアリング マニフェストを要求します。

ステアリング マニフェスト は、サーバーから返される JSON ドキュメントです。構造は非常に単純です。

{
  "VERSION": 1,
  "TTL": 300,
  "RELOAD-URI": "https://steering.example.com/api/v1/steering?bucket=3",
  "PATHWAY-PRIORITY": ["CDN1", "CDN2"]
}

クライアントプレスPATHWAY-PRIORITY接続試行は次の順序で行われます。最初に CDN1 が試行され、CDN1 が使用できない場合は自動的に CDN2 にダウングレードされます。プロセス全体はプレーヤー層に対して透過的です。異なるパスウェイのバリアント ストリーム コンテンツはまったく同じであるため、AVPlayer はパスウェイを切り替えても再生を中断しません。 (07:45)

パスウェイクローニング: 新しい CDN を動的に導入する

(11:00) Pathway Cloning の前提は、古い Pathway と新しい Pathway の構造がまったく同じ (同じ数のバリアント ストリーム、同じコーデックと解像度の組み合わせ) であるが、URI が異なるということです。この前提の下では、サーバーはクライアントに「CDN3 の URI を取得するには、次のルールに従って CDN1 の URI を変更してください」と伝えるだけで済みます。

ステアリングマニフェストのクローン宣言:

{
  "VERSION": 1,
  "PATHWAY-PRIORITY": ["CDN3", "CDN1", "CDN2"],
  "PATHWAY-CLONES": [
    {
      "BASE-ID": "CDN1",
      "ID": "CDN3",
      "URI-REPLACEMENT": {
        "HOST": "cdn3.example.com",
        "PARAMS": { "token": "abc123" }
      }
    }
  ]
}

BASE-IDクライアントに既知のパスウェイであり、IDそれは新しいパスウェイの名前です、URI-REPLACEMENT置換ルールが定義されています。クライアントは、CDN1 のすべてのバリアント ストリームの HOST を次のように置き換えます。cdn3.example.com、プラス?token=abc123パラメータを使用すると、CDN3 の完全な URI セットを取得できます。 (14:20)

より細かく制御するには、次を使用できますPER-VARIANT-URISそしてPER-RENDITION-URIS。前者は特定のバリアント ストリーム (4K DV ストリームなど) に対して別のサーバーを指し、後者は特定のレンディション (英語の AC-3 オーディオ トラックなど) に対して別のサーバーを指します。

{
  "BASE-ID": "CDN1",
  "ID": "CDN3",
  "URI-REPLACEMENT": {
    "HOST": "cdn3.example.com",
    "PER-VARIANT-URIS": {
      "video-4k-dv": "https://faster.example.com/4k.m3u8"
    },
    "PER-RENDITION-URIS": {
      "audio-en-ac3": "https://faster.example.com/ac3.m3u8"
    }
  }
}

ここで使用されますSTABLE-VARIANT-IDそしてSTABLE-RENDITION-ID- メイン プレイリスト内の各バリエーション ストリームとレンディションに安定した識別子を割り当てます。ステアリング サーバーはこの ID を使用して特定の URI を見つけます。 (16:10)

バケットベースのグローバル トラフィック スケジューリング

(17:30) バケット メカニズムの主な設計目標は、サーバー側が完全にステートレスであり、すべてのスケジューリング決定がバケット番号のみに基づいていることです。

ワークフロー:

  1. クライアントが初めてステアリング マニフェストを要求し、サーバーがRELOAD-URIランダムなバケット番号 (1 ~ 12) を埋め込みます。
  2. クライアントからの後続のリクエストには、このバケット番号が送信されます。
  3. サーバーはバケット番号に従ってテーブルを検索し、対応するパスウェイ優先度を返します。

実装例:

# Steering Server 伪代码
BUCKET_MAP = {
    # 50/50 流量分配
    "cdn_split_50_50": {
        range(1, 7):  ["CDN1", "CDN2"],   # buckets 1-6 优先 CDN1
        range(7, 13): ["CDN2", "CDN1"],   # buckets 7-12 优先 CDN2
    },
    # 10/30/60 三路分配
    "cdn_split_10_30_60": {
        range(1, 3):  ["CDN1", "CDN2", "CDN3"],   # buckets 1-2: 约 17%
        range(3, 6):  ["CDN2", "CDN3", "CDN1"],   # buckets 3-5: 约 25%
        range(6, 13): ["CDN3", "CDN1", "CDN2"],   # buckets 6-12: 约 58%
    }
}

def handle_steering_request(bucket, known_pathways):
    rules = get_current_rules()
    priority = rules.lookup(bucket)

    # 确定需要克隆的 Pathway
    clones = compute_clones(known_pathways, priority)

    return {
        "PATHWAY-PRIORITY": priority,
        "PATHWAY-CLONES": clones
    }

ほとんどのシナリオでは、12 バケットの粒度で十分です。より詳細な制御 (1% グレースケールなど) が必要な場合は、クライアント属性 (地理的位置、デバイス タイプ) を組み合わせてサーバー側で追加の判断を行うことができますが、バケット自体は変更されません。 (20:30)

ステアリングサーバーの判定ロジック

(22:00) サーバーは、ステアリング マニフェストを生成するときに 2 つの質問に答える必要があります。

  1. **このバケットのクライアントは最初にどのパスウェイを選択する必要がありますか? **——バケットマッピングテーブルを確認してください。
  2. **どのパスウェイを複製する必要がありますか? ** - クライアントは、知っているパスウェイのリストを持ってきます (経由)SERVER-URIクエリ パラメーター)、サーバーはクライアントに既知のパスウェイから現在利用可能なすべてのパスウェイを差し引き、その差分が複製する必要があるものになります。
def compute_clones(known_pathways, desired_priority):
    needed = set(desired_priority)
    known = set(known_pathways)
    to_clone = needed - known

    clones = []
    for pathway_id in to_clone:
        # BASE-ID を選ぶ: known から同じ構造の Pathway を探す
        base = find_matching_base(pathway_id, known)
        clones.append({
            "BASE-ID": base,
            "ID": pathway_id,
            "URI-REPLACEMENT": get_replacement_rules(base, pathway_id)
        })
    return clones

この設計の利点は、サーバーがクライアントのプレイリストの特定の内容を知る必要がないことです。サーバーはパスウェイ ID の設定操作でのみ動作し、URI 置換ルールが事前に設定されています。 (24:00)


重要ポイント

  • 何をすべきか: HLS ストリーミング サービスにコンテンツ ステアリングを導入し、ハードコーディングされた CDN アドレスを Pathway 抽象化に置き換えます。 価値がある理由: CDN 障害が発生した場合、ステアリング サーバーは、マスター プレイリストを変更したり、クライアントのリロードを待ったりすることなく、すべてのクライアントのトラフィック パスをリアルタイムで切り替えることができます。 SLA 要件のあるライブ サービスおよびオンデマンド サービスの場合、これはアーキテクチャ レベルの信頼性の向上です。 開始方法: メインプレイリストに追加#EXT-X-CONTENT-STEERINGタグを使用して、ステアリング マニフェストを返す HTTP エンドポイントをデプロイし、最初に静的なPATHWAY-PRIORITYクライアントがパスウェイを正しく切り替えることができることを確認し、動的ルールを段階的に導入します。

  • 何をすべきか: パスウェイ クローン作成を使用して、動的オンラインおよびオフライン CDN、特にエッジ ノードの迅速な展開を実装します。 実行する価値がある理由: 従来の方法で CDN を追加するには、メイン プレイリストを変更し、CDN キャッシュが更新されるのを待ち、すべてのクライアントが再リクエストするのを待つ必要があります。プロセス全体には数十分かかる場合があります。パスウェイ クローン作成により、このステップがステアリング マニフェストからの 1 つの応答に短縮され、クライアントは次のリロード サイクルで新しい CDN を感知できます。 開始方法: 古い CDN と新しい CDN のバリアント ストリーム構造がまったく同じ (同じコーデック、解像度、ビットレートの組み合わせ) であることを確認し、ステアリング サーバーで新しい CDN の URI-REPLACEMENT ルールを構成し、パスします。PATHWAY-CLONESフィールド納品。

  • 対処方法: バケットベースのルールを使用してステートフル トラフィック スケジューリングを置き換え、ステアリング サーバーを純粋な機能にします。 実行する価値がある理由: ステートフル スケジューリングでは、各クライアントの状態を保存して同期する必要があるため、一貫性とスケーラビリティの問題が生じます。バケット メカニズムは URL 内のステータスをエンコードし、共有ストレージを必要とせずにサーバーを水平に拡張できます。 12 バケットでは約 8.3% のスケジューリング粒度が提供され、これはほとんどのシナリオに十分です。 開始方法: ステアリングマニフェスト内RELOAD-URIバケットにはランダムなバケット番号 (1 ~ 12) が埋め込まれます。サーバーはバケットからパスウェイ優先度までのマッピング テーブルを維持し、ビジネス要件 (グレー スケール、地域分布、CDN 容量) に従ってマッピング ルールを構成します。


関連セッション

コメント

GitHub Issues · utterances