Note
ブラウザ上で動作する MOQT 実装は shiguredo/moqt-js で公開しています。
Warning
このライブラリは開発中であり、仕様が積極的に変更される場合があります。
We will not respond to PRs or issues that have not been discussed on Discord. Also, Discord is only available in Japanese.
Please read https://github.com/shiguredo/oss before use.
利用前に https://github.com/shiguredo/oss をお読みください。
Rust で実装した Sans I/O かつ no_std 対応の Media over QUIC Transport (MOQT) ライブラリです。 MOQT / LOC / MSF / C4M の codec と、1 本の Transport Session に閉じたセッション状態機械を提供します。
- Sans I/O
- no_std 対応
- 依存は
hashbrown/noflate/nojson/base64ctの 4 つのみ (暗号処理は optional featureaws-lc-rs) - 1 本の Transport Session に閉じた endpoint-local な
Session状態機械- I/O、非同期処理、relay が担う namespace 発見・告知と forwarding は含まない
- バッファ付きインクリメンタルデコーダー (
MessageDecoder/SubgroupStreamDecoder/FetchStreamDecoder) - FETCH 応答のデルタ圧縮エンコーダー (
FetchStreamEncoder) - 対応仕様
- Media over QUIC Transport (MOQT)
draft-22 - Low Overhead Container (LOC)
draft-04 - MOQT Streaming Format (MSF)
draft-01 - Authorization scheme for MOQT using Common Access Tokens (C4M)
draft-01
- Media over QUIC Transport (MOQT)
ControlMessage は Type (varint) | Length (u16 big-endian) | Message Body 形式で encode / decode します。
use shiguredo_moqt::error::MessageError;
use shiguredo_moqt::{message::{ControlMessage, Setup}, parameter::SetupOptions};
fn main() -> Result<(), MessageError> {
// SETUP メッセージを作成してエンコード
let msg = ControlMessage::Setup(Setup {
options: SetupOptions::new(),
});
let bytes = msg.encode()?;
// bytes を制御ストリームに書き出す...
// 受信バイト列からデコード
let (decoded, consumed) = ControlMessage::decode(&bytes)?;
let _ = (decoded, consumed);
Ok(())
}QUIC / WebTransport のフレーム境界とメッセージ境界は一致しないため、受信バッファに蓄積しながらデコードします。
use shiguredo_moqt::decoder::MessageDecoder;
use shiguredo_moqt::error::MessageError;
fn main() -> Result<(), MessageError> {
let mut decoder = MessageDecoder::new();
// 受信データを追記する
// decoder.push(&data);
if let Some(msg) = decoder.try_decode_message()? {
// msg を Session::recv_control 等に渡す
let _ = msg;
}
Ok(())
}Data stream も同じ push + try_decode パターンです。
SubgroupStreamDecoder:try_decode_header()でヘッダー、try_decode_object()でオブジェクトを順次デコードし、ペイロードはtry_read_payload()/consume_payload()で進めるFetchStreamDecoder:FETCH 応答のデコードFetchStreamEncoder:FETCH 応答のデルタ圧縮エンコード
Session は I/O を持たない純粋な状態機械です。
new_client / new_server で生成し、poll_event() で取り出した SessionEvent::SendControl 等を I/O 層に渡して送信します。
use shiguredo_moqt::parameter::SetupOptions;
use shiguredo_moqt::session::core::Session;
use shiguredo_moqt::session::types::{SessionError, SessionEvent, Transport};
fn main() -> Result<(), SessionError> {
let mut session = Session::new_client(Transport::Quic, SetupOptions::new())?;
while let Some(event) = session.poll_event() {
match event {
SessionEvent::SendControl(msg) => {
// 制御ストリームに msg.encode() を書き出す
let _ = msg;
}
SessionEvent::Established => {
// 両側の SETUP が完了
}
SessionEvent::CloseSession(e) => {
// QUIC CONNECTION_CLOSE 等で接続を閉じる
let _ = e;
}
_ => {}
}
}
Ok(())
}受信側:
- bidi request stream の先頭メッセージ:
recv_request() - bidi request stream の応答:
recv_stream_message(request_id, msg) - uni data stream:
recv_data_stream_type()/recv_subgroup_header()/recv_subgroup_object()/recv_fetch_header()recv_subgroup_header()/recv_subgroup_object()はTrackDataAcceptanceを返す。recv_subgroup_object()は受信 Object ごとに購読フィルタを再適用し、フィルタ不通過はFilteredOut、キャンセル済み subscription への不要 Object はDiscardedになる
- datagram:
recv_object_datagram()
送信側:
send_subscribe()/send_publish()/send_fetch()等tick(now_ms)で GOAWAY drain や delivery timeout の期限を進める
use shiguredo_moqt::error::MessageError;
use shiguredo_moqt::msf::MsfCatalogDocument;
fn main() -> Result<(), MessageError> {
// Full / Delta を自動判別してデコード
let bytes = Vec::new();
let doc = MsfCatalogDocument::decode(&bytes)?;
let encoded = doc.encode()?;
let _ = encoded;
Ok(())
}Media / Event Timeline は msf::{encode_media_timeline / decode_media_timeline / encode_event_timeline / decode_event_timeline} で JSON と相互変換します。
TimelineEncodingOptions { gzip: true } で gzip 圧縮し、デコード時は gzip magic (0x1F 0x8B) を検出して自動展開します。
対応仕様ごとの実装状況です。
- Media over QUIC Transport (MOQT)
- MOQT Streaming Format (MSF)
- Low Overhead Container (LOC)
- C4M (Common Access Token for MoQ)
モジュール構成とアーキテクチャは docs/moqt.md を参照してください。
サンプルは Tokio、s2n-quic、shiguredo_http3、shiguredo_http2 を利用しています。 引数のパースには noargs、ログには tracing を利用しています。
moq-pub:QUIC / WebTransport over HTTP/3 / WebTransport over HTTP/2 で relay に接続し、video / audio /catalogtrack を PUBLISH するmoq-sub:QUIC / WebTransport over HTTP/3 / WebTransport over HTTP/2 で relay に接続し、catalogを SUBSCRIBE して取得し、video / audio を SUBSCRIBE して再生するtokio-moq:publisher / subscriber が共有する QUIC / WebTransport over HTTP/3 / WebTransport over HTTP/2 トランスポート層 (ライブラリ)
前提条件は Rust 1.95 以降です。
サンプルが使う s2n-quic が 1.95 を要求するためです。
shiguredo_moqt ライブラリと pbt だけであれば 1.93 で構築できます。
# publisher (疑似キャプチャ)
cargo run -p moq-pub -- --url moqt://127.0.0.1:4443 --namespace moq-example --fake-capture-device
# subscriber
cargo run -p moq-sub -- --url moqt://127.0.0.1:4443 --namespace moq-example接続経路は --url の scheme ではなく --transport (quic / wt-h3 / wt-h2) で選びます。既定は quic です。
wt-h3 / wt-h2 (WebTransport) は experimental です。s2n-quic が RESET_STREAM_AT を送出できず、WebTransport が MUST とする Reliable Size 付きのデータストリーム reset を行えないためです (詳細は examples/README.md を参照してください)。
URL の MSF fragment (#msf:<track-identifier>&c4m=<base64 token>) で C4M 認可トークンを SETUP と各制御メッセージ (PUBLISH / SUBSCRIBE / REQUEST_UPDATE) の AUTHORIZATION_TOKEN として送信できます。
--namespace を省略した場合は MSF fragment の track-identifier が示す namespace を Track Namespace として使います (--namespace と MSF fragment のどちらも無い場合はエラーになります)。
接続先となる MOQT relay は別途用意してください。
詳細なオプションは examples/README.md と各クレートの --help を参照してください。
Agent Skills 形式のスキルを同梱しています。
gh skill install コマンドで対応する AI エージェント (Claude Code, Cursor, GitHub Copilot, Gemini CLI 等) にインストールできます。
エージェントはこのライブラリの API や準拠仕様を理解した上で支援できます。
gh skill install shiguredo/moqt-rs shiguredo-moqtスキルの内容は skills/shiguredo-moqt/SKILL.md を参照してください。
このライブラリが準拠している主な IETF draft です。
- draft-ietf-moq-transport-22:Media over QUIC Transport
- draft-ietf-moq-loc-04:Media over QUIC - Low Overhead Container
- draft-ietf-moq-msf-01:MOQT Streaming Format
- draft-ietf-moq-c4m-01:Authorization scheme for MOQT using Common Access Tokens
# 全テスト実行
make test
# PBT のみ実行
make pbt
# カバレッジ付きで全テスト実行
make cover
# Fuzzing を全ターゲットで 30 秒ずつ実行
make fuzzing
# clippy
make clippy
# フォーマット
make fmt
# ビルド確認
make checkApache License 2.0
Copyright 2026 Shiguredo Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.