Skip to content

Instantly share code, notes, and snippets.

@voluntas
Last active October 22, 2023 12:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voluntas/ae72f30a5bf8db7918cd2237edd3fc50 to your computer and use it in GitHub Desktop.
Save voluntas/ae72f30a5bf8db7918cd2237edd3fc50 to your computer and use it in GitHub Desktop.
時雨堂 WebRTC SFU Sora & Sora Cloud 入門 (講師用資料)

時雨堂 WebRTC SFU Sora & Sora Cloud 入門 (講師用資料)

これは時雨堂が開催しているオンラインイベントである WebRTC SFU Sora & Sora Cloud の 講師用 の資料であり、 参加者用の資料ではありません。

概要

時雨堂が開発し提供している WebRTC SFU Sora とそのクラウド版である Sora Cloud を一通り紹介するための講師用の資料です。

これを機会に多くの商用環境で利用されている WebRTC SFU Sora について学んでほしいと考えています。

進め方

まず最後まで大まかに話をしていきます。その後、残り時間を利用して、細かく話をしていきます。

資料表示用の画面と iPad を画面共有してホワイトボード的な使い方をしていきます。

お願い

是非 Discord にメモを残していってください。 後から振り返るとき、参加者の皆に有用だと思います。

ライセンス

Creative Commons — 表示 - 非営利 - 改変禁止 4.0 国際 — CC BY-NC-ND 4.0

参考書

注意事項

  • 競合他社製品との比較は行いません
  • OSS との比較は行いません

WebRTC とは

WebRTC がわからない人向けに簡単に説明します

  • WebRTC はブラウザ間で P2P で音声や映像、データをやりとりするための仕組みです
  • 基本的に UDP が利用されています
  • 音声や映像を超低遅延 (200 ミリ前後) で送受信できる仕組みです
  • テキストやバイナリデータも低遅延で送る事ができます

WebRTC 用語解説

用語を学ぶことはとても大事です

全く知らない用語がバンバンでてくると聞いていてよくわからなくなってきます。 それを防ぐために、WebRTC でよく使われる単語について説明していきます。

P2P

WebRTC はブラウザ同士が直接音声や映像をやりとりする仕組みという知識の方が多いかと思いますが、それで合っています。まずはその知識は合っていると言うことは覚えておいてください。

メディアトランスポート

WebRTC といえば音声と映像のリアルタイム配信です。それを WebRTC ではメディアトランスポートと呼びます。

後述するデータチャネルが「バイナリなら何でも」なのになぜ音声と映像は特別扱いなのでしょうか?それは単に「音声と映像」は「圧縮する仕組み」や「再送する仕組み」などリアルタイムに音声と映像を扱うには独自の仕組みが必要になるためです。

音声と映像をリアルタイムにインターネット経由で送受信するのはそう簡単ではないということを覚えてください。

メディアトランスポートは基本的に UDP を利用します。

データチャネル

データチャネルはどんなデータでも送れます。ただ音声と映像はメディアトランスポートを利用する事がほとんどです。

さらにサーバに保存するデータなどはデータチャネルから取り出して保存するというのにあまり向いていません。基本的にはデータを保存するのではなく使い捨てるようなデータを使うのに向いています。

データチャネルは TCP のように確実に届けて、かつ順番保証されるという仕組みと、UDP のように確実に届けず、かつ順番保証されないという仕組みを選べます。

データチャネルは再送の回数や再送時間も指定できます。つまり TCP と UDP の美味しいところを利用できる仕組みです。

データチャネルはメディアトランスポートと同様、基本的に UDP を利用します。

STUN/TURN

WebRTC は UDP を前提としたプロトコルのため「UDP が通らない」とか「NAT 化にいる」とかで通信ができないことがあります。

それを解決するのが STUN と TURN です。STUN は「自分の IP アドレスがグローバルなサーバーからはどう見えるのか」を判断する仕組みです。

実装的にはとてもシンプルで受け取った UDP パケットの src ip/src port をレスポンスに入れて返すだけです。

TURN は STUN プロトコルの一種ではありますが、仕組みは全く違います。例えば自分が UDP を受け取れない場合は「代わりに UDP を受け取ってくれる代理サーバー」をグローバルに用意する仕組みです。

相手は UDP をその代理サーバに送り、代理サーバーは TCP で受け取ったパケットを自分に送ってくれるという仕組みです。

sequenceDiagram
  participant c1 as クライアント1
  participant t2 as TURN (クライアント 2 代理)
  participant t as TURN
  participant t1 as TURN (クライアント 1 代理)
  participant c2 as クライアント2

  c1->>+t: Allocation Request
  t-)t1: Allocation IP/Port
  t->>-c1: Allocation Success

  c1->>+t: Permission Request
  t->>-c1: Permission Success

  c1->>+t: Channel-Binding Request
  t->>-c1: Channel-Binding Success

  c2->>+t: Allocation Request
  t-)t2: Allocation IP/Port
  t->>-c2: Allocation Success

  c2->>+t: Permission Request
  t->>-c2: Permission Success

  c2->>+t: Channel-Binding Request
  t->>-c2: Channel-Binding Success

  note over c1,c2: WebRTC 確立

  par
    c1-)t2: SRTP over ChannelData over TCP
    Note over t2,t1: ここは同じ TURN サーバー同士の通信
    t2-)t1: SRTP over UDP
    t1-)c2: SRTP over ChannelData over UDP
  and
    c2->>t1: SRTP over ChannelData over UDP
    Note over t2,t1: ここは同じ TURN サーバー同士の通信
    t1-)t2: SRTP over UDP
    t2->>c1: SRTP over ChannelData over TCP
  end

SDP

SDP というのは Session Description Protocol の略で、簡単に言うとクライアント同士で WebRTC を繋ぐ時に、 自分ができることリストを書いた自己紹介シートみたいなものです。

クライアント同士でハンドシェイクを行い、お互いにできる事を交換して「じゃぁこれでいきましょうか」と合意するためのプロトコルです。

Offer / Answer

WebRTC では Offer / Answer という言葉がよく出てきます。これは SDP を最初に相手に送る側が Offer で、受け取って返す側が Answer になります。 Offer と Answer はペアです。

sequenceDiagram
  participant c1 as クライアント1
  participant c2 as クライアント2
  c1->>c2: Offer
  c2->>c1: Answer

ICE (Interactive Connectivity Establishment)

