Skip to content

Commit 21e2367

Browse files
davidzhaocs50victortheomonnom
authored
Update README (#236)
* Update README * couple of more * token generation example * chore: update 'Receive video frames of a subscribed track' docs (#238) * fixed access token in readme * nit * fmt + api * Update README.md * Delete Cargo.lock * Revert "Delete Cargo.lock" This reverts commit a949178. --------- Co-authored-by: victor <52110451+cs50victor@users.noreply.github.com> Co-authored-by: Théo Monnom <theo.monnom@outlook.com>
1 parent e3e8a45 commit 21e2367

File tree

12 files changed

+170
-84
lines changed

12 files changed

+170
-84
lines changed

README.md

Lines changed: 114 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -12,56 +12,81 @@
1212

1313
[![crates.io](https://img.shields.io/crates/v/livekit.svg)](https://crates.io/crates/livekit)
1414
[![livekit docs.rs](https://img.shields.io/docsrs/livekit)](https://docs.rs/livekit/latest/)
15-
[![Builds](https://github.com/livekit/client-sdk-native/actions/workflows/builds.yml/badge.svg?branch=main)](https://github.com/livekit/client-sdk-native/actions/workflows/builds.yml)
16-
[![Tests](https://github.com/livekit/client-sdk-native/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/livekit/client-sdk-native/actions/workflows/tests.yml)
17-
18-
⚠️ Warning
19-
20-
> This SDK is currently in Developer Preview mode and not ready for production use. There will be bugs and APIs may change during this period.
21-
>
22-
> We welcome and appreciate any feedback or contributions. You can create issues here or chat live with us in the #rust-developer-preview channel within the [LiveKit Community Slack](https://livekit.io/join-slack).
15+
[![Builds](https://github.com/livekit/rust-sdks/actions/workflows/builds.yml/badge.svg?branch=main)](https://github.com/livekit/rust-sdks/actions/workflows/builds.yml)
16+
[![Tests](https://github.com/livekit/rust-sdks/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/livekit/rust-sdks/actions/workflows/tests.yml)
2317

2418
## Features
2519

2620
- [x] Receiving tracks
27-
- [x] Cross-platform ( currently tested on Windows & MacOS )
28-
- [x] Data channels
2921
- [x] Publishing tracks
22+
- [x] Data channels
23+
- [x] Simulcast
24+
- [ ] SVC codecs (AV1/VP9)
3025
- [ ] Adaptive Streaming
3126
- [ ] Dynacast
32-
- [x] Simulcast
33-
- [ ] Hardware video enc/dec
34-
- [ ] NvEnc for Windows
27+
- [x] Hardware video enc/dec
3528
- [x] VideoToolbox for MacOS/iOS
29+
- Supported Platforms
30+
- [x] Windows
31+
- [x] MacOS
32+
- [x] Linux
33+
- [x] iOS
34+
- [x] Android
3635

3736
## Crates
3837

39-
- `livekit-core`: LiveKit protocol implementation
40-
- `livekit-utils`: Shared utilities between our crates
41-
- `livekit-ffi`: Bindings for other languages. Uses `livekit-core`.
42-
- `libwebrtc`: Safe Rust bindings to libwebrtc
43-
- `webrtc-sys`: Unsafe bindings to libwebrtc
38+
- `livekit-api`: Server APIs and auth token generation
39+
- `livekit`: LiveKit real-time SDK
40+
- `livekit-ffi`: Internal crate, used to generate bindings for other languages
4441

45-
## Motivation and Design Goals
42+
## Getting started
4643

47-
LiveKit aims to provide an open source, end-to-end WebRTC stack that works everywhere. We have two goals in mind with this SDK:
44+
Currently, Tokio is required to use this SDK, however we plan to make the async executor runtime agnostic.
4845

49-
1. Build a standalone, cross-platform LiveKit client SDK for Rustaceans.
50-
2. Build a common core for other platform-specific SDKs (e.g. Unity, Unreal, iOS, Android)
46+
## Using Server API
5147

52-
Regarding (2), we've already developed a number of [client SDKs](https://github.com/livekit?q=client-sdk&type=all) for several platforms and encountered a few challenges in the process:
48+
### Generating an access token
5349

54-
- There's a significant amount of business/control logic in our signaling protocol and WebRTC. Currently, this logic needs to be implemented in every new platform we support.
55-
- Interactions with media devices and encoding/decoding are specific to each platform and framework.
56-
- For multi-platform frameworks (e.g. Unity, Flutter, React Native), the aforementioned tasks proved to be extremely painful.
50+
```rust
51+
use livekit_api::access_token;
52+
use std::env;
53+
54+
fn create_token() -> Result<String, access_token::AccessTokenError> {
55+
let api_key = env::var("LIVEKIT_API_KEY").expect("LIVEKIT_API_KEY is not set");
56+
let api_secret = env::var("LIVEKIT_API_SECRET").expect("LIVEKIT_API_SECRET is not set");
57+
58+
let token = access_token::AccessToken::with_api_key(&api_key, &api_secret)
59+
.with_identity("rust-bot")
60+
.with_name("Rust Bot")
61+
.with_grants(access_token::VideoGrants {
62+
room_join: true,
63+
room: "my-room".to_string(),
64+
..Default::default()
65+
})
66+
.to_jwt();
67+
return token
68+
}
69+
```
5770

58-
Thus, we posited a Rust SDK, something we wanted build anyway, encapsulating all our business logic and platform-specific APIs into a clean set of abstractions, could also serve as the foundation for our other SDKs!
71+
### Creating a room with RoomService API
5972

60-
We'll first use it as a basis for our Unity SDK (under development), but over time, it will power our other SDKs, as well.
73+
```rust
74+
use livekit_api::services::room::{CreateRoomOptions, RoomClient};
6175

62-
## Getting started
76+
#[tokio::main]
77+
async fn main() {
78+
let room_service = RoomClient::new("http://localhost:7880").unwrap();
6379

64-
Currently, Tokio is required to use this SDK, however we plan to make the async executor runtime agnostic.
80+
let room = room_service
81+
.create_room("my_room", CreateRoomOptions::default())
82+
.await
83+
.unwrap();
84+
85+
println!("Created room: {:?}", room);
86+
}
87+
```
88+
89+
## Using Real-time SDK
6590

6691
### Connect to a Room and listen for events:
6792

@@ -70,76 +95,88 @@ use livekit::prelude::*;
7095

7196
#[tokio::main]
7297
async fn main() -> Result<()> {
73-
let (room, mut room_events) = Room::connect(&url, &token).await?;
74-
75-
while let Some(event) = room_events.recv().await {
76-
match event {
77-
RoomEvent::TrackSubscribed { track, publication, participant } => {
78-
// ...
79-
}
80-
_ => {}
81-
}
82-
}
83-
84-
Ok(())
98+
let (room, mut room_events) = Room::connect(&url, &token).await?;
99+
100+
while let Some(event) = room_events.recv().await {
101+
match event {
102+
RoomEvent::TrackSubscribed { track, publication, participant } => {
103+
// ...
104+
}
105+
_ => {}
106+
}
107+
}
108+
109+
Ok(())
85110
}
86111
```
87112

88113
### Receive video frames of a subscribed track
89114

90115
```rust
116+
...
117+
use futures::StreamExt; // this trait is required for iterating on audio & video frames
118+
use livekit::prelude::*;
119+
91120
match event {
92-
RoomEvent::TrackSubscribed { track, publication, participant } => {
93-
if let RemoteTrackHandle::Video(video_track) => {
94-
let rtc_track = video_track.rtc_track();
95-
rtc_track.on_frame(Box::new(move |frame, buffer| {
96-
// Just received a video frame!
97-
// The buffer is YuvEncoded, you can decode it to ABGR by using our yuv_helper
98-
// See the basic_room example for the conversion
99-
});
100-
} else {
101-
// Audio Track..
102-
}
103-
}
104-
_ => {}
121+
RoomEvent::TrackSubscribed { track, publication, participant } => {
122+
match track {
123+
RemoteTrack::Audio(audio_track) => {
124+
let rtc_track = audio_track.rtc_track();
125+
let mut audio_stream = NativeAudioStream::new(rtc_track);
126+
tokio::spawn(async move {
127+
// Receive the audio frames in a new task
128+
while let Some(audio_frame) = audio_stream.next().await {
129+
log::info!("received audio frame - {audio_frame:#?}");
130+
}
131+
});
132+
},
133+
RemoteTrack::Video(video_track) => {
134+
let rtc_track = video_track.rtc_track();
135+
let mut video_stream = NativeVideoStream::new(rtc_track);
136+
tokio::spawn(async move {
137+
// Receive the video frames in a new task
138+
while let Some(video_frame) = video_stream.next().await {
139+
log::info!("received video frame - {video_frame:#?}");
140+
}
141+
});
142+
},
143+
}
144+
},
145+
_ => {}
105146
}
106147
```
107148

108149
## Examples
109150

110-
We made a [basic room demo](https://github.com/livekit/client-sdk-native/tree/main/examples/basic_room) leveraging all the current SDK features. Videos are rendered using wgpu and egui.
111-
112-
![](https://github.com/livekit/client-sdk-rust/blob/main/examples/images/simple-room-demo.gif)
151+
![](https://github.com/livekit/rust-sdks/blob/main/examples/images/simple-room-demo.gif)
113152

114-
## FAQ
153+
- [basic room](https://github.com/livekit/rust-sdks/tree/main/examples/basic_room): simple example connecting to a room.
154+
- [wgpu_room](https://github.com/livekit/rust-sdks/tree/main/examples/wgpu_room): complete example app with video rendering using wgpu and egui.
155+
- [mobile](https://github.com/livekit/rust-sdks/tree/main/examples/mobile): mobile app targeting iOS and Android
156+
- [play_from_disk](https://github.com/livekit/rust-sdks/tree/main/examples/play_from_disk): publish audio from a wav file
157+
- [save_to_disk](https://github.com/livekit/rust-sdks/tree/main/examples/save_to_disk): save received audio to a wav file
115158

116-
### Do you plan to offer a C/C++ SDK?
117-
118-
Yes! In fact, we also plan to release an SDK for C++ in the coming months. It, like our other platform-specific SDKs, will use the Rust SDK. 🙂
119-
120-
### Did you consider C/C++ as your common core?
159+
## Motivation and Design Goals
121160

122-
Yes. We chose Rust over C++ for a few reasons:
161+
LiveKit aims to provide an open source, end-to-end WebRTC stack that works everywhere. We have two goals in mind with this SDK:
123162

124-
- Rust's ownership model and thread-safety leads to fewer crashes/issues.
125-
- Rust's build system requires less configuration and is easier to work with.
126-
- While we love C/C++, it's a bit nicer to write code in Rust.
127-
- Rust has a rich ecosystem of tools (e.g. websockets, async executor).
128-
- Having the WebAssembly target will be useful down the road, C++ has Emscripten but it's a bit harder to set up and doesn't yet have WebRTC support.
163+
1. Build a standalone, cross-platform LiveKit client SDK for Rustaceans.
164+
2. Build a common core for other platform-specific SDKs (e.g. Unity, Unreal, iOS, Android)
129165

130-
### Did you look at [Arcas](https://github.com/arcas-io/libwebrtc) for libwebrtc bindings?
166+
Regarding (2), we've already developed a number of [client SDKs](https://github.com/livekit?q=client-sdk&type=all) for several platforms and encountered a few challenges in the process:
131167

132-
Yes. Our build system is inspired by LBL's work! Given that some of our logic (e.g. hardware decoder code) is in C++ and that we may need to bridge more/different things than Arcas, we decided it was better to have our own bindings for full control.
168+
- There's a significant amount of business/control logic in our signaling protocol and WebRTC. Currently, this logic needs to be implemented in every new platform we support.
169+
- Interactions with media devices and encoding/decoding are specific to each platform and framework.
170+
- For multi-platform frameworks (e.g. Unity, Flutter, React Native), the aforementioned tasks proved to be extremely painful.
133171

134-
### Did you consider using [webrtc.rs](https://webrtc.rs/) instead of libwebrtc?
135-
Yes! As webrtc.rs matures, we'll eventually migrate to a pure Rust stack. For now, we chose libwebrtc for a few reasons:
172+
Thus, we posited a Rust SDK, something we wanted build anyway, encapsulating all our business logic and platform-specific APIs into a clean set of abstractions, could also serve as the foundation for our other SDKs!
136173

137-
- Chrome's adoption and usage means libwebrtc is thoroughly battle-tested.
138-
- webrtc.rs is ported from Pion (which [our SFU](https://github.com/livekit/livekit) is built on) and a better fit for server-side use.
139-
- libwebrtc currently supports more features like encoding/decoding and includes platform-specific code for dealing with media devices.
174+
We'll first use it as a basis for our Unity SDK (under development), but over time, it will power our other SDKs, as well.
140175

141176
<!--BEGIN_REPO_NAV-->
177+
142178
<br/><table>
179+
143180
<thead><tr><th colspan="2">LiveKit Ecosystem</th></tr></thead>
144181
<tbody>
145182
<tr><td>Client SDKs</td><td><a href="https://github.com/livekit/components-js">Components</a> · <a href="https://github.com/livekit/client-sdk-js">JavaScript</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <a href="https://github.com/livekit/client-sdk-react-native">React Native</a> · <b>Rust</b> · <a href="https://github.com/livekit/client-sdk-python">Python</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (web)</a> · <a href="https://github.com/livekit/client-sdk-unity">Unity (beta)</a></td></tr><tr></tr>

examples/Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ members = [
55
"save_to_disk",
66
"wgpu_room",
77
"webhooks",
8+
"api",
89
]

examples/api/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "api"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
tokio = { version = "1", features = ["full", "parking_lot"] }
8+
livekit-api = { path = "../../livekit-api", version = "0.2.0", features = ["native-tls"] }
9+
futures = "0.3"
10+

examples/api/src/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use livekit_api::services::room::{CreateRoomOptions, RoomClient};
2+
3+
#[tokio::main]
4+
async fn main() {
5+
let room_service = RoomClient::new("http://localhost:7880").unwrap();
6+
7+
let room = room_service
8+
.create_room("my_room", CreateRoomOptions::default())
9+
.await
10+
.unwrap();
11+
12+
println!("Created room: {:?}", room);
13+
}

examples/basic_room/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ edition = "2021"
77
tokio = { version = "1", features = ["full"] }
88
env_logger = "0.10"
99
livekit = { path = "../../livekit", version = "0.2.0", features = ["native-tls"]}
10+
livekit-api = { path = "../../livekit-api", version = "0.2.0"}
1011
log = "0.4"

examples/basic_room/src/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use livekit_api::access_token;
12
use livekit::prelude::*;
23
use std::env;
34

@@ -9,7 +10,20 @@ async fn main() {
910
env_logger::init();
1011

1112
let url = env::var("LIVEKIT_URL").expect("LIVEKIT_URL is not set");
12-
let token = env::var("LIVEKIT_TOKEN").expect("LIVEKIT_TOKEN is not set");
13+
let api_key = env::var("LIVEKIT_API_KEY").expect("LIVEKIT_API_KEY is not set");
14+
let api_secret = env::var("LIVEKIT_API_SECRET").expect("LIVEKIT_API_SECRET is not set");
15+
16+
let token = access_token::AccessToken::with_api_key(&api_key, &api_secret)
17+
.with_identity("rust-bot")
18+
.with_name("Rust Bot")
19+
.with_grants(access_token::VideoGrants {
20+
room_join: true,
21+
room: "my-room".to_string(),
22+
..Default::default()
23+
})
24+
.to_jwt()
25+
.unwrap();
26+
1327

1428
let (room, mut rx) = Room::connect(&url, &token, RoomOptions::default())
1529
.await

libwebrtc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55
homepage = "https://livekit.io"
66
license = "Apache-2.0"
77
description = "Livekit safe bindings to libwebrtc"
8-
repository = "https://github.com/livekit/client-sdk-rust"
8+
repository = "https://github.com/livekit/rust-sdks"
99

1010
[dependencies]
1111
livekit-protocol = { path = "../livekit-protocol", version = "0.2.0" }

livekit-api/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.2.0"
44
license = "Apache-2.0"
55
description = "Rust Server SDK for LiveKit"
66
edition = "2021"
7-
repository = "https://github.com/livekit/client-sdk-rust"
7+
repository = "https://github.com/livekit/rust-sdks"
88

99
[features]
1010
# By default ws TLS is not enabled

livekit-ffi/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ name = "livekit-ffi"
33
version = "0.3.13"
44
edition = "2021"
55
license = "Apache-2.0"
6-
description = "LiveKit interface to easily use the Rust SDK on other languages"
7-
repository = "https://github.com/livekit/client-sdk-rust"
6+
description = "FFI interface for bindings in other languages"
7+
repository = "https://github.com/livekit/rust-sdks"
88

99
[features]
1010
default = ["rustls-tls-native-roots"]

livekit-protocol/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.2.0"
44
edition = "2021"
55
license = "Apache-2.0"
66
description = "Livekit protocol and utilities for the Rust SDK"
7-
repository = "https://github.com/livekit/client-sdk-rust"
7+
repository = "https://github.com/livekit/rust-sdks"
88

99
[dependencies]
1010
tokio = { version = "1", features = ["full"] }

livekit/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.2.0"
44
edition = "2021"
55
license = "Apache-2.0"
66
description = "Rust Client SDK for LiveKit"
7-
repository = "https://github.com/livekit/client-sdk-rust"
7+
repository = "https://github.com/livekit/rust-sdks"
88

99
[features]
1010
# By default ws TLS is not enabled

0 commit comments

Comments
 (0)