Skip to content
This repository was archived by the owner on Mar 1, 2024. It is now read-only.

Commit 25024f6

Browse files
Merge pull request #411 from mcottontensor/streamer_ids_fix
Fixes for Streamers changing IDs when connecting & Updates to SFU behaviour relating to multi streamer changes.
2 parents f2cde51 + 7f07f4b commit 25024f6

File tree

13 files changed

+375
-265
lines changed

13 files changed

+375
-265
lines changed

Frontend/Docs/Settings Panel.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ This page will be updated with new features and commands as they become availabl
1919
| **Browser send offer** | The browser will start the WebRTC handshake instead of the Unreal Engine application. This is an advanced setting for users customising the frontend. Primarily for backwards compatibility for 4.x versions of the engine. |
2020
| **Use microphone** | Will start receiving audio input from your microphone and transmit it to the Unreal Engine. |
2121
| **Start video muted** | Muted audio when the stream starts. |
22-
| **Prefer SFU** | Will attempt to use the Selective Forwarding Unit (SFU), if you have one running. |
2322
| **Is quality controller?** | Makes the encoder of the Pixel Streaming Plugin use the current browser connection to determine the bandwidth available, and therefore the quality of the stream encoding. **See notes below** |
2423
| **Force mono audio** | Force the browser to request mono audio in the SDP. |
2524
| **Force TURN** | Will attempt to connect exclusively via the TURN server. Will not work without an active TURN server. |

Frontend/implementations/typescript/package-lock.json

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

Frontend/library/src/Config/Config.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export class Flags {
2323
static FakeMouseWithTouches = 'FakeMouseWithTouches' as const;
2424
static IsQualityController = 'ControlsQuality' as const;
2525
static MatchViewportResolution = 'MatchViewportRes' as const;
26-
static PreferSFU = 'preferSFU' as const;
2726
static StartVideoMuted = 'StartVideoMuted' as const;
2827
static SuppressBrowserKeys = 'SuppressBrowserKeys' as const;
2928
static UseMic = 'UseMic' as const;
@@ -315,17 +314,6 @@ export class Config {
315314
)
316315
);
317316