WebRTC で一番よくわからないのが ICE 関連です。なんだこれ?ってなります。 簡単に言うと「自分が利用できる IP アドレスを探す」という仕組みと、 「自分が利用できる IP アドレスを相手に送って、相互で疎通確認を行い、疎通ができるかどうかを確認する」仕組みです。

  • STUN / TURN も ICE の一部です
  • アドレスを探すことを Gathering と呼びます
    • 収集
  • 疎通前のペアを Nominated Pair と呼びます
    • ノミネートペア
  • 疎通ができるアドレスのペアを Selected Candidate Pair と呼びます
    • 選択されたペア候補?

ICE は色々難しいのでなんかうまい事双方で疎通確認をする仕組みくらいの認識でいましょう。 多くの場合は TURN を利用する事で疎通は可能になります。

シグナリング

WebRTC ではシグナリング、という仕組みが重要になります。これはクライアント同士が通信をする上で、 「何が利用できるのか」というのをお互いに探る仕組みです。音声は Opus で映像は VP9 を利用する、 再送はするのかしないのか、など。

シグナリングの規格は決まっていません。どんな規格を利用してもかまいません。 伝書鳩でも問題ありません。時雨堂ではウェブソケットとデータチャネルを利用しています。

DTLS

WebRTC で暗号化というとすぐこの単語が出てきます。 Datagram Transport Layer Security の略です。 TLS は TCP を目的として策定されましたが、DTLS はデータグラム(主に UDP) での利用を目的として策定されました。

WebRTC における DTLS はメディアトランスポート、データチャネル両方で利用されています。

ただし、メディアトランスポートでは DTLS で交換したマスターシークレットのみを利用して、 DTLS の暗号機能は利用していません。use_srtp というクライアントハロー拡張を利用しています。

データチャネルは DTLS の暗号機能をそのまま利用しています。

データチャネルでの暗号は多くのケースで AES-GCM が利用されています。

DTLS 1.3 が出てきていますが、WebRTC では今のところ利用されていません。 OpenSSL が DTLS 1.3 を実装してないというのはあるかもしれませんが。

昔は DTLS なんかなくて TLS over UDP な時代もありました ... 。

RTP / RTCP

WebRTC の RTP と RTCP は、音声や映像を送受信するためのプロトコルです。偉そうな名前でリアルタイムトランスポートプロトコルの略です。凄く偉そうです。

RTP / RTCP と別になっているのは RTP が実際の音声やデータを運ぶためのプロトコル。RTCP がそれらをコントロールするプロトコルです。 RTCP では「再送パケット要求」や「全画面要求」、さらには統計情報や時間情報、帯域推定などデータ以外の情報をやりとりします。

RTP / RTCP に暗号機能はありません

SRTP / SRTCP

RTP / RTCP に暗号機能が無いので、後出し出てきたのが SRTP / SRTCP です。RTP / RTCP の一部を暗号化する仕組みが規定されています。 暗号は AES-CTR または AES-GCM が利用されます。

暗号化に利用するマスターシークレットは DTLS で取得したモノを利用します。DTLS-SRTP と呼ばれる特殊な仕組みです。

SCTP / WebRTC Data Channel Establishment Protocol

データチャネルでは SCTP というプロトコルが利用されています。これは TCP と UDP の良い所取りのプロトコルです。 ただルーターが TCP と UDP にしか対応していなく、SCTP をうまく扱えない場合があるため、パブリックなネットワークで利用されることはありません。

そのため WebRTC でも UDP 上に DTLS で暗号化トンネルを用意して、その上で SCTP を利用しています。

さらにデータチャネルでは SCTP 上のストリームをコントロールするために DCEP (DataChannel Establishment Protocol) を実装しています。 これはデータチャネルの label という「ストリームに名前を付ける機能」を実現するための仕組みです。

また、ストリーム毎の再送回数/再送時間や順番保証を設定できるようにするためです。

SCTP 自体複雑過ぎるプロトコルということもあり、覚える必要は一切ありません。 ちなみに Google (libwebrtc) は SCTP 標準ライブラリである usrsctp を利用せず、dcsctp という自前ライブラリを開発しています。

音声コーデック

WebRTC における音声圧縮に利用されるコーデックはほとんどの場合で Opus です。Opus だけ知っておけば十分です。

Opus

Opus Codec

音声圧縮コーデックの一つです。リアルタイムにも高音質にも使える万能コーデックで、 基本的には Opus を使えば良いという流れになっています。

最近では Amazon が FEC 機能を強化しています。

Neural encoding enables more-efficient recovery of lost audio packets - Amazon Science

これは互換性を保ったまま Opus に拡張として追加される予定です。

Lyra

音声圧縮コーデックの一つです。超低ビットレートで一定音質を実現する仕組みです。 Google が開発して、公開されています。WebRTC でも利用できます。

映像コーデック

WebRTC において映像圧縮に使われるコーデックは、状況によって様々です。時雨堂では現時点では VP9 を押していますし、 今後は AV1 を推奨していきます。ただハードウェアアクセラレーターを考慮すると H.264 が圧倒的有利ですし、 サービス毎に利用される端末によって様々です。背景などを細くしながら説明していきます。

サイマルキャスト

WebRTC におけるサイマルキャストは、クライアントが複数の画質を配信することです。 P2P では利用されず、SFU での利用を前提とした技術です。

I フレーム (イントラフレーム) または キーフレーム

WebRTC で配信される映像は圧縮されており、さらに差分のみを配信することで転送量を減らしています。 動きがあまりなければほとんど差分を送らなくて転送量が軽くなります。

その際に一定期間で I フレームを送ります。WebRTC ではこの感覚が恐ろしく長いです。

HLS / MPEG-DASH などでは 1-2 秒間隔で送りますが、WebRTC で VP9 を利用した場合の I フレーム間隔 100 秒です。 ちなみに H.264 だと 20 秒です。

WebRTC では 回線が不安定になって 再送ではどうしようもなくなった際に、 全画面を要求する「Full Intra Request」 というのがあります。

これを利用する事で乱れた映像を復旧することができます。

VP8

映像圧縮コーデックの一つです。 On2 という企業が保持していましたが、Google が買収しオープンソース化されました。 WebRTC 対応すべき必須コーデックの一つです。もう一つは H.264 です。

RFC 7742 - WebRTC Video Processing and Codec Requirements

VP9

映像圧縮コーデックの一つです。VP8 の後継です。圧縮率も高く YouTube の標準コーデックに採用されています。 Google が押しているほか、Intel の多くの端末でハードウェアアクセラレーター(HWA)を搭載しています。

macOS もデコードだけですが、VP9 の HWA を搭載しています。

draft-ietf-payload-vp9-16

AV1

