Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ axum-extra = { version = "0.12.6", features = ["typed-header"] }
derive_more = { version = "2.1.1", features = ["full"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
str0m = "0.23.0"
str0m = { version = "0.23.0", features = ["unversioned"] }
systemstat = "0.2.6"
thiserror = "2.0.18"
tokio = { version = "1.50.0", features = ["full"] }
Expand Down
4 changes: 3 additions & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

Rust와 [str0m](https://github.com/algesten/str0m)으로 만든 라이브 스트리밍용 WebRTC SFU입니다. 송출자는 OBS에서 WHIP으로 방송을 올립니다. 시청자는 대역폭 추정치에 맞는 simulcast 레이어를 받고, 업로드 여유가 있는 시청자는 다른 시청자에게 P2P로 스트림을 중계해 서버 부하를 덜어줍니다.

<!-- demo GIF -->
![OBS 방송을 재생하면서 simulcast 레이어를 전환하는 시청 페이지](docs/assets/demo.webp)

OBS 방송을 재생하는 시청 페이지입니다. 자동 모드로 시작한 뒤, 시청자가 가장 낮은 simulcast 레이어로 내렸다가 가장 높은 레이어로 되돌립니다.

## 측정 결과

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ English | [한국어](README.ko.md)

A WebRTC SFU for live streaming, written in Rust on [str0m](https://github.com/algesten/str0m). Publishers push over WHIP from OBS. Viewers get the simulcast layer their bandwidth estimate allows, and viewers with upload to spare relay the stream to each other over a peer link, taking load off the server.

<!-- demo GIF -->
![The watch page playing an OBS broadcast and switching simulcast layers](docs/assets/demo.webp)

The watch page playing an OBS broadcast. It starts in automatic mode, then the viewer switches to the lowest simulcast layer and back to the highest.

## Measured

Expand Down
Binary file added docs/assets/demo.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 19 additions & 1 deletion src/sfu/streamer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use std::{

use str0m::{
Event, IceConnectionState, Rtc,
format::Codec,
media::{KeyframeRequest, MediaKind, Mid, Rid},
unversioned::{H264Packetizer, Packetizer},
};
use uuid::Uuid;

Expand All @@ -21,6 +23,8 @@ use crate::{
},
};

const MAX_PACKET_SIZE: usize = 1200;

impl Streamer {
pub fn new(rtc: Rtc, session_id: Uuid) -> Streamer {
Streamer {
Expand Down Expand Up @@ -61,10 +65,24 @@ impl Streamer {
.iter()
.find(|l| l.rid == rid)
{
let frame_size = match data.params.spec().codec {
Codec::H264 => {
let mut packetizer = H264Packetizer::default();
if let Ok(packet) =
packetizer.packetize(MAX_PACKET_SIZE, &data.data)
{
packet.iter().map(|v| v.len()).sum()
} else {
data.data.len()
}
}
_ => data.data.len(),
};

let push_outcome = simulcast_layer
.bitrate_estimator
.borrow_mut()
.push(data.data.len(), Instant::now());
.push(frame_size, Instant::now());

if matches!(push_outcome, PushOutcome::EstimateBecameAvailable) {
*should_reevaluate = true;
Expand Down
10 changes: 10 additions & 0 deletions tests/viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@ async fn the_server_measures_every_layer_it_receives() {
high > low * 4,
"the gap matches what was sent, 300 against 2500 kbps: {estimates:?}"
);

// Ranking alone would also hold for a count of packets or frames. The
// figure has to be the bitrate itself, since layers are picked by it.
for (bps, sent_kbps) in measured.iter().zip([300u64, 800, 2500]) {
let sent = sent_kbps * 1000;
assert!(
(sent * 3 / 4..=sent * 5 / 4).contains(bps),
"a layer sent at {sent_kbps} kbps is measured near it: {estimates:?}"
);
}
}

/// Auto mode filters on two numbers the SDP cannot supply: a bitrate estimate
Expand Down
Loading