6 releases

new 0.1.6 Dec 16, 2024
0.1.4 Dec 8, 2024
0.1.1 Nov 25, 2024
0.0.5 Nov 18, 2024

#60 in Video

Download history 286/week @ 2024-11-18 158/week @ 2024-11-25 216/week @ 2024-12-02 82/week @ 2024-12-09

742 downloads per month

Apache-2.0

83KB
2K 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

~57MB
~1M SLoC