映像圧縮コーデックの一つです。VP9 の後継ですが、 Alliance for Open Media (AOMedia) というところで開発されています。 最近では高性能なビデオカードに AV1 の HWA が搭載され初めてきています。

変換が遅い遅い言われていますが、リアルタイムな配信ができるくらいにはなってきており、 現在も積極的に開発が進められています。AV2 という規格も進み始めています。

H264

映像圧縮コーデックの一つです。ライセンスをきっちりと払い、安全に利用できる唯一の映像コーデックといっていいでしょう。 規格自体は古いですが、ライセンス問題をキレイに解決していること、さらに多くの HWA が出ていることから、いつまでたっても現役です。

H.264 のライセンスを Cisco が負担するという事で WebRTC で H.264 が気軽に利用できるようになりました。

H265

映像圧縮コーデックの一つです。ライセンス問題がふわっとしています。Safari が H.265 に対応していますが、 それ以外は対応していません。

H.265/HEVC 特許暗黒時代 - Qiita

WebRTC SFU とは

WebRTC SFU がわからない人向けにしっかり説明します

WebRTC SFU とは WebRTC を P2P 方式ではなくクライアントサーバー方式で利用する仕組みです。 クライアントとクライアントが直接やりとりせず、クライアントからの音声や映像が一度サーバーを経由します。

暗号化と復号

サーバー側で受信、復号し、再度それぞれのクライアントに暗号化して配信します。

sequenceDiagram
  participant c1 as クライアント1
  participant c2 as クライアント2
  participant c3 as クライアント3
  participant s as SFU
  note over c1,s: WebRTC 確立済
  par
    c1->>s: 音声/映像/データ (1)
    note right of s: 復号
    s->>c2: 音声/映像/データ (1)
    note right of s: 暗号化
    s->>c3: 音声/映像/データ (1)
    note right of s: 暗号化
  and
    c2->>s: 音声/映像/データ (2)
    note right of s: 復号
    s->>c1: 音声/映像/データ (2)
    note right of s: 暗号化
    s->>c3: 音声/映像/データ (2)
    note right of s: 暗号化
  and
    c3->>s: 音声/映像/データ (3)
    note right of s: 復号
    s->>c1: 音声/映像/データ (3)
    note right of s: 暗号化
    s->>c2: 音声/映像/データ (3)
    note right of s: 暗号化
  end

MCU と SFU の違い

MCU(Media Control Unit) はサーバー側で合成をして配信をするという仕組みを持っていることがほとんどです。 これは昔からある仕組みで、そもそも視聴する側の回線が細く、端末性能も低いという「過去の時代に活躍した」ものです。

もともとあったビデオ会議システムは「パソコン上で動かす」モノではなく、専用端末が必要でした。 回線も細かった事もあり、サーバー側で参加者の映像を合成することで帯域占有率を下げるという手段がとられていました。

しかし、合成をリアルタイムで行うという「低遅延を要求する」仕組みに対してとても無茶な戦略をとっています。

なぜ WebRTC SFU が選択されるの?

今は回線も太く、端末性能も高い時代です。多くの PC やスマホには H.264 のハードウェアエンコーダー/デコーダーが搭載していますし、 LTE を使えば少なくとも 10 Mbps は出る時代です。

であれば、サーバー側で合成するのではなく、クライアント側でうまく表示する方が良いです。

MCU の課題に「レイアウトが固定される」という問題もありました。つまり「配信者本人も含めた全員を合成して配信する」というものです。 でもそもそも自分の映像はローカルで取得してるわけです、なのにわざわざ自分の映像を合成されても ... となります。

そう考えるとただ転送するだけの SFU とクライアント側で好き勝手にレイアウトをいじれるという組み合わせは、 サービスを作る上でかなり色々できるようになります。

実際 SFU 側で配信を止めるという需要もあります。「話をしていない人は別に映さなくていい」という需要です。 これは SFU であれば、簡単に実現できます。

SFU 採用

  • Google Meet
  • Microsoft Teams
  • Cisco Webex
  • Zoom
    • 正しくはメディアリレーサーバー
  • Discord
  • WhatsApp
  • Signal

SFU は規格があるの?

SFU は規格はありません。自由に作ってかまいません。ポイントがあるとしたらブラウザから利用できる技術だけ作る事くらいでしょうか。

しかしそれも別にブラウザからの WebRTC を諦めてしまうならば、何でもできてしまいます。

例えば Discord の音声と映像は SFU を利用していますが、iOS / Android 向けの暗号処理を変えているそうです。 ただし、これは少し古い話なので今はどうかわかりません。

元々シグナリングの規格がないため、SFU 自体の仕組みは自由に作る事ができます。

WebRTC SFU で TURN サーバーは必要?

しっかり回答している記事がおそらく見当たらないと思います。あまりよくわかってない人が多いためです。SFU の場合はそもそも SFU がグローバルに出ていることもあり、そもそもそのまま接続に行けます。NAT 越えをする必要が あまり ありません。

そのため、多くの SFU では TURN サーバーを用意しないという戦略をとっています。でも TURN-TLS はどうするんでしょうか? これは裏技があり udp と tcp だけでなく ssltcp タイプがあります。

Chrome は ssltcp が含まれると擬似的な SSL ClientHello を送信します。

つまり TLS っぽいパケット を送る仕組みがありますが、これは仕様として公開されていません。また RFC として規格があるわけでもありません。つまり「Google が Chrome で使いたいから libwebrtc に突っ込んでいる規格」なわけです。

そのため個人的にそんな事よりさっさと TURN の仕組みに乗っかった方が早いのでは?と思っています。

Sora では TURN 実装を SFU に組み込んでおり、クライアントが常に TURN サーバーを経由するような仕組みを採用しています。これは Sora の TURN の仕組みで詳細を説明します。

SFU で SDP の取り扱い

WebRTC SFU ではクライアントは SFU に繋いでるクライアントとは SDP の交換は行いません。 あくまで SFU とのみ行います。

クライアント <-> SFU という P2P がたくさんあると考えてください。

ただし、他のクライアントの接続や切断をトリガーとして、SDP の交換は発生します。

WebRTC P2P では SDP の交換は基本的に 1 回っきりです。接続する前に Offer/Answer でやりとりをするだけです。 WebRTC SFU の場合はクライアントの参加と離脱時に SDP の再交換が発生します。

これを Re-Offer / Re-Answer と呼びます。

なぜ再交換が必要かというと「新しく繋いできたクライアントから送る音声や映像の情報」をやりとりするためです。もちろん切断するタイミングでは「今まで繋いでいたクライアントからの音声や映像が送られてこなくなる」ということをクライアントに伝えるという意味もあります。

