3 min read

Chrome で MOQT が動いた

MOQT (Media over QUIC Transport) は QUIC と WebTransport の二つがトランスポートでの利用が想定されており QUIC は moqt:// で WebTransport は https:// です。

Chrome は WebTransport 実装がかなり遅れており検証目的としては厳しいと判断して、後回しにしてきましたが、汎用的に Chrome で確認できるのもまぁ大事だろうと考えブラウザの WebTransport にも Python の MOQT ライブラリを対応することにしました。

0:00
/0:05

ブラウザから Python のリレーサーバー経由でブラウザに配信しているデモ

現在の 2025 年 12 月現在の WebTransport は draft-14 ですが、Chrome の WebTransport は draft-02 です。ただし --enable-features=EnableWebTransportDraft07 を指定する事で draft-07 が利用できることがわかりました。draft-07 は大きく draft-14 と違うわけではありませんが、nghttp3 の WebTransport 対応側で対応する必要があります。

いったん fork で対応して、動作を確認して「これでブラウザで動いた」という差分を ngthttp3 の作者に共有したところ取り込んで貰いました。

GitHub - ngtcp2/nghttp3 at webtransport
HTTP/3 library written in C. Contribute to ngtcp2/nghttp3 development by creating an account on GitHub.

MOQT の JavaScript ライブラリ

MOQT をブラウザから利用できるようにするため JS ライブラリを開発しました。MOQT 自信が難しくないこともあり 1 日で実装自体は終わりました。これはそのうち OSS として公開します。

その後、検証ページを作りました。これは preact + signals + tailwind + vite です。React に疲れていたので preact を採用してみましたが、自分には合っていそうなので今後は preact で頑張ろうという気持ちになりました。

moqt-devtools として MOQT JS ライブラリに含めてありますので、こちらも公開します。サイトもあるのでそちらも公開します。

MOQT の Python ライブラリ

時雨堂では MOQT は msquic と nghttp3 (nghttp2 を含む) を組み合わせて nanobind を利用して Free Threading で利用できるようにしています。

全くチューニングしていないのでリレーサーバーは性能定期には 1 Gbps でるかでないか程度ですが、検証用としては十分な性能だと思っています。スケールアップは狙っていますが、スケールアウトはしません。

Python だと pytest 経由で色々できます。Playwright を使ってブラウザでのテストもささっとできてしまいます。

こちらは色々落ち着いたら 2026 年には OSS として Apache-2.0 で公開予定です。気軽に MOQT が動かせる仕組みを提供していきます。

サーバー (Relay)

from moqt import RelayServer

relay = RelayServer(
    port=4433,
    cert_file="server.crt",
    key_file="server.key",
)

def on_session(session):
    print(f"New session: {session}")

relay.set_on_session(on_session)
relay.run()

クライアント (Publisher)

from moqt import Client

with Client(verify=False) as client:
    with client.connect("moqt://127.0.0.1:4433/moqt") as session:
        publisher = session.publish(
            namespace=[b"live"],
            track_name=b"video",
        )

        publisher.send_object(group_id=0, object_id=0, payload=b"Hello, MOQT!")
        publisher.unpublish()

クライアント (Subscriber)

from moqt import Client

with Client(verify=False) as client:
    with client.connect("moqt://127.0.0.1:4433/moqt") as session:
        def on_object(group_id: int, object_id: int, payload: bytes):
            print(f"Received: {payload}")

        subscriber = session.subscribe(
            namespace=[b"live"],
            track_name=b"video",
            on_object=on_object,
        )

        # ... データ受信待機 ...

        subscriber.unsubscribe()

雑感

MOQT をとりあえず msquic と nghttp3 で実装してきましたが、msquic と nghttp3 のおかげで楽をさせて貰っています。MOQT 自体はあまり困っていません。MOQT の Python も JavaScript も両方所はまり所なく実装できました。

色々コードを整理して公開でき次第 MOQT は一段落させて、Multipath QUIC へ進められればと思います。

おまけ

今回は msquic + nghttp3 で WebTransport over HTTP/3 も実装してみました。Python の moqt ライブラリにおまけで入れるか、独立するかを悩んでいます。wt-devtools も JavaScript でざっくり作りました。