|
2 | 2 |
|
3 | 3 | ## Why |
4 | 4 |
|
5 | | -`SFU-to-SFU` is an example of a cascaded decentralised SFU. The intention is to be a implementation of Matrix's [MSC3401: Native Group VoIP signalling](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
6 | | -This example is self contained and doesn't require any external software. The project was informed by the following goals. |
7 | | - |
8 | | -* **Easy Scaling** - SFU count can be grown/shrunk as users arrive. We don't scale on the dimension of calls making things easier. |
9 | | -* **Shorter Last Mile** - Users can connect to SFUs closest to them. Links `SFU <-> SFU` are higher quality then public hops. |
10 | | -* **Flexibility in WebRTC server choice** - All communication takes place using standard protocols/formats. You can use whatever server software best fits your needs. |
11 | | -* **Client Simplicity** - Clients will need to be created on lots of platforms. We should aim to use native WebRTC features as much as possible. |
12 | | - |
13 | | -The SFUs themselves have no concept of conference calls/rooms etc... All of this is communicated in the Matrix room. The SFUs themselves just operate off of |
14 | | -pub/sub semantics. The pub/sub streams are keyed by `foci`, `call_id`, `device_id` and `purpose` these keys come from [MSC3401](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
15 | | - |
16 | | -Lets say you have a Matrix room where user `Alice` wishes to publish a screenshare to `Bob` and `Charlie`. |
17 | | - |
18 | | -``` |
19 | | -* `Alice` establishes a session with a SFU |
20 | | -* `Alice` publishes a screenshare feed with `call_id`, `device_id` and `purpose` |
21 | | -* `Alice` publishes to the matrix room with the values `foci`, `call_id`, `device_id` and `purpose` |
22 | | -
|
23 | | -# Connecting directly to publishers FOCI |
24 | | -* `Bob` connects directly to `foci` and establishes a session. |
25 | | -* `Bob` requests a stream with values `foci`, `call_id`, `device_id` and `purpose`. |
26 | | -
|
27 | | -# Connect to FOCI through different SFU |
28 | | -* `Charlie` connects to a SFU they run on a remote host. |
29 | | -* `Charlie` requests a stream with values `foci`, `call_id`, `device_id` and `purpose`. |
30 | | -* `Charlie`'s SFU connects to `foci` and requests the stream. |
31 | | -* `Alice`'s stream arrives to Charlie via `Alice -> FOCI -> Charlie's SFU -> Charlie` |
32 | | -``` |
| 5 | +`SFU-to-SFU` is an example of a cascaded decentralised SFU. The intention is to |
| 6 | +be a implementation of Matrix's [MSC3401: Native Group VoIP |
| 7 | +signalling](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
| 8 | +This example is self contained and doesn't require any external software. The |
| 9 | +project was informed by the following goals. |
| 10 | + |
| 11 | +* **Easy Scaling** - SFU count can be grown/shrunk as users arrive. We don't |
| 12 | + scale on the dimension of calls making things easier. |
| 13 | +* **Shorter Last Mile** - Users can connect to SFUs closest to them. Links `SFU |
| 14 | + <-> SFU` are higher quality then public hops. |
| 15 | +* **Flexibility in WebRTC server choice** - All communication takes place using |
| 16 | + standard protocols/formats. You can use whatever server software best fits |
| 17 | + your needs. |
| 18 | +* **Client Simplicity** - Clients will need to be created on lots of platforms. |
| 19 | + We should aim to use native WebRTC features as much as possible. |
| 20 | + |
| 21 | +This implements the MSC only roughly - given the current experimental nature of |
| 22 | +this projects, it deviates in certain areas from the MSC. |
33 | 23 |
|
34 | 24 | ## How |
35 | | -### Establishing a session |
36 | | -Client sends a POST with a WebRTC Offer that is datachannel only. Server responds with Answer. |
37 | | - |
38 | | -Server will open a datachannel called `signaling`. Clients can send publish/subscribe now. |
39 | | - |
40 | | -`POST /createSession` |
41 | | - |
42 | | -`Request` |
43 | | -``` |
44 | | -o=- 6685856480478485828 2 IN IP4 127.0.0.1 |
45 | | -s=- |
46 | | -t=0 0 |
47 | | -a=group:BUNDLE 0 |
48 | | -a=extmap-allow-mixed |
49 | | -a=msid-semantic: WMS |
50 | | -m=application 9 UDP/DTLS/SCTP webrtc-datachannel |
51 | | -c=IN IP4 0.0.0.0 |
52 | | -a=ice-ufrag:gLSF |
53 | | -a=ice-pwd:xuxSHK0uJuSb607uYunnzlCQ |
54 | | -a=ice-options:trickle |
55 | | -a=fingerprint:sha-256 C2:1F:9B:A1:C2:DF:7E:13:E4:F9:64:F5:EC:4D:17:A1:89:21:0E:32:61:2A:B7:A5:A7:2A:7C:06:AC:FB:B2:A1 |
56 | | -a=setup:actpass |
57 | | -a=mid:0 |
58 | | -a=sctp-port:5000 |
59 | | -a=max-message-size:262144 |
60 | | -``` |
61 | | - |
62 | | -`Response` |
63 | | -``` |
64 | | -o=- 1712750552704711910 2 IN IP4 127.0.0.1 |
65 | | -s=- |
66 | | -t=0 0 |
67 | | -a=group:BUNDLE 0 |
68 | | -a=extmap-allow-mixed |
69 | | -a=msid-semantic: WMS |
70 | | -m=application 9 UDP/DTLS/SCTP webrtc-datachannel |
71 | | -c=IN IP4 0.0.0.0 |
72 | | -a=ice-ufrag:90cu |
73 | | -a=ice-pwd:PARVC6h9kLvvgCqxSocjrXYZ |
74 | | -a=ice-options:trickle |
75 | | -a=fingerprint:sha-256 7F:79:0F:50:FF:D1:3F:DF:CA:BD:06:89:2B:C8:05:2E:EC:7D:EF:66:AF:A8:6E:D8:70:C6:74:68:E6:5C:47:D7 |
76 | | -a=setup:active |
77 | | -a=mid:0 |
78 | | -a=sctp-port:5000 |
79 | | -a=max-message-size:262144 |
80 | | -``` |
81 | | - |
82 | | -### Publish a Stream |
83 | | -A user can start publish a stream by making a JSON request to publish with a new Offer. With the following keys. |
84 | | - |
85 | | -* `event` - Must be `publish` |
86 | | -* `id` - Unique ID for this message. Allows server to respond with with errors |
87 | | -* Stream Identification - `call_id`, `device_id`, `purpose` |
88 | | -* `sdp` - Offer frome the Peer. Any new additional tracks will belong to the stream. |
89 | | - |
90 | | -``` |
91 | | -{ |
92 | | - event: 'publish', |
93 | | - id: `ABC`, |
94 | | - call_id: 'AAA', |
95 | | - device_id: 'BBB', |
96 | | - purpose: 'DDD', |
97 | | - sdp: `...`, |
98 | | -} |
99 | | -``` |
100 | | - |
101 | | -** Errors ** |
102 | | -* Stream already exists |
103 | | -* Server over capacity |
104 | | - |
105 | | -The server will respond to the `subscribe` with the answer. |
106 | | - |
107 | | -``` |
108 | | -{ |
109 | | - event: 'publish', |
110 | | - id: `ABC`, |
111 | | - call_id: 'AAA', |
112 | | - device_id: 'BBB', |
113 | | - purpose: 'DDD', |
114 | | - sdp: `...`, |
115 | | -} |
116 | | -``` |
117 | | - |
118 | | - |
119 | | -### Subscribe to a Stream |
120 | | -A user can subscribe to a stream by making a JSON request to subscribe with a new Offer. With the following keys. |
121 | | - |
122 | | -* `event` - Must be `subscribe` |
123 | | -* `id` - Unique ID for this message. Allows server to respond with with errors |
124 | | -* Stream Identification - `call_id`, `device_id`, `purpose` |
125 | | - |
126 | | -``` |
127 | | -{ |
128 | | - event: 'subscribe', |
129 | | - id: `ABC`, |
130 | | - call_id: 'AAA', |
131 | | - device_id: 'BBB', |
132 | | - purpose: 'DDD', |
133 | | - sdp: `...`, |
134 | | -} |
135 | | -``` |
136 | | - |
137 | | -The client will respond to the `subscribe` with the answer. |
138 | 25 |
|
139 | | -``` |
140 | | -{ |
141 | | - event: 'subscribe', |
142 | | - id: `ABC`, |
143 | | - sdp: `...`, |
144 | | -} |
145 | | -``` |
| 26 | +### Configuration |
146 | 27 |
|
147 | | -** Errors ** |
148 | | -* Stream doesn'texist |
149 | | -* Server over capacity |
| 28 | +* `cp config.yaml.sample config.yaml` |
| 29 | +* Fill in `config.yaml` |
150 | 30 |
|
151 | | -### Unpublish a Stream |
152 | | -``` |
153 | | -{ |
154 | | - event: 'unpublish', |
155 | | - id: `ABC`, |
156 | | - call_id: 'AAA', |
157 | | - device_id: 'BBB', |
158 | | - purpose: 'DDD', |
159 | | -} |
160 | | -``` |
| 31 | +### Running |
161 | 32 |
|
162 | | -### Unsubscribe to a Stream |
| 33 | +* `./scripts/run.sh` |
| 34 | +* Access at <http://localhost:8080> |
163 | 35 |
|
164 | | -``` |
165 | | -{ |
166 | | - event: 'unsubscribe', |
167 | | - id: `ABC`, |
168 | | - call_id: 'AAA', |
169 | | - device_id: 'BBB', |
170 | | - purpose: 'DDD', |
171 | | -} |
172 | | -``` |
| 36 | +### Profiling |
173 | 37 |
|
174 | | -## Running |
| 38 | +* `./scripts/profile.sh` |
| 39 | +* Access at <http://localhost:8080> |
175 | 40 |
|
176 | | -* `go run *.go` |
177 | | -* Access at http://localhost:8080 |
| 41 | +### Building |
178 | 42 |
|
| 43 | +* `./scripts/build.sh` |
| 44 | +* `./dist/bin` |
| 45 | +* Access at <http://localhost:8080> |
0 commit comments