この SDP 再交換は WebRTC SFU 独特の仕組みではあるので、覚えておくと良いです。

WebRTC SFU Sora とは

WebRTC SFU Sora (以降 Sora) は時雨堂が 1 から開発した WebRTC SFU です。 OSS の SFU をベースにしてはおらず、WebRTC プロトコルスタックも 1 から実装しています。

1 から実装している理由は開発当時にそもそも WebRTC SFU が存在しなかったこと、 さらにサポートを提供するにあたり、内部を隅から隅まで把握しているには自作するのが手っ取り早いと判断したからです。

Sora は独自のシグナリングの仕組みを持ちつつ libwebrtc に合わせた WebRTC スタックを実装しています。 また、実践的な多くの機能を多く持っています。

WebRTC SFU Sora の用語

Sora では色々と Sora のみに利用される用語を定義しています。ここではその用語について説明します。

チャネル ID

Sora においてチャネルとはルームのようなものです。Sora は事前に「ルームを作成して使う」といった仕組みはありません。

誰も接続していないチャネル ID への接続が成功すれば、そのチャネルが存在することになります。

コネクション ID

Sora において完全ユニークな値を保証する ID です。中身は UUIDv4 です。コネクション ID を指定する場合はかならずチャネル ID と組み合わせて利用します。

クライアント ID

Sora においてクライアント ID とは、重複可能なクライアント用の ID です。 例えば「あるユーザのウェブクライアントとスマホクライアント」を同じグループとして扱いたい場合に利用します。クライアント単位でのプッシュ通知などが利用できます。

バンドル ID

Sora のバンドル ID では同じバンドル ID が指定されている場合は、音声や映像やデータを送信しないという仕組みです。

例えば、あるクライアントが画面共有用に別のクライアントで接続した場合、映像や音声を受信したくないとします。その場合は両方の接続クライアントで同じバンドル ID を指定します。

セッション ID

セッションとは「あるチャネルにおいて少なくとも 1 コネクション以上が存在している状態」です。 誰も接続していないチャネルでセッションが存在していない状態に接続が行われるとセッションが作成されます。

セッションは誰も接続していない状態が一定時間経過すると削除されます。

メタデータ

Sora ではメタデータという名前が色々な場所ででてきます。

あまりにも多すぎるのでメタデータという名前でドキュメントを書いています。

https://sora-doc.shiguredo.jp/METADATA

WebRTC SFU Sora の特徴

Sora は簡単に使えつつ、かなりマニアックな機能も搭載しているというのが売りの製品です。

OSS をベースに開発されている商用パッケージ製品はありますが、 1 から書かれている WebRTC SFU はほとんどありません。

明確なライセンス体系

お金の話はここでだけ話をします

https://sora.shiguredo.jp/price

Sora は同時接続数ライセンスです。同時に接続できるコネクション数を買ってもらいます。 ちなみに先勝ちです。最大同時接続数に達した場合、後から接続したコネクションは接続できません。

セットアップ

30 分程度でセットアップ可能です。

  • Sora のインストールと設定
    • ライセンスの設定
    • IP アドレスの設定
  • 証明書の取得
    • DNS-01 による Let's Encrypt を利用すればすぐです
  • Nginx のインストールと設定

これで利用が開始できます。

無設定

Sora は多くの機能、多くの設定がありますが、設定項目は何一つ設定することなく動かすことができます。 ライセンスファイルを etc/license.json として配置したら bin/sora start するだけで動きます。

設定ファイルを色々設定しないと起動しないと行けない、というのが凄く好きじゃないというのがあり、 とにかく無設定で動くようにしています。

TURN 内蔵

Sora は TURN サーバーを内蔵しているため、SFU とは別に TURN サーバーを立てる必要がありません。 Sora の組み込み TURN サーバーは TURN-UDP / TURN-TCP / TURN-TLS に対応しており、かつ IPv6 にも対応しています。

IPv6 のみの環境でも問題無く動作します。

Sora は TURN を組み込むために様々な工夫をしています。

1 つ目はリレーの強制です。Sora は TURN サーバーを前提とした通信を想定してるため、TURN サーバー (といっても Sora ですが) を経由する通信を強制します。

そのためクライアントは STUN での NAT 検出を行う必要がありません。Sora から払い出された TURN サーバーへの URL へアクセスを試みるだけで良いです。

2 つ目 は Sora はクライアントが TURN サーバーを経由して P2P で通信を行っていると勘違いさせています。 そのため、素直な動作をします。SFU にありがちなハック的な挙動が一切ありません。

マルチストリーム

SFU を使わない WebRTC では 1:1 つまりストリームを双方向で1つずつ張るのが基本的ですが、 SFU の場合は参加者毎にストリームを張る必要があります。

例えば参加者が 5 に居る場合は、1 参加者毎に配信 1 視聴 4 というストリームを合計で 5 本張る必要があります。 さらに全体では合計で 25 本のストリームを張る必要があります。

マルチストリームはこの複数のストリームを 1 つのコネクションで実現する仕組みです。

マルチストリームを実現していない場合は、1つのストリーム毎にコネクションを張る必要があり、管理が複雑になります。

サイマルキャスト

WebRTC でのサイマルキャストは複数種類の画質を同時に配信する技術です。

  • 1080p 30fps の映像
  • 720p 25fps の映像
  • 360p 10fps の映像

このように 3 種類の映像を SFU に送る事ができます。 サイマルキャストは WebRTC の課題を解決する仕組みの1つです。

WebRTC ではクライアントは基本的に1つの画質を配信しますが、 参加者全員に配信することになるため、もし配信者の回線が安定していて帯域も余裕がある場合、 5 Mbps の 1080p で映像を送るとします。

しかし、その場合参加者全員が 5 Mbps の映像を受信する必要があります。 もし参加者の一人が回線が不安定で、帯域に余裕がない場合は 5 Mbps の映像を受信することができないとします。

そうなると、配信者は「帯域に余裕がない」クライアントに合わせた映像を配信する必要があります。 もし帯域が 500 Kbps しかない場合は、配信者は 500 Kbps で配信する必要があり、 他の帯域に余裕があるクライアントでも 500 Kbps の映像を受信することになります。

コレはなんか納得がいきません。参加者が多ければ多いほど、不安定な回線似合わせる必要があります。 これはビデオ会議でならなんとか我慢できますが、ライブ配信だとそうはいきません。

そこで登場するのがサイマルキャストです。 複数の画質をクライアントが配信し、視聴者側が「どの画質を視聴するかどうか」を決める事ができます。