318-
this.flags.set(
319-
Flags.PreferSFU,
320-
new SettingFlag(
321-
Flags.PreferSFU,
322-
'Prefer SFU',
323-
'Try to connect to the SFU instead of P2P.',
324-
false,
325-
useUrlParams
326-
)
327-
);
328-
329317
this.flags.set(
330318
Flags.IsQualityController,
331319
new SettingFlag(

Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,12 +1384,6 @@ export class WebRtcPlayerController {
13841384
if (messageStreamerList.ids.length == 1) {
13851385
// If there's only a single streamer, subscribe to it regardless of what is in the URL
13861386
autoSelectedStreamerId = messageStreamerList.ids[0];
1387-
} else if (
1388-
this.config.isFlagEnabled(Flags.PreferSFU) &&
1389-
messageStreamerList.ids.includes('SFU')
1390-
) {
1391-
// If the SFU toggle is on and there's an SFU connected, subscribe to it regardless of what is in the URL
1392-
autoSelectedStreamerId = 'SFU';
13931387
} else if (
13941388
urlParams.has(OptionParameters.StreamerId) &&
13951389
messageStreamerList.ids.includes(
@@ -1406,8 +1400,9 @@ export class WebRtcPlayerController {
14061400
);
14071401
} else {
14081402
// no auto selected streamer
1409-
if (this.config.isFlagEnabled(Flags.WaitForStreamer)) {
1410-
this.startAutoJoinTimer()
1403+
if (messageStreamerList.ids.length == 0 && this.config.isFlagEnabled(Flags.WaitForStreamer)) {
1404+
this.closeSignalingServer();
1405+
this.startAutoJoinTimer();
14111406
}
14121407
}
14131408
this.pixelStreaming.dispatchEvent(

Frontend/ui-library/src/Config/ConfigUI.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,6 @@ export class ConfigUI {
174174
psSettingsSection,
175175
this.flagsUi.get(Flags.StartVideoMuted)
176176
);
177-
this.addSettingFlag(
178-
psSettingsSection,
179-
this.flagsUi.get(Flags.PreferSFU)
180-
);
181177
this.addSettingFlag(
182178
psSettingsSection,
183179
this.flagsUi.get(Flags.IsQualityController)

SFU/config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,18 @@ for(let arg of process.argv){
1111
}
1212

1313
const config = {
14+
// The URL of the signalling server to connect to
1415
signallingURL: "ws://localhost:8889",
1516

17+
// The ID for this SFU to use. This will show up as a streamer ID on the signalling server
18+
SFUId: "SFU",
19+
20+
// The ID of the streamer to subscribe to. If you leave this blank it will subscribe to the first streamer it sees.
21+
subscribeStreamerId: "DefaultStreamer",
22+
23+
// Delay between list requests when looking for a specifc streamer.
24+
retrySubscribeDelaySecs: 10,
25+
1626
mediasoup: {
1727
worker: {
1828
rtcMinPort: 40000,

SFU/sfu_server.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ const WebSocket = require('ws');
33
const mediasoup = require('mediasoup_prebuilt');
44
const mediasoupSdp = require('mediasoup-sdp-bridge');
55

6+
if (!config.retrySubscribeDelaySecs) {
7+
config.retrySubscribeDelaySecs = 10;
8+
}
9+
610
let signalServer = null;
711
let mediasoupRouter;
812
let streamer = null;
@@ -24,6 +28,35 @@ function connectSignalling(server) {
2428
});
2529
}
2630

31+
async function onStreamerList(msg) {
32+
let success = false;
33+
34+
// subscribe to either the configured streamer, or if not configured, just grab the first id
35+
if (msg.ids.length > 0) {
36+
if (!!config.subscribeStreamerId && config.subscribeStreamerId.length != 0) {
37+
if (msg.ids.includes(config.subscribeStreamerId)) {
38+
signalServer.send(JSON.stringify({type: 'subscribe', streamerId: config.subscribeStreamerId}));
39+
success = true;
40+
}
41+
} else {
42+
signalServer.send(JSON.stringify({type: 'subscribe', streamerId: msg.ids[0]}));
43+
success = true;
44+
}
45+
}
46+
47+
if (!success) {
48+
// did not subscribe to anything
49+
setTimeout(function() {
50+
signalServer.send(JSON.stringify({type: 'listStreamers'}));
51+
}, config.retrySubscribeDelaySecs * 1000);
52+
}
53+
}
54+
55+
async function onIdentify(msg) {
56+
signalServer.send(JSON.stringify({type: 'endpointId', id: config.SFUId}));
57+
signalServer.send(JSON.stringify({type: 'listStreamers'}));
58+
}
59+
2760
async function onStreamerOffer(sdp) {
2861
console.log("Got offer from streamer");
2962

@@ -57,6 +90,11 @@ function onStreamerDisconnected() {
5790
}
5891
streamer.transport.close();
5992
streamer = null;
93+
signalServer.send(JSON.stringify({type: 'stopStreaming'}));
94+
95+
setTimeout(function() {
96+
signalServer.send(JSON.stringify({type: 'listStreamers'}));
97+
}, config.retrySubscribeDelaySecs * 1000);
6098
}
6199
}
62100

@@ -228,7 +266,7 @@ function onLayerPreference(msg) {
228266
}
229267

230268
async function onSignallingMessage(message) {
231-
//console.log(`Got MSG: ${message}`);
269+
//console.log(`Got MSG: ${message}`);
232270
const msg = JSON.parse(message);
233271

234272
if (msg.type == 'offer') {
@@ -255,6 +293,12 @@ async function onSignallingMessage(message) {
255293
else if (msg.type == 'layerPreference') {
256294
onLayerPreference(msg);
257295
}
296+
else if (msg.type == 'streamerList') {
297+
onStreamerList(msg);
298+
}
299+
else if (msg.type == 'identify') {
300+
onIdentify(msg);
301+
}
258302
}
259303

260304
async function startMediasoup() {
@@ -276,6 +320,14 @@ async function startMediasoup() {
276320
return mediasoupRouter;
277321
}
278322

323+
async function onICEStateChange(identifier, iceState) {
324+
console.log("%s ICE state changed to %s", identifier, iceState);
325+
326+
if (identifier == 'Streamer' && iceState == 'completed') {
327+
signalServer.send(JSON.stringify({type: 'startStreaming'}));
328+
}
329+
}
330+
279331
async function createWebRtcTransport(identifier) {
280332
const {
281333
listenIps,
@@ -291,7 +343,7 @@ async function createWebRtcTransport(identifier) {
291343
initialAvailableOutgoingBitrate: initialAvailableOutgoingBitrate
292344
});
293345

294-
transport.on("icestatechange", (iceState) => { console.log("%s ICE state changed to %s", identifier, iceState); });
346+
transport.on("icestatechange", (iceState) => onICEStateChange(identifier, iceState));
295347
transport.on("iceselectedtuplechange", (iceTuple) => { console.log("%s ICE selected tuple %s", identifier, JSON.stringify(iceTuple)); });
296348
transport.on("sctpstatechange", (sctpState) => { console.log("%s SCTP state changed to %s", identifier, sctpState); });
297349

0 commit comments

Comments
 (0)