WebRTC の前方誤り訂正

WebRTC 上級

自社の WebRTC SFU にとりあえず実装したのでまとめておく。

WebRTC は UDP を利用している以上、パケロスが発生した場合の処理が必要です。WebRTC で利用している RTP にはもちろん再送制御がある。

ただ再送制御の場合は「再送されてくるのを待つ」必要がある。これを待たずになんとかしたいというのが前方誤り訂正になる。

Wikipedia にあるくらい有名な仕組みで、FEC(Forward Error Correction) と呼ばれている。いろいろな分野で使われているらしい。自分は WebRTC で初めて知った仕組みだ。

RFC もあるので興味のある方は是非読んでみてほしい。

FEC の目的はできるだけ遅延させることなく、さらに転送量を抑えつつパケロスした重要な RTP パケットを再送制御無しで実現したいというのがゴールになる。

WebRTC の FEC は I フレームのパケロスをカバーする仕組みになっている。I フレームは大きめのデータになるため、RTP パケットが分割されて送られてくることが多い。この分割された RTP パケットがパケロスした時に再送制御なしで FEC パケットとパケロスしなかった RTP パケットからパケロスした RTP パケットを復元させる仕組みになる。

I フレームの RTP パケットは多い場合は 10 程度になる。これが1つでもパケロスするとかなり映像が乱れてしまう。それを回避するために、I フレームの RTP パケットと FEC パケットを利用し復元できるようにする。

I フレームの RTP パケットが 5 程度ある場合は FEC パケットも 5 程度送られる。FEC の中には復元に必要な RTP パケットのシーケンス番号が複数入っている。例えば 1,3 と書いてあったら、この FEC パケットとシーケンス番号が 3 の RTP パケットがあればシーケンス番号が 1 の RTP パケットを復元することができる。

シーケンス番号 3 の RTP パケットとシーケンス番号 1 の RTP パケットがパケロスしてしまった場合この FEC パケットからは何も復元できず、転送するだけ無駄になってしまう。

そのため RTP パケットが 5 程度ある場合はシーケンス番号がランダムな 組み合わせで FEC パケットも 5 程度送られるようになっている。

  • シーケンス番号 1, 3 の RTP パケットがあれば復元できる FEC パケット
  • シーケンス番号 2, 4 の RTP パケットがあれば復元できる FEC パケット

例えこのような組み合わせで FEC パケットが送られる。これで 1 つの RTP パケットがパケロスした RTP パケットを復元できるようになる、再送なしで、だ。

FEC は帯域を通常より使うというデメリットもある。当たり前だが 5 パケット送るのに加えて FEC パケットを送ることで冗長化をするからだ。

そのため FEC は パケロスが 1–5% あたりで機能する仕組みに感じる。これを超えてしまうとパケロスをカバーするためにFEC パケットが多くなってしまい、ただでさえ不安定な回線を圧迫してしまう。

WebRTC において FEC は不安定な回線でも大幅に映像が崩れない事を保証するための機能だ。もともと再送制御がある世界でさらに FEC を利用することでより安定した配信が可能になる。

特に配信者の回線が不安定な場合に効果的になると考えている。

今回この FEC 機能を自社の WebRTC SFU に実装した。もともと再送制御搭載しているが、より安定的な配信ができるようにするのが目的だ。さらに帯域推定による画質コントロールも実装していく予定だ。

これらの機能を実装し不安定な状況でも快適に映像のやり取りができるような製品にしていくつもりだ。

もちろんこの機能はクライアントは一切意識する必要はない。全てサーバ側が「うまいことやってくれる」からだ。

FEC を実装している WebRTC SFU は少ない、理由は実装がかなりめんどくさい上に、再送制御のような大きなメリットを受けられるわけではない。

ただ不安定な回線で安定した配信を実現するためにはこのように地味な機能を積み重ねて実装していく必要がある。

今回実装した FEC は古き良き ULPFEC だが、次世代の FlexFEC も実装していく予定だ。

期待していてほしい。

Written by

Erlang/OTP / 時雨堂 / WebRTC / E2EE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store