ライブストリーミングで言う ABR (Adaptive Bitrate) を、サーバーが行うのではなく、 クライアントが行います。

シーケンス図

   sequenceDiagram
       participant client1 as クライアント1
       participant sora as WebRTC SFU Sora
       participant client2 as クライアント2
       client1->>sora: "type": "connect",<br/>"role": "sendonly",<br/>"simulcast":"true"
       note over client1, sora: クライアント1 WebRTC 確立
       client2->>sora: "type": "connect",<br/>"role": "sendonly",<br/>"simulcast":"true",<br/>"simulcast_rid": "r1"
       note over client2, sora: クライアント2 WebRTC 確立
       par
           client1-)sora: 映像<br>rid: r0
       and
           client1-)sora: 映像<br>rid: r1
           sora-)client2: 映像<br>rid: r1
       and
           client1-)sora: 映像<br>rid: r2
       end

スポットライト

Sora のスポットライト機能は、WebRTC で用意されている機能ではありません。時雨堂が考えた独自の機能です。 きっかけは「会議中、別にしゃべってない人の映像ってあまり重要ないよね」という話からでした。

また、もともと双方向配信はクライアント側の帯域と CPU 使用率が高くなってしまうため、 多くのユーザーを1つのチャネルに追加するのが難しいという問題を抱えていました。

フォーカス

そこで、考え出したのが「直近で話をしている人の映像だけを鮮明にする」という仕組みです。 これをスポットライトを当てて フォーカスする と呼ぶことにしました。

この仕組みはサイマルキャストの複数の映像配信を利用する事で、 直近で話をした人は高画質、話していない人は低画質という仕組みを利用できます。

このフォーカスするかどうかどうかは、SFU で音声パケットの音量を見て切り替えます。 実は WebRTC の音声パケットには音量レベルが常に入ってきます。

一定音量を超えた場合は高画質、そうでない場合は低画質と判断します。

遅延フォーカス

ただ、この音量を超えるがなかなかやっかいで「チョットした物音」にも反応するため、 遅延フォーカスという仕組みを導入しました。 遅延フォーカスは「ある一定以上の音質を一定時間経過しないと高画質に切り替えない」という仕組みです。

この仕組みを追加することで、チョットした物音で映像が切り替わるという事を防ぐことができます。

実際この仕組みを利用することで、クライアントとサーバーの負荷両方を抑えることができます。

自動アンフォーカス

あまり話をしないとフォーカスをするのを自動でやめるという仕組みも導入しています。 これは一度フォーカスした人が話をしていないにもかかわらず、フォーカスが当たり続けるのを回避できます。

シーケンス図

   sequenceDiagram
       participant client1 as クライアント1
       participant sora as WebRTC SFU Sora
       participant client2 as クライアント2
       client1->>sora: "type": "connect",<br/>"role": "sendrecv"<br/>"spotlight": true,<br/>"multistream": true,<br/>"simulcast": true
       note over client1,sora: クライアント1 WebRTC 確立
       par
           client1-)sora: 映像<br/>rid: r0
       and
           client1-)sora: 映像<br/>rid: r1
       end
       client2->>sora: "type": "connect",<br/>"role": "sendrecv"<br/>"spotlight": true,<br/>"multistream": true,<br/>"simulcast": true
       note over client2,sora: クライアント2 WebRTC 確立
       par
           client2-)sora: 映像<br/>rid: r0
       and
           client2-)sora: 映像<br/>rid: r1
       end
       par
           sora-)client2: クライアント1映像<br/>rid: r0
       and
           sora-)client1: クライアント2映像<br/>rid: r0
       end
       note over client1: クライアント1が話し始める
       sora-)client2: クライアント1音声
       note over client1: しゃべり初めて 2 秒経過
       note right of sora: r0 の代わりに r1 映像を配信
       sora-)client2: クライアント1映像<br/>rid: r1

OBS での WebRTC 配信機能 (WHIP 対応)

2022 年末に OBS から WebRTC の配信ができるようになる WHIP への対応が進められメインラインへマージされました。

録画機能

Sora の強みの1つは録画機能です。Sora は音声や映像パケットを無変換で録画することが可能です。

パケロスしたときもうまいこと録画をする仕組みを導入しています。 少し遅延して録画をすることで、実際の配信よりも再送を受け取れるようにしています。

リップシンクも実現しており、音声と映像のズレを発生しにくくしています。

ファイル出力は接続毎に行われ、完全に独立したファイルが生成されます。 そのため、レイアウトを JSON で指定できる Hisui という録画ファイルの合成ツールを OSS にて公開しています。 WebRTC SFU を利用して、録画機能を提供する以上、録画合成ツールが必須です。

長時間録画機能

Sora では録画ファイルを分割して出力する機能をいれることで、長時間の録画に対応しています。 具体的には 1 ヶ月以上の録画なども可能です。

WebM ファイルを分割出力するため、それぞれの WebM ファイルは独立しています。 WebM ファイルと同様の名前のメタデータファイル (JSON) が生成されるため、それを利用する事でファイルのオフセット値なども確認できます。

負荷の削減

WebRTC SFU では全てのストリームに対して、復号、暗号化を行います。ただ、誰も視聴していない場合、録画をしていない限りは復号する必要がありません。

そのため、Sora では 録画していない、または誰も視聴していない音声、または映像ストリーム を復号しない処理が入っています。

例えば、スポットライト機能でアクティブではないクライアントの中画質映像と音声は復号していません。

ウェブソケットシグナリング機能

WebRTC ではシグナリングについては規格はありません。Sora ではウェブソケットとデータチャネルを採用しています。 最初は必ずウェブソケットでつなぎます。ウェブソケットは TLS で接続することになり「基本的に接続できない」という事がありません。 そこでクライアントと Sora の接続を確立します。

データチャネルを利用する場合はデータチャネルへ切り替えますが、データチャネルを使わないことも可能です。

Sora でウェブソケットを採用した理由

Sora はシグナリングの通信にウェブソケットを採用しました。 これはウェブソケットはブラウザで利用がとても簡単かつ、Sora 側でのハンドリングも難しくなかった、というのが大きな理由です。

それ以外にクライアントからも非同期で送信するタイミングがあることがあるため、 ウェブソケットを利用しておきたかったというのです。

また、シグナリング用のウェブソケット経由で Sora から通知を送ったりする仕組みを実現することを考えると、 一度張ったら切断までは張り続けるウェブソケットの仕組みはとても扱いやすいと判断したたためです。

