以前WHIPについてのサポート記事を書いた.
これの続きで,ようやっとWHEPのサポートを開始した.
こちらは0.8.0から入っている.
WHEPとはこういうやつ
WHIPと同じくWebRTCのシグナリングをHTTPでなんとかしたい話の,受信側のプロトコルで,HTTPだけで映像を受信できるようなシグナリングをしたいという理解.
プロトコルとしてはHTTPエンドポイントを作るだけだが,WHIPとは方向が真逆
配信側は,クライアントからHTTPエンドポイントを叩いて,SDPを送りつけるところからスタートした.これはWebSocketを使うときと同じで,基本的にクライアントサイドで送りたい映像や音声を混ぜ込んだSDPを作れる.これをサーバに送りつけることで,配信の初期段階がスタートする.
しかし,受信の場合,メディアの情報はサーバ側にしかないわけで,WebSocketではSDP生成はサーバ側で行っていた.というか大抵のSFUサーバは,subscriberに対してSDPを送りつける形を取る. HTTPのエンドポイントを用意するだけだと,サーバ側からクライアント側に一方的に送りつけることができない.ので,WHEPではクライアントからメディア情報が入っていないSDPを送りつけ,サーバで不足しているメディアの情報を埋めてから送り返すというフローを取る.こうすることで,通常のHTTPサーバのままSDPのやり取りを開始することができる.
で,その先はWebSocketの場合とそこまで変わらないし,用意するエンドポイントもWHIPとそこまで大差ない.
- POST /whep/{session_id}/{publisher_id} - 空のSDPを受け取り,
publisher_idで指定されたpublisherが持っているtrack情報を埋めたSDPを返す - PATCH /whep/{session_id} - Trickle ICEのSDPを受け取る
- DELETE /whep/{session_id} - WHEPのセッションを終わりにする
最初のPOSTエンドポイントだけ,publisher_id を受け取る.これは,どのメディアをsubscribeしたいかの指定をする場所がないので,エンドポイントのパスに入れている.
セッションの概念はWHIPと同じ.今回は,subscribe_transportを用意する必要があるので
struct SessionStore { sessions: Arc<Mutex<HashMap<String, Session>>> } struct Session { session_id: String, // Or user_id. subscribe_transport: Arc<SubscribeTransport> } #[async_trait::async_trait] impl SubscribeTransportProvider for SessionStore { async fn get_subscribe_transport( &self, session_id: &str, ) -> Result<Arc<SubscribeTransport>, actix_web::Error> { let sessions = self.sessions.lock().await; if let Some(session) = sessions.get(session_id) { let s = session.subscribe_transport.clone(); Ok(s) } else { Err(actix_web::error::ErrorNotFound("Session not found")) } } }
こういうメソッドを実装してやれば良い.
使い方
actix-webを使っている場合は,endpointを突っ込むだけ.これはWHIPと同じ.
#[actix_web::main] async fn main() -> std::io::Result<()> { let store = SessionStore { sessions: Arc::new(Mutex::new(HashMap::new())), }; let store_data = Data::new(store.clone()); let endpoint = WhepEndpoint::new(store); HttpServer::new(move || { App::new() .app_data(store_data.clone()) .configure(|cfg| { endpoint.clone().configure(cfg); }) }) .bind("0.0.0.0:4000")? .run() .await }
これで前述の3つのエンドポイントが自動的に生える.
WHEPはサーバ側のプロトコルを定義しているだけなので,クライアント側はこのプロトコルに従ってくれていれば,好きに作ってもらって問題ない.
ただ,一応サンプルは用意しているので,この辺を参考にしてもらうとだいたい何をすればいいか理解できると思う.
追加でのサポート予定
WHIPのところでも触れたが,現状actix-webへの差し込みしかサポートしていない.これを将来的に別のwebサーバに対しても差し込めるような関数を用意することは考えている.
また,WHEPのProtocol extensionsには
- Server Sent Events extension
- Video Layer Selection extension
の項目があり,これらはサポートしたいと思っている.RheomeshはSimulcastもSVCもサポートしているが,現状WHEPだとレイヤー選択をする口がないので.
また,これはWHIP・WHEP共通の話だが,
- STUN/TURN server configuration
- Authentication and authorization
あたりもサポートしたいと思っているよ.