10 releases

0.2.3 Jan 29, 2025
0.2.2 Jan 23, 2025
0.1.6 Dec 16, 2024
0.1.1 Nov 25, 2024
0.0.5 Nov 18, 2024

#97 in Video

Download history 71/week @ 2024-11-12 304/week @ 2024-11-19 145/week @ 2024-11-26 165/week @ 2024-12-03 134/week @ 2024-12-10 60/week @ 2024-12-17 152/week @ 2024-12-31 145/week @ 2025-01-07 14/week @ 2025-01-14 117/week @ 2025-01-21 119/week @ 2025-01-28 17/week @ 2025-02-04

299 downloads per month

Apache-2.0

115KB
2.5K SLoC

Rheomesh

Build docs.rs Crates.io GitHub

Rheomesh is a WebRTC SFU library that provides a simple API for building real-time communication applications. This provides an SDK to help you build a WebRTC SFU server. Here is an example SFU server for video streaming.

Install

Add your Cargo.toml like this:

[dependencies]
rheomesh = { version = "0" }

Usage

Create router and transports

First of all, please create a router. Router accommodates multiple transports and they can communicate with each other. That means transports belonging to the same Router can send/receive their media. Router is like a meeting room.

use rheomesh::config::MediaConfig;
use rheomesh::router::Router;

//...

async fn new() {
  let config = MediaConfig::default();
  let router = Router::new(config);
}

Next, please create publish and subscribe transports.

use rheomesh::config::WebRTCTransportConfig

async fn new() {
  //...
  let mut config = WebRTCTransportConfig::default();
  config.configuration.ice_servers = vec![RTCIceServer {
    urls: vec!["stun:stun.l.google.com:19302".to_owned()],
    ..Default::default()
  }];
  let publish_transport = router.create_publish_transport(config.clone()).await;
  let subscribe_transport = router.create_subscribe_transport(config.clone()).await;
}

Handle publish events

Bind on_ice_candidate callback

publish_transport
  .on_ice_candidate(Box::new(move |candidate| {
      let init = candidate.to_json().expect("failed to parse candidate");
      // Send `init` message to client. The client have to call `addIceCandidate` method with this parameter.
  }))
  .await;

Please send init to client. The corresponding client-side handler is here.

Handle RTCIceCandidateInit

On the other hand, you will receive RTCIceCandidateInit message from client, here.

let _ = publish_transport
  .add_ice_candidate(candidate)
  .await
  .expect("failed to add ICE candidate");

Handle offer message

Then, server will receive offer from client, the corresponding client-side handler is here.

let answer = publish_transport
  .get_answer(offer)
  .await
  .expect("failed to connect publish_transport");
// Send `answer` message to client. The client have to call `setAnswer` method.

Please send answer to client. The corresponding client-side handler is here.

Publish

Finally, please handle publish event with track_id.

let publisher = publish_transport.publish(track_id).await;

Handle subscribe events

Bind on_ice_candidate and on_negotiation_needed callback

subscribe_transport
  .on_ice_candidate(Box::new(move |candidate| {
      let init = candidate.to_json().expect("failed to parse candidate");
      // Send `init` message to client. The client have to call `addIceCandidate` method with this parameter.
  }))
    .await;
subscribe_transport
  .on_negotiation_needed(Box::new(move |offer| {
    // Send `offer` message to client. The client have to call `setOffer` method.
  }))

Please send init to client. The corresponding client-side handler is here.

Handle RTCIceCandidateInit

On the other hand, you will receive RTCIceCandidateInit message from client, here.

let _ = subscribe_transport
  .add_ice_candidate(candidate)
  .await
  .expect("failed to add ICE candidate");

Subscribe

Then, please call subscribe method.

let (subscriber, offer) = subscribe_transport
  .subscribe(track_id)
  .await
  .expect("failed to connect subscribe_transport");
// Send `offer` message to client. The client have to call `setOffer` method.

Please send offer message to client. The corresponding client-side handler is here.

Handle answer message

Finally, server will receive answer from client, the corresponding client-side handler is here.

let _ = subscribe_transport
  .set_answer(answer)
  .await
  .expect("failed to set answer");

Dependencies

~58MB
~1M SLoC