データチャネルシグナリング機能

Sora ではウェブソケットのシグナリングを接続し、WebRTC の接続が完了したタイミングで、シグナリングをウェブソケットからデータチャネルに切り替える仕組みがあります。これは Sora オリジナルの仕組みです。

Sora には 3 種類のシグナリングの仕組みがあります。

  • ウェブソケットシグナリング
    • 特に今まで通りです
  • ウェブソケットシグナリング後、ウェブソケットは切断せずにデータチャネルシグナリングに切り替える
    • データチャネルを利用するようになり HoL Blocking を回避できるようになります
    • さらに切断検知にウェブソケットを利用できるため、切断に Sora が気付きやすくなります
  • ウェブソケットシグナリング後、ウェブソケットを切断し、データチャネルシグナリングに切り替える
    • ウェブソケットを完全に切断するため、切断検知がしづらくなります
    • 瞬断などに対応ができます

時雨堂としてはウェブソケットとデータチャネルのハイブリッドの利用を推奨しています。

https://sora.shiguredo.jp/features#signaling

シーケンス図

sequenceDiagram
    autonumber
    participant client as クライアント
    participant sora as WebRTC SFU Sora
    participant app as アプリケーションサーバー
    client->>+sora: "type": "connect"
    sora->>+app: 認証ウェブフック
    app-->>-sora: 200 OK<br/>{"allowed": "true"}
    sora->>-client: "type": "offer"
    client->>sora: "type": "answer"
    note over client,app: WebRTC 確立
    sora->>+app: イベントウェブフック<br/>"type": "connection.created"
    app-->>-sora: 200 OK
    note over client,app: DataChannel 確立
    sora->>client: "type": "switched"
    note over client,app: これ以降は DataChannel が利用される

シグナリング通知機能

常時接続のシグナリング用のウェブソケットやデータチャネルを利用して、サーバからリアルタイムなプッシュ通知を送ることができます。

これはシグナリング通知機能と呼んでおり、例えば誰かが参加した、離脱したことを通知したりします。 それ以外にもサーバ側にあるプッシュ API を叩くことで、指定したチャネルやコネクションに対してメッセージを送ることができます。

https://sora-doc.shiguredo.jp/SIGNALING_NOTIFY

メッセージング機能

Sora はデータチャネルを利用したメッセージング機能があります。 メッセージング自体を保存する仕組みはないため、この仕組みはデータを保存する必要が無く、 リアルタイムにデータのやりとりをしたい場合に利用する仕組みです。

メッセージングは 1 つのクライアントが複数利用する事ができます。 データチャネルを定義するときにラベルに # のプレフィックスをつける事でそのデータチャネルがメッセージングとして扱われます。

#spam というラベルのメッセージングを directionsendrecv または recvonly に設定しているクライアントに送られます。

この direction というのはデータチャネルではもともと P2P で利用されることを想定されているため、 受信する人を選択できません。そのため時雨堂が独自にデータチャネルに追加した仕組みです。

ただし、データチャネル自体をカスタマイズしているわけではないため、メッセージング機能はデータチャネルとは完全互換です。

普通にリアルタイムに通知したいだけであれば、シグナリング通知機能を利用してください。 シグナリング通知はシグナリングにデータチャネルを利用していれば、データチャネル経由で通知されます。

ウェブフック機能

Sora 自体は認証の仕組みを持っておらず、 認証機能などを全て外部のサーバーに依存する仕組みになっています。

ウェブフックはアプリ側がとても組み込みやすい仕組みの一つだと思っています。

  • mTLS が利用できる
  • HTTP Proxy が利用できる

Sora のウェブフックは順番保証

Sora は接続、切断のウェブフックの順番を保証します。

接続ウェブフックの 200 OK を受け取る前に、切断ウェブフックを送信することはありません。

認証ウェブフック

認証ウェブフックはクライアントが接続しに来たタイミングで、ウェブフックを送信する仕組みです。

接続しようとしてきているクライアントの情報が色々詰まっていますし、現在 Sora に接続しているユーザー数なども送信してきます。

sequenceDiagram
    autonumber
    participant クライアント
    participant Sora
    participant アプリケーションサーバー
    クライアント->>+Sora: "type": "connect"
    Sora->>+アプリケーションサーバー: 認証ウェブフック
    アプリケーションサーバー-->>-Sora: 200OK<br />{"allowed": true}
    Sora-->>-クライアント: "type": "offer"
    クライアント->>Sora: "type": "answer"
    note over クライアント,アプリケーションサーバー: WebRTC 確立

セッションウェブフック

セッションウェブフックはセッションが作成されるタイミングと、セッションが破棄されるタイミングでウェブフックを送信する仕組みです。

sequenceDiagram
    autonumber
    participant クライアント1
    participant クライアント2
    クライアント1->>Sora: type: connect
    Sora->>+アプリケーションサーバー: 認証ウェブフック
    アプリケーションサーバー-->>-Sora: 200 OK
    Sora->>+アプリケーションサーバー: セッションウェブフック<br/>type: session.created
    アプリケーションサーバー-->>-Sora: 200 OK
    Sora->>クライアント1: type: offer
    クライアント1->>Sora: type: answer
    Note over クライアント1,アプリケーションサーバー: クライアント1 WebRTC 確立
    Sora->>+アプリケーションサーバー: イベントウェブフック<br/>type: connection.created
    アプリケーションサーバー-->>-Sora: 200 OK
    クライアント2->>Sora: type: connect
    Sora->>+アプリケーションサーバー: 認証ウェブフック
    アプリケーションサーバー-->>-Sora: 200 OK
    Sora->>クライアント2: type: offer
    クライアント2->>Sora: type: answer
    Note over クライアント1,アプリケーションサーバー: クライアント2 WebRTC 確立
    Sora->>+アプリケーションサーバー: イベントウェブフック<br/>type: connection.created
    アプリケーションサーバー-->>-Sora: 200 OK
    クライアント1->>Sora: "type": "disconnect"
    Sora->>+アプリケーションサーバー: イベントウェブフック<br/>type: connection.destroyed
    アプリケーションサーバー-->>-Sora: 200 OK
    Sora->>クライアント1: WebSocket Close
    Note over クライアント1,アプリケーションサーバー: クライアント1 WebRTC 切断
    クライアント2->>Sora: "type": "disconnect"
    Sora->>+アプリケーションサーバー: イベントウェブフック<br/>type: connection.destroyed
    アプリケーションサーバー-->>-Sora: 200 OK
    Sora->>クライアント2: WebSocket Close
    Note over クライアント1,アプリケーションサーバー: クライアント2 WebRTC 切断
    note right of Sora: 接続数 0 から 15 秒経過
    Sora->>+アプリケーションサーバー: セッションウェブフック<br/>type: session.destroyed
    アプリケーションサーバー-->>-Sora: 200 OK
    note right of Sora: セッションがすべて破棄された
    Sora->>+アプリケーションサーバー: セッションウェブフック<br/>type: session.vanished
    アプリケーションサーバー-->>-Sora: 200 OK

