@whereby.com/media 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +12 -7
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +12 -7
- package/dist/legacy-esm.js +12 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -157,6 +157,8 @@ const getMediasoupDeviceAsync = (features) => __awaiter(void 0, void 0, void 0,
|
|
|
157
157
|
if (/iphone|ipad/i.test(navigator.userAgent)) {
|
|
158
158
|
handlerName = "Safari12";
|
|
159
159
|
}
|
|
160
|
+
if (!handlerName)
|
|
161
|
+
handlerName = "Chrome111";
|
|
160
162
|
return new mediasoupClient.Device({ handlerName });
|
|
161
163
|
});
|
|
162
164
|
|
|
@@ -297,7 +299,7 @@ const ADDITIONAL_SCREEN_SHARE_SETTINGS = {
|
|
|
297
299
|
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
298
300
|
],
|
|
299
301
|
};
|
|
300
|
-
const getMediaSettings = (kind, isScreenShare, features,
|
|
302
|
+
const getMediaSettings = (kind, isScreenShare, features, areTooManyAlreadyPresenting = false) => {
|
|
301
303
|
var _a;
|
|
302
304
|
const { lowDataModeEnabled, simulcastScreenshareOn, vp9On } = features;
|
|
303
305
|
if (kind === "audio") {
|
|
@@ -307,7 +309,7 @@ const getMediaSettings = (kind, isScreenShare, features, isSomeoneAlreadyPresent
|
|
|
307
309
|
const isVp9Available = isChrome && vp9On;
|
|
308
310
|
if (isScreenShare) {
|
|
309
311
|
return getScreenShareMediaSettings({
|
|
310
|
-
|
|
312
|
+
areTooManyAlreadyPresenting,
|
|
311
313
|
simulcastScreenshareOn,
|
|
312
314
|
});
|
|
313
315
|
}
|
|
@@ -330,8 +332,8 @@ const getCameraMediaSettings = ({ lowBandwidth, isVp9Available, }) => {
|
|
|
330
332
|
}
|
|
331
333
|
return VIDEO_SETTINGS_HD;
|
|
332
334
|
};
|
|
333
|
-
const getScreenShareMediaSettings = ({
|
|
334
|
-
if (
|
|
335
|
+
const getScreenShareMediaSettings = ({ areTooManyAlreadyPresenting, simulcastScreenshareOn, }) => {
|
|
336
|
+
if (areTooManyAlreadyPresenting) {
|
|
335
337
|
return ADDITIONAL_SCREEN_SHARE_SETTINGS;
|
|
336
338
|
}
|
|
337
339
|
if (simulcastScreenshareOn)
|
|
@@ -1258,6 +1260,8 @@ const PROTOCOL_RESPONSES = {
|
|
|
1258
1260
|
CLIENT_UNABLE_TO_JOIN: "client_unable_to_join",
|
|
1259
1261
|
LIVE_TRANSCRIPTION_STARTED: "live_transcription_started",
|
|
1260
1262
|
LIVE_TRANSCRIPTION_STOPPED: "live_transcription_stopped",
|
|
1263
|
+
LIVE_CAPTIONS_STARTED: "live_captions_started",
|
|
1264
|
+
LIVE_CAPTIONS_STOPPED: "live_captions_stopped",
|
|
1261
1265
|
};
|
|
1262
1266
|
const PROTOCOL_ERRORS = {
|
|
1263
1267
|
CANNOT_INVITE_YOURSELF: "cannot_invite_yourself",
|
|
@@ -5122,7 +5126,7 @@ class VegaRtcManager {
|
|
|
5122
5126
|
const codec = this._features.sfuVp9On
|
|
5123
5127
|
? (_b = (_a = this._routerRtpCapabilities) === null || _a === void 0 ? void 0 : _a.codecs) === null || _b === void 0 ? void 0 : _b.find((codec) => codec.mimeType.match(/vp8/i))
|
|
5124
5128
|
: undefined;
|
|
5125
|
-
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this.
|
|
5129
|
+
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this._getAreTooManyAlreadyPresenting())), { appData: {
|
|
5126
5130
|
streamId: OUTBOUND_SCREEN_OUTBOUND_STREAM_ID,
|
|
5127
5131
|
sourceClientId: this._selfId,
|
|
5128
5132
|
screenShare: true,
|
|
@@ -5256,8 +5260,9 @@ class VegaRtcManager {
|
|
|
5256
5260
|
producer.appData.localClosed = true;
|
|
5257
5261
|
producer.close();
|
|
5258
5262
|
}
|
|
5259
|
-
|
|
5260
|
-
return
|
|
5263
|
+
_getAreTooManyAlreadyPresenting() {
|
|
5264
|
+
return ([...this._clientStates.values()].filter((state) => state.hasAcceptedScreenStream && state.screenStream)
|
|
5265
|
+
.length >= 3);
|
|
5261
5266
|
}
|
|
5262
5267
|
isInitializedWith({ selfId, roomName, isSfu }) {
|
|
5263
5268
|
return this._selfId === selfId && this._room.name === roomName && Boolean(isSfu);
|
package/dist/index.d.cts
CHANGED
|
@@ -717,7 +717,7 @@ declare const getMediaSettings: (kind: string, isScreenShare: boolean, features:
|
|
|
717
717
|
lowDataModeEnabled?: boolean;
|
|
718
718
|
simulcastScreenshareOn?: boolean;
|
|
719
719
|
vp9On?: boolean;
|
|
720
|
-
},
|
|
720
|
+
}, areTooManyAlreadyPresenting?: boolean) => {
|
|
721
721
|
encodings: {}[];
|
|
722
722
|
};
|
|
723
723
|
declare const modifyMediaCapabilities: (routerRtpCapabilities: RtpCapabilities, features: {
|
|
@@ -1109,6 +1109,8 @@ interface SignalEvents {
|
|
|
1109
1109
|
video_enable_requested: VideoEnableRequestedEvent;
|
|
1110
1110
|
live_transcription_started: LiveTranscriptionStartedEvent;
|
|
1111
1111
|
live_transcription_stopped: LiveTranscriptionStoppedEvent;
|
|
1112
|
+
live_captions_started: void;
|
|
1113
|
+
live_captions_stopped: void;
|
|
1112
1114
|
}
|
|
1113
1115
|
interface IdentifyDeviceRequest {
|
|
1114
1116
|
deviceCredentials: Credentials;
|
|
@@ -1592,7 +1594,7 @@ declare class VegaRtcManager implements RtcManager {
|
|
|
1592
1594
|
_replaceScreenAudioTrack(): Promise<void>;
|
|
1593
1595
|
_sendScreenAudio(track: MediaStreamTrack): Promise<void>;
|
|
1594
1596
|
_stopProducer(producer: any): void;
|
|
1595
|
-
|
|
1597
|
+
_getAreTooManyAlreadyPresenting(): boolean;
|
|
1596
1598
|
isInitializedWith({ selfId, roomName, isSfu }: {
|
|
1597
1599
|
selfId: string;
|
|
1598
1600
|
roomName: string;
|
|
@@ -1759,6 +1761,8 @@ declare const PROTOCOL_RESPONSES: {
|
|
|
1759
1761
|
CLIENT_UNABLE_TO_JOIN: string;
|
|
1760
1762
|
LIVE_TRANSCRIPTION_STARTED: string;
|
|
1761
1763
|
LIVE_TRANSCRIPTION_STOPPED: string;
|
|
1764
|
+
LIVE_CAPTIONS_STARTED: string;
|
|
1765
|
+
LIVE_CAPTIONS_STOPPED: string;
|
|
1762
1766
|
};
|
|
1763
1767
|
declare const PROTOCOL_ERRORS: {
|
|
1764
1768
|
CANNOT_INVITE_YOURSELF: string;
|
package/dist/index.d.mts
CHANGED
|
@@ -717,7 +717,7 @@ declare const getMediaSettings: (kind: string, isScreenShare: boolean, features:
|
|
|
717
717
|
lowDataModeEnabled?: boolean;
|
|
718
718
|
simulcastScreenshareOn?: boolean;
|
|
719
719
|
vp9On?: boolean;
|
|
720
|
-
},
|
|
720
|
+
}, areTooManyAlreadyPresenting?: boolean) => {
|
|
721
721
|
encodings: {}[];
|
|
722
722
|
};
|
|
723
723
|
declare const modifyMediaCapabilities: (routerRtpCapabilities: RtpCapabilities, features: {
|
|
@@ -1109,6 +1109,8 @@ interface SignalEvents {
|
|
|
1109
1109
|
video_enable_requested: VideoEnableRequestedEvent;
|
|
1110
1110
|
live_transcription_started: LiveTranscriptionStartedEvent;
|
|
1111
1111
|
live_transcription_stopped: LiveTranscriptionStoppedEvent;
|
|
1112
|
+
live_captions_started: void;
|
|
1113
|
+
live_captions_stopped: void;
|
|
1112
1114
|
}
|
|
1113
1115
|
interface IdentifyDeviceRequest {
|
|
1114
1116
|
deviceCredentials: Credentials;
|
|
@@ -1592,7 +1594,7 @@ declare class VegaRtcManager implements RtcManager {
|
|
|
1592
1594
|
_replaceScreenAudioTrack(): Promise<void>;
|
|
1593
1595
|
_sendScreenAudio(track: MediaStreamTrack): Promise<void>;
|
|
1594
1596
|
_stopProducer(producer: any): void;
|
|
1595
|
-
|
|
1597
|
+
_getAreTooManyAlreadyPresenting(): boolean;
|
|
1596
1598
|
isInitializedWith({ selfId, roomName, isSfu }: {
|
|
1597
1599
|
selfId: string;
|
|
1598
1600
|
roomName: string;
|
|
@@ -1759,6 +1761,8 @@ declare const PROTOCOL_RESPONSES: {
|
|
|
1759
1761
|
CLIENT_UNABLE_TO_JOIN: string;
|
|
1760
1762
|
LIVE_TRANSCRIPTION_STARTED: string;
|
|
1761
1763
|
LIVE_TRANSCRIPTION_STOPPED: string;
|
|
1764
|
+
LIVE_CAPTIONS_STARTED: string;
|
|
1765
|
+
LIVE_CAPTIONS_STOPPED: string;
|
|
1762
1766
|
};
|
|
1763
1767
|
declare const PROTOCOL_ERRORS: {
|
|
1764
1768
|
CANNOT_INVITE_YOURSELF: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -717,7 +717,7 @@ declare const getMediaSettings: (kind: string, isScreenShare: boolean, features:
|
|
|
717
717
|
lowDataModeEnabled?: boolean;
|
|
718
718
|
simulcastScreenshareOn?: boolean;
|
|
719
719
|
vp9On?: boolean;
|
|
720
|
-
},
|
|
720
|
+
}, areTooManyAlreadyPresenting?: boolean) => {
|
|
721
721
|
encodings: {}[];
|
|
722
722
|
};
|
|
723
723
|
declare const modifyMediaCapabilities: (routerRtpCapabilities: RtpCapabilities, features: {
|
|
@@ -1109,6 +1109,8 @@ interface SignalEvents {
|
|
|
1109
1109
|
video_enable_requested: VideoEnableRequestedEvent;
|
|
1110
1110
|
live_transcription_started: LiveTranscriptionStartedEvent;
|
|
1111
1111
|
live_transcription_stopped: LiveTranscriptionStoppedEvent;
|
|
1112
|
+
live_captions_started: void;
|
|
1113
|
+
live_captions_stopped: void;
|
|
1112
1114
|
}
|
|
1113
1115
|
interface IdentifyDeviceRequest {
|
|
1114
1116
|
deviceCredentials: Credentials;
|
|
@@ -1592,7 +1594,7 @@ declare class VegaRtcManager implements RtcManager {
|
|
|
1592
1594
|
_replaceScreenAudioTrack(): Promise<void>;
|
|
1593
1595
|
_sendScreenAudio(track: MediaStreamTrack): Promise<void>;
|
|
1594
1596
|
_stopProducer(producer: any): void;
|
|
1595
|
-
|
|
1597
|
+
_getAreTooManyAlreadyPresenting(): boolean;
|
|
1596
1598
|
isInitializedWith({ selfId, roomName, isSfu }: {
|
|
1597
1599
|
selfId: string;
|
|
1598
1600
|
roomName: string;
|
|
@@ -1759,6 +1761,8 @@ declare const PROTOCOL_RESPONSES: {
|
|
|
1759
1761
|
CLIENT_UNABLE_TO_JOIN: string;
|
|
1760
1762
|
LIVE_TRANSCRIPTION_STARTED: string;
|
|
1761
1763
|
LIVE_TRANSCRIPTION_STOPPED: string;
|
|
1764
|
+
LIVE_CAPTIONS_STARTED: string;
|
|
1765
|
+
LIVE_CAPTIONS_STOPPED: string;
|
|
1762
1766
|
};
|
|
1763
1767
|
declare const PROTOCOL_ERRORS: {
|
|
1764
1768
|
CANNOT_INVITE_YOURSELF: string;
|
package/dist/index.mjs
CHANGED
|
@@ -136,6 +136,8 @@ const getMediasoupDeviceAsync = (features) => __awaiter(void 0, void 0, void 0,
|
|
|
136
136
|
if (/iphone|ipad/i.test(navigator.userAgent)) {
|
|
137
137
|
handlerName = "Safari12";
|
|
138
138
|
}
|
|
139
|
+
if (!handlerName)
|
|
140
|
+
handlerName = "Chrome111";
|
|
139
141
|
return new Device({ handlerName });
|
|
140
142
|
});
|
|
141
143
|
|
|
@@ -276,7 +278,7 @@ const ADDITIONAL_SCREEN_SHARE_SETTINGS = {
|
|
|
276
278
|
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
277
279
|
],
|
|
278
280
|
};
|
|
279
|
-
const getMediaSettings = (kind, isScreenShare, features,
|
|
281
|
+
const getMediaSettings = (kind, isScreenShare, features, areTooManyAlreadyPresenting = false) => {
|
|
280
282
|
var _a;
|
|
281
283
|
const { lowDataModeEnabled, simulcastScreenshareOn, vp9On } = features;
|
|
282
284
|
if (kind === "audio") {
|
|
@@ -286,7 +288,7 @@ const getMediaSettings = (kind, isScreenShare, features, isSomeoneAlreadyPresent
|
|
|
286
288
|
const isVp9Available = isChrome && vp9On;
|
|
287
289
|
if (isScreenShare) {
|
|
288
290
|
return getScreenShareMediaSettings({
|
|
289
|
-
|
|
291
|
+
areTooManyAlreadyPresenting,
|
|
290
292
|
simulcastScreenshareOn,
|
|
291
293
|
});
|
|
292
294
|
}
|
|
@@ -309,8 +311,8 @@ const getCameraMediaSettings = ({ lowBandwidth, isVp9Available, }) => {
|
|
|
309
311
|
}
|
|
310
312
|
return VIDEO_SETTINGS_HD;
|
|
311
313
|
};
|
|
312
|
-
const getScreenShareMediaSettings = ({
|
|
313
|
-
if (
|
|
314
|
+
const getScreenShareMediaSettings = ({ areTooManyAlreadyPresenting, simulcastScreenshareOn, }) => {
|
|
315
|
+
if (areTooManyAlreadyPresenting) {
|
|
314
316
|
return ADDITIONAL_SCREEN_SHARE_SETTINGS;
|
|
315
317
|
}
|
|
316
318
|
if (simulcastScreenshareOn)
|
|
@@ -1237,6 +1239,8 @@ const PROTOCOL_RESPONSES = {
|
|
|
1237
1239
|
CLIENT_UNABLE_TO_JOIN: "client_unable_to_join",
|
|
1238
1240
|
LIVE_TRANSCRIPTION_STARTED: "live_transcription_started",
|
|
1239
1241
|
LIVE_TRANSCRIPTION_STOPPED: "live_transcription_stopped",
|
|
1242
|
+
LIVE_CAPTIONS_STARTED: "live_captions_started",
|
|
1243
|
+
LIVE_CAPTIONS_STOPPED: "live_captions_stopped",
|
|
1240
1244
|
};
|
|
1241
1245
|
const PROTOCOL_ERRORS = {
|
|
1242
1246
|
CANNOT_INVITE_YOURSELF: "cannot_invite_yourself",
|
|
@@ -5101,7 +5105,7 @@ class VegaRtcManager {
|
|
|
5101
5105
|
const codec = this._features.sfuVp9On
|
|
5102
5106
|
? (_b = (_a = this._routerRtpCapabilities) === null || _a === void 0 ? void 0 : _a.codecs) === null || _b === void 0 ? void 0 : _b.find((codec) => codec.mimeType.match(/vp8/i))
|
|
5103
5107
|
: undefined;
|
|
5104
|
-
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this.
|
|
5108
|
+
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this._getAreTooManyAlreadyPresenting())), { appData: {
|
|
5105
5109
|
streamId: OUTBOUND_SCREEN_OUTBOUND_STREAM_ID,
|
|
5106
5110
|
sourceClientId: this._selfId,
|
|
5107
5111
|
screenShare: true,
|
|
@@ -5235,8 +5239,9 @@ class VegaRtcManager {
|
|
|
5235
5239
|
producer.appData.localClosed = true;
|
|
5236
5240
|
producer.close();
|
|
5237
5241
|
}
|
|
5238
|
-
|
|
5239
|
-
return
|
|
5242
|
+
_getAreTooManyAlreadyPresenting() {
|
|
5243
|
+
return ([...this._clientStates.values()].filter((state) => state.hasAcceptedScreenStream && state.screenStream)
|
|
5244
|
+
.length >= 3);
|
|
5240
5245
|
}
|
|
5241
5246
|
isInitializedWith({ selfId, roomName, isSfu }) {
|
|
5242
5247
|
return this._selfId === selfId && this._room.name === roomName && Boolean(isSfu);
|
package/dist/legacy-esm.js
CHANGED
|
@@ -136,6 +136,8 @@ const getMediasoupDeviceAsync = (features) => __awaiter(void 0, void 0, void 0,
|
|
|
136
136
|
if (/iphone|ipad/i.test(navigator.userAgent)) {
|
|
137
137
|
handlerName = "Safari12";
|
|
138
138
|
}
|
|
139
|
+
if (!handlerName)
|
|
140
|
+
handlerName = "Chrome111";
|
|
139
141
|
return new Device({ handlerName });
|
|
140
142
|
});
|
|
141
143
|
|
|
@@ -276,7 +278,7 @@ const ADDITIONAL_SCREEN_SHARE_SETTINGS = {
|
|
|
276
278
|
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
277
279
|
],
|
|
278
280
|
};
|
|
279
|
-
const getMediaSettings = (kind, isScreenShare, features,
|
|
281
|
+
const getMediaSettings = (kind, isScreenShare, features, areTooManyAlreadyPresenting = false) => {
|
|
280
282
|
var _a;
|
|
281
283
|
const { lowDataModeEnabled, simulcastScreenshareOn, vp9On } = features;
|
|
282
284
|
if (kind === "audio") {
|
|
@@ -286,7 +288,7 @@ const getMediaSettings = (kind, isScreenShare, features, isSomeoneAlreadyPresent
|
|
|
286
288
|
const isVp9Available = isChrome && vp9On;
|
|
287
289
|
if (isScreenShare) {
|
|
288
290
|
return getScreenShareMediaSettings({
|
|
289
|
-
|
|
291
|
+
areTooManyAlreadyPresenting,
|
|
290
292
|
simulcastScreenshareOn,
|
|
291
293
|
});
|
|
292
294
|
}
|
|
@@ -309,8 +311,8 @@ const getCameraMediaSettings = ({ lowBandwidth, isVp9Available, }) => {
|
|
|
309
311
|
}
|
|
310
312
|
return VIDEO_SETTINGS_HD;
|
|
311
313
|
};
|
|
312
|
-
const getScreenShareMediaSettings = ({
|
|
313
|
-
if (
|
|
314
|
+
const getScreenShareMediaSettings = ({ areTooManyAlreadyPresenting, simulcastScreenshareOn, }) => {
|
|
315
|
+
if (areTooManyAlreadyPresenting) {
|
|
314
316
|
return ADDITIONAL_SCREEN_SHARE_SETTINGS;
|
|
315
317
|
}
|
|
316
318
|
if (simulcastScreenshareOn)
|
|
@@ -1237,6 +1239,8 @@ const PROTOCOL_RESPONSES = {
|
|
|
1237
1239
|
CLIENT_UNABLE_TO_JOIN: "client_unable_to_join",
|
|
1238
1240
|
LIVE_TRANSCRIPTION_STARTED: "live_transcription_started",
|
|
1239
1241
|
LIVE_TRANSCRIPTION_STOPPED: "live_transcription_stopped",
|
|
1242
|
+
LIVE_CAPTIONS_STARTED: "live_captions_started",
|
|
1243
|
+
LIVE_CAPTIONS_STOPPED: "live_captions_stopped",
|
|
1240
1244
|
};
|
|
1241
1245
|
const PROTOCOL_ERRORS = {
|
|
1242
1246
|
CANNOT_INVITE_YOURSELF: "cannot_invite_yourself",
|
|
@@ -5101,7 +5105,7 @@ class VegaRtcManager {
|
|
|
5101
5105
|
const codec = this._features.sfuVp9On
|
|
5102
5106
|
? (_b = (_a = this._routerRtpCapabilities) === null || _a === void 0 ? void 0 : _a.codecs) === null || _b === void 0 ? void 0 : _b.find((codec) => codec.mimeType.match(/vp8/i))
|
|
5103
5107
|
: undefined;
|
|
5104
|
-
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this.
|
|
5108
|
+
const producer = yield this._sendTransport.produce(Object.assign(Object.assign({ track: this._screenVideoTrack, disableTrackOnPause: false, stopTracks: false, codec }, getMediaSettings("video", true, Object.assign(Object.assign({}, this._features), { vp9On: false }), this._getAreTooManyAlreadyPresenting())), { appData: {
|
|
5105
5109
|
streamId: OUTBOUND_SCREEN_OUTBOUND_STREAM_ID,
|
|
5106
5110
|
sourceClientId: this._selfId,
|
|
5107
5111
|
screenShare: true,
|
|
@@ -5235,8 +5239,9 @@ class VegaRtcManager {
|
|
|
5235
5239
|
producer.appData.localClosed = true;
|
|
5236
5240
|
producer.close();
|
|
5237
5241
|
}
|
|
5238
|
-
|
|
5239
|
-
return
|
|
5242
|
+
_getAreTooManyAlreadyPresenting() {
|
|
5243
|
+
return ([...this._clientStates.values()].filter((state) => state.hasAcceptedScreenStream && state.screenStream)
|
|
5244
|
+
.length >= 3);
|
|
5240
5245
|
}
|
|
5241
5246
|
isInitializedWith({ selfId, roomName, isSfu }) {
|
|
5242
5247
|
return this._selfId === selfId && this._room.name === roomName && Boolean(isSfu);
|