3 min read

Python で msquic + nghttp3 + nghttp2 による MOQT 実装が動いた

ここ最近はちまちまと MOQT (Media over QUIC Transport) を気軽に試せる仕組みの実現に向けて進めてきました。まずは第一弾が動きました。

クライアントもリレーサーバーも全て Python (という名の C/C++) で実装しています。

動作

0:00
/0:04

左が QUIC / 右上が WebTransport-H3 / 右下が WebTransport-H2

これは Publisher 側でダミー映像を利用して AV1 に変換して MOQT としてリレーサーバーに配信、リレーサーバーは Subscriber 側 x 2 に転送というシンプルな仕組みです。

Publisher 側は QUIC 、Subscriber 側は WebTransport over HTTP/2 と WebTransport over HTTP/2 という構成です。

実装

Python から msquic を利用できるようにして、msquic 上に nghttp3 を利用して HTTP/3 を利用できるようにしています。MOQT 部分は性能を諦めていったん Python でメッセージをパースを実装しています。

MOQT は仕組み的に QUIC と WebTransport over HTTP/3WebTransport over HTTP/2 で利用できる必要があります。特に WebTransport over HTTP/2 は UDP が通らない場合のフォールバック先としてとても大事です。WebRTC の TURN 的な役割をします。

この HTTP/2 部分には nghttp2 を採用しています。WebTransport 部分はこちらも Python で実装しています。

実現

Python から nanobindscikit-build-corecmake を利用して msquic と nghttp3 と ngtthp2 を組み込んでいます。

ダミー映像は blend2d の Python バインディングである blend2d-py を利用しており、映像再生は SDL (Simple DirectMedia Layer) を利用した raw-player を利用しています。映像圧縮は様々なコーデックを Python から WebCodes API ほぼ互換で利用できる webcodecs-py を利用しています。

さらに MOQT の Publisher と Subscriber 側のそれぞれで MP4 への保存をすることで検証しやすい仕組みも用意しています。これは mp4-rust の Python バインディングである mp4-py を利用しています。

ちなみに msquic は I/O がしっかりと実装されているため、Python からでもネガティブがありません。XDP 対応までしています。

HTTP/2 に関しては Python 側で I/O をハンドリングしているので色々諦めています。ここら辺は nghttp2 側で I/O をハンドリングしたいところです。

今後

とりあえず動くのを優先して作ったので、今後はコードの整備をして誰もが気軽に MOQT を使えるところまで持って行きたいと考えています。実際「すぐ動かせる」って本当に大事だと思っているので。

ブラウザは巨人たちが最適化をしてくれるので、一番後回しで良いと思っています。ただ、普通に WebTransport over HTTP/3 で動くはずなので、ブラウザでも利用できるようにする予定です。。TypeScript で WebCodecs APIWebTransport API で MOQT 実装するのは、今の時代そんなに時間がかからないでしょうし。あと、ブラウザだと MOQT のしっかりとした検証が難しいだろうというのもあります。

カメラの映像も気軽に扱えるようにしたいため、現在カメラを気軽に使えるように UVC を Python から利用できるライブラリを絶賛開発中です。こちらも OSS (Apache-2.0) として公開予定です。

それにしても msquic で XDP を使ったりとか、 GIL をやめて Free-Threading を実現するのはとても楽しみだなと思っています。

クライアントは最終的に Python を Rust に置き換えれば性能は確保できますし、サーバー側は Erlang/OTP でスケールアップとスケールアウト、そして何より信頼性を確保できます。

時雨堂ではまずは「誰でもMOQT を気軽に試せる」を目標に開発を進めていきます。この MOQT の Python 実装は OSS (Apache-2.0) として公開予定です。WebRTC では libwebrtc に頼り切っていましたが、MOQT では msquic と nghttp{2,3} に頼り切った実装をしていければと思っています。

十分な検証し MOQT を使ったビジネスをしたいと考える企業がができたら、 Sora に MOQT を実装をして「Raft ベースで実装された分散システムによるスケールアウトする MOQT」を商品として提供できればと思います。

マルチパス QUIC

時雨堂では Python での MOQT 実装とは別に msquic にマルチパス QUIC を実装し Python から呼べる仕組みを開発中です。

マルチパス QUIC は複数経路を同時にうまいこと利用する仕組みだと思っていただいて間違いないです。マルチパス QUIC を利用する事で複数のキャリア回線を束ねたりすることが簡単にできるようになります。また WiFi と 5G を同時に使ったりできます。つまり誰もが欲しい夢の技術です。

マルチパス QUIC ブラウザ側では対応していないため、あくまでブラウザ以外での利用になります。ただそれ以上にマルチパス QUIC はかなり魅力的だと思っています。視聴側は別にマルチパス使わなければいいだけですし、使いたければ専用アプリを Python でサクサクっと組めばいいだけです。

今後は マルチパス QUIC が実装された msquic を Python から呼べるようにして pyroute2 などで気軽にマルチパスを検証できるようにしたいとも考えて言います。もちろん msquic ベースなので 今実装している MOQT にもそのまま持ち込めます。大事なのは実装ではなく十分検証されたマルチパス QUIC 実装だと思っています。マルチパス QUIC はいろいろなところで使えるはずです。

宣伝

現在、時雨堂では Hisui というマルチプロトコル+リアルタイム合成と変換を実現するメディアパイプラインツールを Rust で開発中です。こちらは RTMP / SRT / SRTP といったプロトコルに対応していきます。もちろん WebRTC と MOQT にも対応しますので、ご安心ください。プロトコル部分の RTMP / SRT / RTSP は完全 1 から自前で書いています、しっかり良いモノを遠回りしてでも作っていくという寸タンスです。

  • Sora は WebRTC をベースにスケールアウトする仕組みを提供
  • Hisui はマルチプロトコル対応とリアルタイム変換/合成を提供

WebRTC は libwebrtc 、MOQT は msquic / nghttp{2,3} で実現します。C 実装は Rust から呼びやすくて本当に便利です。

配信ツール -> <MOQT (QUIC)> -> Sora -> <WebRTC >-> Hisui で文字起こしして合成 -> <RTMP> -> Twitch とかが気軽にできるようになります。


今回の MOQT の Python 実装は多くの素晴らしい OSS のおかげで実現できています。本当にありがとうございます。

特に nghttp2 と ngthtp3 の作者である tatsuhiro-t 氏に感謝します。