イベントウェブフック

イベントウェブフックはコネクション単位のイベントが起きるたびに送信されるウェブフックです。 接続の成功、録画ファイルの作成、スポットライトの切り替わりなどがあります。

sequenceDiagram
    participant client as クライアント
    participant sora as WebRTC SFU Sora
    participant app as アプリケーションサーバー
    note over client,app: 認証成功
    sora->>client: "type": "offer"
    client->>sora: "type": "answer"
    note over client,sora: WebRTC 確立
    sora->>+app: イベントウェブフック<br/>"type": "connection.created"
    app-->>-sora: 200 OK
    note over client,sora: 接続から 1 分経過
    sora->>+app: イベントウェブフック<br/>"type": "connection.updated"
    app-->>-sora: 200 OK
    client->>sora: "type": "disconnect"
    sora->>+app: イベントウェブフック<br/>"type": "connection.destroyed"
    app-->-sora: 200 OK
    sora->>client: WebSocket Close

クラスター

Sora はクラスターを構築する事ができます。現時点では冗長構成が主な目的です。 Sora 3 台以上でクラスターを組むことができます。

特定のチャネルへのアクセスを特定のノードへ集約する仕組みを持っているため、 LB も利用できます。クラスター全ノードが「どのチャネルがどのノードを管理しているか」を把握しています。

ハードウェア障害が起きたとしても、新規でノードを追加することで、サービスの継続性を高められます。

リダイレクト

もし接続先が指定したチャネルを担当しているノードでなければ、指定したノードに再接続するように Sora 側からうながします。これを Sora ではリダイレクト機能と呼んでいます。

sequenceDiagram
    participant クライアント
    participant Sora1
    participant Sora2
    participant Sora3
    participant アプリケーションサーバー
    クライアント->>Sora1: "type": "connect"
    Sora1->>クライアント: "type": "redirect"
    クライアント->>Sora2: "type": "connect", "redirect": true
    Sora2->>+アプリケーションサーバー: 認証ウェブフック
    アプリケーションサーバー-->>-Sora2: 200 OK<br />{"allowed": true}
    Sora2->>クライアント: "type": "offer"
    クライアント->>Sora2: "type": "answer"
    note over クライアント, アプリケーションサーバー: WebRTC 確立
    Sora2->>+アプリケーションサーバー: イベントウェブフック<br />"type": "connection.created"
    アプリケーションサーバー-->>-Sora2: 200 OK

ウェブソケット LB による URL 統一機能

ウェブソケットに対応した LB を利用する事で、一つの URL をクライアント側に伝えるだけで良くなります。

sequenceDiagram
    participant C as クライアント
    participant LB as ロードバランサー
    participant S1 as Sora (0001)
    participant S2 as Sora (0002)
    participant A as アプリケーションサーバー
    C->>LB: wss://sora.example.com/signaling
    LB->>S1: wss://0001.sora.example.com/signaling
    note over B,S1: WebSocket 確立
    C->>+LB: "type": "connect"
    LB->>+S1: "type": "connect"
    S1-->>-LB: "type": "redirect"<br>"location": "wss://0002.sora.example.com/signaling"
    LB->>-C: "type": "redirect"<br>"location": "wss://0002.sora.example.com/signaling"
    note over B,S1: WebSocket 切断
    C->>S2: wss://0002.sora.example.com/signaling
    note over B,S1: WebSocket 確立
    C->>+S2: "type": "connect"
    S2->>+A: 認証ウェブフック
    A-->>-S2: "allowed": true
    S2->>-C: "type": "offer"
    C->>S2: "type": "answer"
    note over B,S2: WebRTC 確立

音声ストリーミング機能

音声ストリーミング機能は Sora がクライアントから受け取った Opus を HTTP/2 経由で外部のサーバーに送信する仕組みです。

また、外部サーバから受け取った音声ストリーミングの解析結果をクライアントに配信する仕組みもあります。

利用用途としては音声からのリアルタイムな文字起こしや翻訳などです。

クライアントが誰も解析結果をサブスクライブしていない場合は、自動で外部サーバーへの配信を停止し、誰かがサブスクライブし始めたら外部サーバへの配信を再開するという仕組みが入っているため、外部サービスの利用コストも削減することができます。

OSS で公開している Suzu と連携する事を想定しています。

統計エクスポーター機能

統計エクスポーター機能はクライアントから受け取った統計情報を HTTP/2 経由で外部のサーバーに創始する仕組みです。

クライアントから特設外部サーバーに送る場合、認証や負荷などが面倒になります。しかし Sora の統計エクスポーター機能はシグナリングのために張っている接続を利用しますので、認証などが不要になります。

特にデータチャネルシグナリングを利用している場合は、かなり扱いやすくなります。

OSS で公開している Kohaku と連携する事をそうしていします。

ログと統計

Sora が配信と録画機能以外にこだわっているのは、ログと統計機能です。

特にログはサポートにおいて非常に重要な役割を果たします。そのため可能な限りの情報を出力します。

ログに顧客固有情報(センシティブデータ)が含まれる部分は全て隠蔽してログ機能を出力します。

https://sora-doc.shiguredo.jp/SENSITIVE_DATA

WebRTC SFU Sora が対応しないこと

WebRTC / WebTransport 以外のプロトコルの対応

今のところ WebRTC 以外のプロトコルだと一応後継である WebTransport 以外は予定していません。 RTMP は SRT や RTSP といったプロトコルには対応しません。

カスタマイズ

独自仕様へのカスタマイズは一切受けていません。

外部からの音声/映像取り込み

RTP 転送機能や音声ストリーミング機能の戻りとして音声や映像を受け取ることはしません。

Sora SDK

Sora では libwebrtc ベースの SDK を OSS (APL 2.0) として公開しています。

Sora JavaScript SDK

ブラウザで利用することを想定した SDK です。JavaScript となっていますが、Node などでは動作しません。

Sora への追従が一番早いです。

Sora iOS / Android SDK

iOS と Android の SDK です。現在はそれぞれに独自でシグナリング部分などを実装をしていますが、将来的には C++ SDK ベースにする予定です。

