Implementation
Future<void> join() async {
if (_joined) {
//
log("Already Joined");
return;
}
//
String baseUrl;
try {
//
final jsonRes = await http.post(Uri.parse(_initConfigUrl), body: {
'roomId': id,
}, headers: {
'Authorization': _token,
});
final jsonData = json.decode(jsonRes.body);
if (jsonRes.statusCode != 200) {
//
throw jsonData['error'] ?? "Error while getting baseUrl";
}
//
final data = jsonData['data'];
baseUrl = data['baseUrl'];
//
try {
String decryptedIceServer = decrypt(data['iceServers']);
//
List<dynamic> iceServers = json.decode(decryptedIceServer.substring(
0, decryptedIceServer.lastIndexOf(']') + 1)) as List;
//
iceServers.asMap().forEach((key, value) {
//
if (value['url'].toString().contains("stun")) {
//
RTCIceServer iceServer = RTCIceServer(
credentialType: RTCIceCredentialType.password,
username: "",
urls: [value['url']],
credential: "");
_iceServers.add(iceServer);
} else {
//
RTCIceServer iceServer = RTCIceServer(
credentialType: RTCIceCredentialType.password,
username: value['username'],
urls: [value['url']],
credential: value['credential']);
_iceServers.add(iceServer);
}
});
final observability = data['observability'];
// set meetingId, peerId for Logs
VideoSDKLog.meetingId = id;
VideoSDKLog.peerId = localParticipant.id;
VideoSDKLog.logsConfig = observability['logs'];
VideoSDKLog.jwtKey = observability['jwt'];
// open-telemeetry
videoSDKTelemetery = VideoSDKTelemetery(
roomId: id,
peerId: localParticipant.id,
observabilityJwt: observability['jwt'],
traces: observability['traces'],
metaData: observability['metaData'],
);
} catch (error) {
//
VideoSDKLog.createLog(
message: "Error in join() \n ${error.toString()}",
logLevel: "ERROR");
//
log(error.toString());
}
} catch (err) {
//
VideoSDKLog.createLog(
message: "error while getting baseUrl \n ${err.toString()}",
logLevel: "ERROR");
//
log(err.toString());
//
throw "Error while getting baseUrl";
}
// send trace roomConfig
try {
deviceInfo = await VideoSDK.getDeviceInfo();
_joinSpan = videoSDKTelemetery!.trace(
spanName: 'Join() Calling',
span: null,
attributes: [
Attribute.fromString('deviceInfo', deviceInfo.toString()),
Attribute.fromString('displayName', _displayName),
Attribute.fromBoolean('micEnabled', micEnabled),
Attribute.fromBoolean('camEnabled', _camEnabled),
Attribute.fromString('maxResolution', _maxResolution),
Attribute.fromBoolean('multiStream', _multiStream),
Attribute.fromString('mode', _mode.name.toString()),
if (_customCameraVideoTrack != null)
Attribute.fromString('customCameraVideoTrack',
_customCameraVideoTrack!.toMap().toString()),
if (_customMicrophoneAudioTrack != null)
Attribute.fromString('customMicrophoneAudioTrack',
_customMicrophoneAudioTrack!.toMap().toString()),
if (_selectedAudioInput != null)
Attribute.fromString(
'selectedAudioInput', _selectedAudioInput!.label),
if (_selectedVideoInput != null)
Attribute.fromString(
'selectedVideoInput', _selectedVideoInput!.label),
],
);
} catch (error) {}
//
_webSocket = WebSocket(
baseUrl: baseUrl,
peerId: localParticipant.id,
meetingId: id,
token: _token,
mode: _mode.parseToString());
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Meeting is in CONNECTING State',
);
}
} catch (error) {
log("error in webSocket OnConnecting $error");
}
//
_webSocket!.onOpen = () {
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Meeting is in CONNECTED State',
);
}
} catch (error) {
log("error in webSocket onOpen $error");
}
_requestEntry();
};
//
_webSocket!.onFail = () {
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Meeting is in FAILED State',
status: StatusCode.error,
message: 'WebSocket Connection Failed');
}
} catch (error) {
log("error in webSocket onFail $error");
}
};
//
_webSocket!.onDisconnected = () {
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Meeting is in DISCONNECTED State',
);
}
} catch (error) {
log("error in webSocket onDisconnected $error");
}
if (_micProducer != null) {
if (!_micProducer!.closed && _micProducer!.paused) {
_micProducer!.resume();
}
_micProducer!.track.stop();
_micProducer!.close();
_micProducer = null;
}
if (_sendTransport != null) {
_sendTransport!.close();
_sendTransport = null;
}
if (_recvTransport != null) {
_recvTransport!.close();
_recvTransport = null;
}
};
//
_webSocket!.onClose = () {
//
if (_closed) return;
//
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Meeting is in CLOSED State',
);
}
} catch (error) {
log("error in webSocket onClose $error");
}
//
_close();
};
//
_webSocket!.onRequest = (request, accept, reject) async {
switch (request['method']) {
case "close":
{
_close();
break;
}
case 'newConsumer':
{
Span? newConsumerSpan;
Span? span;
try {
if (videoSDKTelemetery != null) {
newConsumerSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: newConsumer',
attributes: [
Attribute.fromString('request', request.toString())
],
);
}
} catch (error) {}
if (!_consume) {
reject(403, 'I do not want to consume');
if (newConsumerSpan != null) {
videoSDKTelemetery!.completeSpan(
span: newConsumerSpan,
message: 'Do not want to consume',
status: StatusCode.ok);
}
break;
}
try {
try {
if (newConsumerSpan != null) {
span = videoSDKTelemetery!.trace(
spanName: 'Creating Consumer',
span: newConsumerSpan,
);
}
} catch (error) {}
_recvTransport!.consume(
id: request['data']['id'],
producerId: request['data']['producerId'],
kind: RTCRtpMediaTypeExtension.fromString(
request['data']['kind']),
rtpParameters:
RtpParameters.fromMap(request['data']['rtpParameters']),
appData: Map<String, dynamic>.from(request['data']['appData']),
peerId: request['data']['peerId'],
accept: accept,
);
if (span != null) {
videoSDKTelemetery!.completeSpan(
span: span,
message: 'Consumer Created',
status: StatusCode.ok);
span = null;
}
if (newConsumerSpan != null) {
videoSDKTelemetery!.completeSpan(
span: newConsumerSpan,
message: 'New Consumer Created Successfully',
status: StatusCode.ok);
}
} catch (error) {
//
VideoSDKLog.createLog(
message: "Error in newConsumer \n ${error.toString()}",
logLevel: "ERROR");
//
log(error.toString());
if (span != null) {
videoSDKTelemetery!.completeSpan(
span: span,
message: 'Consumer Creation Failed',
status: StatusCode.error);
span = null;
}
if (newConsumerSpan != null) {
videoSDKTelemetery!.completeSpan(
span: newConsumerSpan,
message:
'New Consumer Creation Failed \n ${error.toString()}',
status: StatusCode.error);
}
rethrow;
}
break;
}
case 'enableMic':
{
Span? enableMicSpan;
try {
try {
if (videoSDKTelemetery != null) {
enableMicSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: enableMic',
);
}
} catch (error) {}
_eventEmitter.emit('mic-requested', {
// 'participantId': peerId,
"accept": () {
try {
if (enableMicSpan != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Accept Request of EnableMic',
span: enableMicSpan,
);
}
} catch (error) {}
_enableMicImpl(parentSpan: enableMicSpan);
},
"reject": () {
try {
if (enableMicSpan != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Reject Request of EnableMic',
span: enableMicSpan,
);
}
} catch (error) {}
},
});
accept();
if (enableMicSpan != null) {
videoSDKTelemetery!.completeSpan(
span: enableMicSpan,
message: 'EnableMic Request Completed',
status: StatusCode.ok);
}
} catch (error) {
//
VideoSDKLog.createLog(
message: "Error in mic-requested \n ${error.toString()}",
logLevel: "ERROR");
//
if (enableMicSpan != null) {
videoSDKTelemetery!.completeSpan(
span: enableMicSpan,
message: 'EnableMic Request Failed \n ${error.toString()}',
status: StatusCode.error);
}
rethrow;
}
break;
}
case 'disableMic':
{
Span? disableMicSpan;
try {
try {
if (videoSDKTelemetery != null) {
disableMicSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: disableMic',
);
}
} catch (error) {}
_disableMic(parentSpan: disableMicSpan);
accept();
if (disableMicSpan != null) {
videoSDKTelemetery!.completeSpan(
span: disableMicSpan,
message: 'DisableMic Request Completed',
status: StatusCode.ok);
}
} catch (error) {
//
VideoSDKLog.createLog(
message:
"error in request disableMic() \n ${error.toString()}",
logLevel: "ERROR");
if (disableMicSpan != null) {
videoSDKTelemetery!.completeSpan(
span: disableMicSpan,
message: 'DisableMic Request Failed \n ${error.toString()}',
status: StatusCode.error);
}
rethrow;
}
break;
}
case 'enableWebcam':
{
Span? enableWebcam;
try {
if (videoSDKTelemetery != null) {
enableWebcam = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: enableWebcam',
);
}
} catch (error) {}
try {
_eventEmitter.emit('webcam-requested', {
// "participantId": peerId,
"accept": () {
_enableCamImpl(parentSpan: enableWebcam);
try {
if (enableWebcam != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Accept Request of EnableWebCam',
span: enableWebcam,
);
}
} catch (error) {}
},
"reject": () {
if (enableWebcam != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Reject Request of EnableWebCam',
span: enableWebcam,
);
}
},
});
accept();
if (enableWebcam != null) {
videoSDKTelemetery!.completeSpan(
message: 'EnableWebCam Request Completed',
span: enableWebcam,
status: StatusCode.ok,
);
}
} catch (error) {
//
VideoSDKLog.createLog(
message: "Error in webcam-requested \n ${error.toString()}",
logLevel: "ERROR");
if (enableWebcam != null) {
videoSDKTelemetery!.completeSpan(
message: 'EnableWebCam Request Failed \n ${error.toString()}',
span: enableWebcam,
status: StatusCode.error,
);
}
rethrow;
}
break;
}
case 'disableWebcam':
{
Span? disableWebcamSpan;
try {
try {
if (videoSDKTelemetery != null) {
disableWebcamSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: disableWebcam',
);
}
} catch (error) {}
_disableCamImpl(parentSpan: disableWebcamSpan);
accept();
if (disableWebcamSpan != null) {
videoSDKTelemetery!.completeSpan(
span: disableWebcamSpan,
message: 'DisableWebCam Request Completed',
status: StatusCode.ok);
}
} catch (error) {
//
VideoSDKLog.createLog(
message: "Error in request disableCam \n ${error.toString()}",
logLevel: "ERROR");
if (disableWebcamSpan != null) {
videoSDKTelemetery!.completeSpan(
span: disableWebcamSpan,
message:
'DisableWebCam Request Failed \n ${error.toString()}',
status: StatusCode.error);
}
rethrow;
}
break;
}
case "statsData":
{
accept({
"peerId": localParticipant.id,
"statsData": _stats,
});
_stats = {};
break;
}
case "pinStateChanged":
{
String peerId = request["data"]['peerId'];
Map<dynamic, dynamic> state = request["data"]['state'];
String? pinnedBy = request["data"]['pinnedBy'];
Span? pinStateChangedSpan;
try {
if (videoSDKTelemetery != null) {
pinStateChangedSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo REQ: pinStateChanged',
attributes: [
Attribute.fromString('peerId', peerId),
Attribute.fromString('state', state.toString()),
if (pinnedBy != null)
Attribute.fromString('pinnedBy', pinnedBy),
]);
}
} catch (error) {}
// Update current State of participant pin
if (!pinnedParticipants.containsKey(peerId)) {
pinnedParticipants.putIfAbsent(
peerId,
() => ParticipantPinState(
cam: state['cam'],
share: state['share'],
));
}
pinnedParticipants[peerId] = ParticipantPinState(
cam: state['cam'],
share: state['share'],
);
ParticipantPinState pinParticipantState =
pinnedParticipants[peerId]!;
// delete if both were false or current state is false
if (!pinParticipantState.cam && !pinParticipantState.share) {
pinnedParticipants.remove(peerId);
}
_eventEmitter.emit('pin-state-changed-$peerId', {
'participantId': peerId,
'state': state,
'pinnedBy': pinnedBy,
});
_eventEmitter.emit('pin-state-changed', {
'participantId': peerId,
'state': state,
'pinnedBy': pinnedBy,
});
if (pinStateChangedSpan != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Emitted `pin-state-changed` Event',
span: pinStateChangedSpan,
);
}
accept();
if (pinStateChangedSpan != null) {
videoSDKTelemetery!.completeSpan(
span: pinStateChangedSpan,
message: 'PinStateChange Request Completed',
status: StatusCode.ok);
}
break;
}
default:
break;
}
};
//
_webSocket!.onNotification = (notification) async {
switch (notification['method']) {
case 'error':
{
dynamic error = notification['data'];
//
VideoSDKLog.createLog(
message: "Error from server \n ${error.toString()}",
logLevel: "ERROR");
//
if (VideoSDKErrors.containsKey(error['code'])) {
_eventEmitter.emit("error", VideoSDKErrors[error['code']]);
} else {
_eventEmitter.emit("error", error);
}
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Emitted `ERROR` Event',
attributes: [
Attribute.fromString('error', error.toString()),
],
status: StatusCode.error,
message: 'Error from server');
}
} catch (error) {}
break;
}
case 'producerScore':
{
break;
}
case 'consumerClosed':
{
String consumerId = notification['data']['consumerId'];
_removePeerConsumer(consumerId);
try {
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Protoo Noti: consumerClosed for $consumerId',
);
}
} catch (error) {}
break;
}
case 'consumerPaused':
{
// String consumerId = notification['data']['consumerId'];
// peersBloc.add(PeerPausedConsumer(consumerId: consumerId));
break;
}
case 'consumerResumed':
{
// String consumerId = notification['data']['consumerId'];
// peersBloc.add(PeerResumedConsumer(consumerId: consumerId));
break;
}
case "consumerLayersChanged":
{
log("consumerLayersChanged server");
String consumerId = notification['data']['consumerId'];
int spatialLayer = notification['data']['spatialLayer'] ?? -1;
int temporalLayer = notification['data']['temporalLayer'] ?? -1;
_changePeerConsumerQuality(
consumerId,
spatialLayer: spatialLayer,
temporalLayer: temporalLayer,
);
Consumer? consumer = _recvTransport?.getConsumer(consumerId);
if (consumer != null) {
consumer.spatialLayer = spatialLayer;
consumer.temporalLayer = temporalLayer;
}
break;
}
case "entryRequested":
{
var id = notification['data']['id'];
var name = notification['data']['name'];
Span? entryRequestedSpan;
try {
if (videoSDKTelemetery != null && _joinSpan != null) {
entryRequestedSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo Noti: entryRequested',
attributes: [
Attribute.fromString('peerId', id.toString()),
Attribute.fromString('name', name.toString())
],
span: _joinSpan,
);
}
} catch (error) {}
if (id != localParticipant.id) {
_eventEmitter.emit("entry-requested", <String, dynamic>{
'participantId': id,
'name': name,
'allow': () {
_respondEntry(id, "allowed", entryRequestedSpan);
},
'deny': () {
_respondEntry(id, "denied", entryRequestedSpan);
},
});
if (entryRequestedSpan != null) {
videoSDKTelemetery!.completeSpan(
span: entryRequestedSpan,
message: 'EntryRequested Received',
status: StatusCode.ok,
);
}
} else {
if (entryRequestedSpan != null) {
videoSDKTelemetery!.completeSpan(
span: entryRequestedSpan,
message: 'EntryRequested Failed',
status: StatusCode.error,
);
}
}
break;
}
case "entryResponded":
{
var id = notification['data']['id'];
var decision = notification['data']['decision'];
var sessionId = notification['data']['sessionId'];
Span? entryRespondedSpan;
try {
if (videoSDKTelemetery != null && _joinSpan != null) {
entryRespondedSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo Noti: entryResponded',
attributes: [
Attribute.fromString('peerId', id.toString()),
Attribute.fromString('decision', decision.toString()),
Attribute.fromString('sessionId', sessionId.toString())
],
span: _joinSpan,
);
}
} catch (error) {}
_eventEmitter.emit(
"entry-responded",
<String, dynamic>{
"id": id,
"decision": decision,
},
);
if (id == localParticipant.id && decision == "allowed") {
_joinRoom();
if (entryRespondedSpan != null) {
videoSDKTelemetery!.completeSpan(
span: entryRespondedSpan,
message: 'EntryResponded Received',
status: StatusCode.ok,
);
}
} else {
if (entryRespondedSpan != null) {
videoSDKTelemetery!.completeSpan(
span: entryRespondedSpan,
message: 'Join Request Denied',
status: StatusCode.error,
);
}
}
break;
}
case 'newPeer':
{
final Map<String, dynamic> newPeer =
Map<String, dynamic>.from(notification['data']);
Span? newPeerSpan;
if (videoSDKTelemetery != null) {
newPeerSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo Noti: newPeer for ${newPeer.toString()}',
attributes: [
Attribute.fromString('newPeer', newPeer.toString()),
],
);
}
_addPeer(newPeer, newPeerSpan);
if (newPeerSpan != null) {
videoSDKTelemetery!.completeSpan(
message:
'Protoo Noti: newPeer for ${newPeer.toString()} Completed',
status: StatusCode.ok,
span: newPeerSpan,
);
}
break;
}
case 'peerClosed':
{
String peerId = notification['data']['peerId'];
Span? peerClosedSpan;
if (videoSDKTelemetery != null) {
peerClosedSpan = videoSDKTelemetery!.trace(
spanName: 'Protoo Noti: peerClosed for $peerId',
);
}
__removePeer(peerId, peerClosedSpan);
if (peerClosedSpan != null) {
videoSDKTelemetery!.completeSpan(
message: 'Protoo Noti: peerClosed for $peerId Completed',
span: peerClosedSpan,
status: StatusCode.ok,
);
}
break;
}
case 'recordingStarted':
{
_eventEmitter.emit('recording-started');
break;
}
case 'recordingStopped':
{
_eventEmitter.emit('recording-stopped');
break;
}
case 'recordingStateChanged':
{
_recordingState = notification['data']['status'];
_eventEmitter.emit('recording-state-changed', _recordingState);
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName:
'Emitted RECORDING_STATE_CHANGED, status : ${notification['data']['status']}',
attributes: [
Attribute.fromString(
'data', notification['data'].toString())
]);
}
break;
}
case "livestreamStarted":
{
_eventEmitter.emit('livestream-started');
break;
}
case "livestreamStopped":
{
_eventEmitter.emit('livestream-stopped');
break;
}
case 'livestreamStateChanged':
{
_livestreamState = notification['data']['status'];
_eventEmitter.emit('livestream-state-changed', _livestreamState);
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName:
'Emitted LIVESTREAM_STATE_CHANGED, status : ${notification['data']['status']}',
attributes: [
Attribute.fromString(
'data', notification['data'].toString())
]);
}
break;
}
case "hlsStarted":
{
var downstreamUrl = notification['data']['downstreamUrl'];
_eventEmitter.emit('hls-started', downstreamUrl);
break;
}
case "hlsStopped":
{
_eventEmitter.emit('hls-stopped');
break;
}
case 'hlsStateChanged':
{
_hlsState = notification['data']['status'];
var downstreamUrl = notification['data']['downstreamUrl'];
var playbackHlsUrl = notification['data']['playbackHlsUrl'];
var livestreamUrl = notification['data']['livestreamUrl'];
if (_hlsState == "HLS_STARTED") {
_hlsDownstreamUrl = downstreamUrl;
_hlsUrls = {
"downstreamUrl": downstreamUrl,
"playbackHlsUrl": playbackHlsUrl,
"livestreamUrl": livestreamUrl,
};
} else if (_hlsState == "HLS_STOPPED") {
_hlsDownstreamUrl = null;
_hlsUrls = _hlsUrls = {
"downstreamUrl": null,
"playbackHlsUrl": null,
"livestreamUrl": null,
};
}
_eventEmitter.emit('hls-state-changed', <String, dynamic>{
"status": _hlsState,
"downstreamUrl": downstreamUrl,
"playbackHlsUrl": playbackHlsUrl,
"livestreamUrl": livestreamUrl,
});
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName:
'Emitted HLS_STATE_CHANGED, status : ${notification['data']['status']}',
attributes: [
Attribute.fromString('data', notification['data'].toString())
],
);
}
break;
}
case 'hlsPlayableStateChanged':
{
bool isPlayable = notification["data"]["isPlayable"];
if (isPlayable) {
_hlsState = "HLS_PLAYABLE";
var downstreamUrl = notification['data']['downstreamUrl'];
var playbackHlsUrl = notification['data']['playbackHlsUrl'];
var livestreamUrl = notification['data']['livestreamUrl'];
_hlsUrls = {
"downstreamUrl": downstreamUrl,
"playbackHlsUrl": playbackHlsUrl,
"livestreamUrl": livestreamUrl,
};
_eventEmitter.emit('hls-state-changed', <String, dynamic>{
"status": _hlsState,
"downstreamUrl": downstreamUrl,
"playbackHlsUrl": playbackHlsUrl,
"livestreamUrl": livestreamUrl,
});
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Protoo Noti: hlsPlayableStateChanged',
);
}
}
break;
}
case "activeSpeaker":
{
String? peerId = notification['data']['peerId'];
if (peerId != _activeSpeakerId) {
_activeSpeakerId = peerId;
_eventEmitter.emit("speaker-changed", peerId);
}
break;
}
case "pubsubMessage":
{
_eventEmitter.emit("pubsub-message", notification['data']);
break;
}
case "peerModeChanged":
{
_eventEmitter.emit(
"participant-mode-changed-${notification['data']['peerId']}", {
'participantId': notification['data']['peerId'],
'mode': notification['data']['mode'],
});
_eventEmitter.emit("participant-mode-changed", {
'participantId': notification['data']['peerId'],
'mode': notification['data']['mode'],
});
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName: 'Emitted PEER_MODE_CHANGED',
attributes: [
Attribute.fromString('data', notification['data'].toString())
],
);
}
break;
}
case "restartIce":
{
String transportId = notification['data']['transportId'];
IceParameters iceParameters =
IceParameters.fromMap(notification['data']['iceParameters']);
Span? restartIceSpan;
if (videoSDKTelemetery != null) {
restartIceSpan = videoSDKTelemetery!.trace(
spanName:
'Protoo Noti: restartIce for transportId : $transportId',
attributes: [
Attribute.fromString(
'iceParameters', iceParameters.toString())
],
);
}
handleRemoteRestartIce(transportId, iceParameters, restartIceSpan);
break;
}
case 'transcriptionStateChanged':
{
_eventEmitter.emit(
"transcription-state-changed", notification['data']);
if (videoSDKTelemetery != null) {
videoSDKTelemetery!.traceAutoComplete(
spanName:
'Emitted TRANSCRIPTION_STATE_CHANGED, status: ${notification['data']['status']}',
attributes: [
Attribute.fromString('data', notification['data'].toString())
],
);
}
break;
}
case 'transcriptionText':
{
_eventEmitter.emit("transcription-text", notification['data']);
break;
}
default:
break;
}
};
}