Sora C++ SDK

多くのプラットフォームに対応した C++ SDK です。Sora のシグナリングと libwebrtc のとても薄いラッパーとして実装されています。Unity SDK と Python SDK は C++ SDK がベースとなっています。

  • HTTP Proxy への対応
  • クライアント証明書指定への対応

Sora Unity SDK

Unity で利用できる SDK です。C++ SDK をベースとしているため、多くの HWA に対応しています。

Sora Python SDK

Python から気軽に WebRTC を利用する事を目的とした SDK です。C++ SDK をベースとしています。 音声や映像の取り扱いを他の SDK とは違い独立させているため音声や映像の加工が可能です。

データチャネルなどにも対応しています。 `pip install sora_sdk`` ですぐに利用が始められます。

Sora ツール

時雨堂では Sora をより便利に利用するためのツールを OSS として開発し、公開しています。

Zakuro

https://github.com/shiguredo/zakuro

Zakuro は時雨堂が開発し OSS (APL 2.0) として公開している Sora 専用の負荷試験ツールです。 libwebrtc をベースにしているため「本番さながらの負荷」を書けることができます。

YAML でシナリオを書くことで簡単に気軽に負荷をかけれます。

  • 一定時間負荷をかけて、いったん切断をしてから再度負荷をかけるといったシナリオ
  • 複数のシナリオの組み合わせ

Kohaku

https://github.com/shiguredo/kohaku

Kohaku は時雨堂が開発し OSS (APL 2.0) として公開している Sora 専用の WebRTC 統計情報収集ツールです。

Hisui

https://github.com/shiguredo/hisui

Hisui は時雨堂が開発し OSS (APL 2.0) として公開している Sora 専用の録画映像合成ツールです。

WebRTC SFU では録画をしたとしても、それぞれのクライアント事に録画ファイルが生成されてしまいます。 それを一つのファイルにするためには、録画ファイルの合成が必要になります。

レイアウト機能で利用する JSON を Twilio の録画合成機能とほぼ互換にしています。

https://www.twilio.com/docs/video/api/compositions-resource

Suzu

https://github.com/shiguredo/suzu

Suzu は時雨堂が開発し OSS (APL 2.0) として公開している Sora 専用の音声ストリーミングゲートウェイです。

Sora の音声ストリーミング機能と組み合わせることで文字起こしサービスを利用した、リアルタイム字幕を実現できます。

sequenceDiagram
  participant C1 as クライアント1<br>Subscribed
  participant C2 as クライアント2<br>Unsubscribed
  participant C3 as クライアント3<br>Unsubscribed
  participant S as Sora
  participant SUZU as Suzu
  participant GCP as GCP
  C2-)S: SRTP
  S-)SUZU: Opus over HTTP/2
  SUZU-)GCP: Ogg over HTTP/2
  GCP-)SUZU: TEXT over HTTP/2
  SUZU-)S: TEXT over HTTP/2
  S-)C1: TEXT over DataChannel
  C3-)S: SRTP
  S-)SUZU: Opus over HTTP/2
  SUZU-)GCP: Ogg over HTTP/2
  GCP-)SUZU: TEXT over HTTP/2
  SUZU-)S: TEXT over HTTP/2
  S-)C1: TEXT over DataChannel

Sora Exporter

Sora の API から取得した統計情報を Prometheus 互換の形式で出力するエクスポーターです。

https://github.com/shiguredo/sora_exporter

Momo

Momo は libwebrtc をラップした WebRTC クライアントです。

  • 多くのプラットフォームに対応
  • 多くのハードウェアアクセラレーターに対応

Sora だけでなく Ayame (P2P) や Momo 自体がシグナリングサーバーになることで、 本当の意味での P2P が利用できる仕組みが入っています。

バイナリをダウンロードしてすぐに使い始められます。

メディアプロセッサー

おまけ

時雨堂では、ブラウザ上で音声や映像を加工するライブラリを公開しています。 ベンダーロックフリーとして開発しており、利益目的ではなく「あったら便利だろう」という理由で開発しています。

仮想背景、ノイズ抑制、ライト調整といったライブラリを公開しています。

https://github.com/shiguredo/media-processors

Sora Cloud とは

転送量や利用時間での課金ではなく、接続数と利用帯域で課金をしているサービスです。

中小規模で WebRTC SFU Sora を長時間利用する事を想定しています。

Sora Cloud の特徴

  • Sora を運用しなくて良い
    • Sora の更新を頑張らなくていい

Sora Cloud をお勧めしないケース

  • 自前で運用したい
  • 大規模接続
    • 自前運用した方が安上がりです

Sora Archive Uploader

Sora Cloud で利用するために開発したツールを OSS として公開しています。 録画され出力されたファイルを、S3 または S3 互換オブジェクトストレージへアップロードします。

並列アップロードにも対応しています。

ユースケース

導入事例からのユースケース紹介

https://sora.shiguredo.jp/cases

Sora の今後

コネクション分散機能

今年の 12 月リリースに向けて、実験的機能として複数のノードから 1 つのチャネルへのアクセスを可能にするという仕組みを導入する予定です。 そもそも WebRTC はレイテンシーを最優先するため、特定のノードに集まる事が一番効率が良いです。

しかし、1 つのノードではリソース的に最大接続数には限りがありますので、それ以上の接続ができなくなります。 これを回避するために、複数ノードで 1 つのチャネルへの接続できるような仕組みを追加します。

この仕組みを導入することで、大規模な接続を処理することができるようになります。

合成変換出力ノード

Rust を利用し、Sora のクラスターの1つとして動作する、音声/映像合成をし HLS 出力を行うノードを開発します。

WebRTC SFU に MCU 的な役割を追加する仕組みです。ただし WebRTC 的な配信は行わず、 HLS での出力を行います。

sequenceDiagram
  participant O1 as OBS1
  participant O2 as OBS2
  participant SN as Sora Node<br>Erlang/OTP
  participant SHN as Sora Composition Node<br>Rust
  participant CDN as CDN (S3)
  participant B1 as ブラウザ1
  participant B2 as ブラウザ2
  note over O1, SN: WebRTC 確立済み
  par
    O1-)SN: SRTP
    SN-)B1: SRTP
    SN-)SHN: Erlang Term<br>erl_rpc
  and
    O2-)SN: SRTP
    SN-)B1: SRTP
    SN-)SHN: Erlang Term<br>erl_rpc
  end
  note over SHN: 音声映像合成処理
  SHN-)CDN: Fragmented MP4
  B2->>CDN: HLS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment