mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: manage STT participant as an invisible one
parent
b31b612954
commit
cf15f9f7b6
|
@ -92,6 +92,10 @@ export class OpenVidu {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
recorder = false;
|
recorder = false;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
stt = false;
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
@ -932,6 +936,13 @@ export class OpenVidu {
|
||||||
return this.recorder;
|
return this.recorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
getStt(): boolean {
|
||||||
|
return this.stt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1378,7 +1378,8 @@ export class Session extends EventDispatcher {
|
||||||
sdkVersion: this.openvidu.libraryVersion,
|
sdkVersion: this.openvidu.libraryVersion,
|
||||||
metadata: !!this.options.metadata ? this.options.metadata : '',
|
metadata: !!this.options.metadata ? this.options.metadata : '',
|
||||||
secret: this.openvidu.getSecret(),
|
secret: this.openvidu.getSecret(),
|
||||||
recorder: this.openvidu.getRecorder()
|
recorder: this.openvidu.getRecorder(),
|
||||||
|
stt: this.openvidu.getStt()
|
||||||
};
|
};
|
||||||
return joinParams;
|
return joinParams;
|
||||||
}
|
}
|
||||||
|
@ -1538,6 +1539,7 @@ export class Session extends EventDispatcher {
|
||||||
sessionId: queryParams['sessionId'],
|
sessionId: queryParams['sessionId'],
|
||||||
secret: queryParams['secret'],
|
secret: queryParams['secret'],
|
||||||
recorder: queryParams['recorder'],
|
recorder: queryParams['recorder'],
|
||||||
|
stt: queryParams['stt'],
|
||||||
webrtcStatsInterval: queryParams['webrtcStatsInterval'],
|
webrtcStatsInterval: queryParams['webrtcStatsInterval'],
|
||||||
sendBrowserLogs: queryParams['sendBrowserLogs'],
|
sendBrowserLogs: queryParams['sendBrowserLogs'],
|
||||||
edition: queryParams['edition'],
|
edition: queryParams['edition'],
|
||||||
|
@ -1689,6 +1691,9 @@ export class Session extends EventDispatcher {
|
||||||
if (!!tokenParams.recorder) {
|
if (!!tokenParams.recorder) {
|
||||||
this.openvidu.recorder = true;
|
this.openvidu.recorder = true;
|
||||||
}
|
}
|
||||||
|
if (!!tokenParams.stt) {
|
||||||
|
this.openvidu.stt = true;
|
||||||
|
}
|
||||||
if (!!tokenParams.webrtcStatsInterval) {
|
if (!!tokenParams.webrtcStatsInterval) {
|
||||||
this.openvidu.webrtcStatsInterval = tokenParams.webrtcStatsInterval;
|
this.openvidu.webrtcStatsInterval = tokenParams.webrtcStatsInterval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class OpenViduException extends JsonRpcErrorException {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public static enum Code {
|
public static enum Code {
|
||||||
GENERIC_ERROR_CODE(999), WRONG_PATH_CODE(998),
|
GENERIC_ERROR_CODE(999), WRONG_PATH_CODE(998), WRONG_OPENVIDU_EDITION(997),
|
||||||
|
|
||||||
TRANSPORT_ERROR_CODE(803), TRANSPORT_RESPONSE_ERROR_CODE(802), TRANSPORT_REQUEST_ERROR_CODE(801),
|
TRANSPORT_ERROR_CODE(803), TRANSPORT_RESPONSE_ERROR_CODE(802), TRANSPORT_REQUEST_ERROR_CODE(801),
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public class OpenViduException extends JsonRpcErrorException {
|
||||||
|
|
||||||
FORCED_CODEC_NOT_FOUND_IN_SDPOFFER(800),
|
FORCED_CODEC_NOT_FOUND_IN_SDPOFFER(800),
|
||||||
|
|
||||||
MEDIA_NODE_NOT_FOUND(900), MEDIA_NODE_STATUS_WRONG(901);
|
MEDIA_NODE_NOT_FOUND(900), MEDIA_NODE_STATUS_WRONG(901), MEDIA_NODE_CONNECTION_ERROR_CODE(902);
|
||||||
|
|
||||||
private int value;
|
private int value;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class ProtocolElements {
|
||||||
public static final String JOINROOM_PLATFORM_PARAM = "platform";
|
public static final String JOINROOM_PLATFORM_PARAM = "platform";
|
||||||
public static final String JOINROOM_SDKVERSION_PARAM = "sdkVersion";
|
public static final String JOINROOM_SDKVERSION_PARAM = "sdkVersion";
|
||||||
public static final String JOINROOM_RECORDER_PARAM = "recorder";
|
public static final String JOINROOM_RECORDER_PARAM = "recorder";
|
||||||
|
public static final String JOINROOM_STT_PARAM = "stt";
|
||||||
|
|
||||||
public static final String JOINROOM_PEERID_PARAM = "id";
|
public static final String JOINROOM_PEERID_PARAM = "id";
|
||||||
public static final String JOINROOM_PEERCREATEDAT_PARAM = "createdAt";
|
public static final String JOINROOM_PEERCREATEDAT_PARAM = "createdAt";
|
||||||
|
@ -236,4 +237,5 @@ public class ProtocolElements {
|
||||||
public static final String CUSTOM_NOTIFICATION = "customNotification";
|
public static final String CUSTOM_NOTIFICATION = "customNotification";
|
||||||
|
|
||||||
public static final String RECORDER_PARTICIPANT_PUBLICID = "RECORDER";
|
public static final String RECORDER_PARTICIPANT_PUBLICID = "RECORDER";
|
||||||
|
public static final String STT_PARTICIPANT_PUBLICID = "SPEECH_TO_TEXT";
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.server.kurento.endpoint.EndpointType;
|
import io.openvidu.server.kurento.endpoint.EndpointType;
|
||||||
import io.openvidu.server.utils.GeoLocation;
|
import io.openvidu.server.utils.GeoLocation;
|
||||||
|
|
||||||
|
@ -220,6 +221,18 @@ public class Participant {
|
||||||
&& this.participantPrivateId.startsWith(IdentifierPrefixes.IPCAM_ID);
|
&& this.participantPrivateId.startsWith(IdentifierPrefixes.IPCAM_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRecorderParticipant() {
|
||||||
|
return ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.participantPublicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSttParticipant() {
|
||||||
|
return ProtocolElements.STT_PARTICIPANT_PUBLICID.equals(this.participantPublicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRecorderOrSttParticipant() {
|
||||||
|
return (this.isRecorderParticipant() || this.isSttParticipant());
|
||||||
|
}
|
||||||
|
|
||||||
public String getPublisherStreamId() {
|
public String getPublisherStreamId() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.recording.service.RecordingManager;
|
import io.openvidu.server.recording.service.RecordingManager;
|
||||||
|
@ -140,9 +139,13 @@ public class Session implements SessionInterface {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onlyRecorderParticipant() {
|
public boolean onlyRecorderAndOrSttParticipant() {
|
||||||
return this.participants.size() == 1 && ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
|
if (this.participants.size() == 1) {
|
||||||
.equals(this.participants.values().iterator().next().getParticipantPublicId());
|
return this.participants.values().iterator().next().isRecorderOrSttParticipant();
|
||||||
|
} else if (this.participants.size() == 2) {
|
||||||
|
return this.participants.values().stream().allMatch(p -> p.isRecorderOrSttParticipant());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getActivePublishers() {
|
public int getActivePublishers() {
|
||||||
|
@ -216,8 +219,8 @@ public class Session implements SessionInterface {
|
||||||
Set<Participant> snapshotOfActiveConnections = this.getParticipants().stream().collect(Collectors.toSet());
|
Set<Participant> snapshotOfActiveConnections = this.getParticipants().stream().collect(Collectors.toSet());
|
||||||
JsonArray jsonArray = new JsonArray();
|
JsonArray jsonArray = new JsonArray();
|
||||||
snapshotOfActiveConnections.forEach(participant -> {
|
snapshotOfActiveConnections.forEach(participant -> {
|
||||||
// Filter recorder participant
|
// Filter RECORDER and STT participants
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (!participant.isRecorderOrSttParticipant()) {
|
||||||
jsonArray.add(withWebrtcStats ? participant.withStatsToJson() : participant.toJson());
|
jsonArray.add(withWebrtcStats ? participant.withStatsToJson() : participant.toJson());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -130,16 +130,16 @@ public class SessionEventsHandler {
|
||||||
participantJson.add(ProtocolElements.JOINROOM_PEERSTREAMS_PARAM, streamsArray);
|
participantJson.add(ProtocolElements.JOINROOM_PEERSTREAMS_PARAM, streamsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid emitting 'connectionCreated' event of existing RECORDER participant in
|
// Avoid emitting 'connectionCreated' event of existing RECORDER or STT
|
||||||
// openvidu-browser in newly joined participants
|
// participant in openvidu-browser in newly joined participants
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(existingParticipant.getParticipantPublicId())) {
|
if (!existingParticipant.isRecorderOrSttParticipant()) {
|
||||||
resultArray.add(participantJson);
|
resultArray.add(participantJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If RECORDER participant has joined do NOT send 'participantJoined'
|
// If RECORDER or STT participant has joined do NOT send 'participantJoined'
|
||||||
// notification to existing participants. 'recordingStarted' will be sent to all
|
// notification to existing participants. 'recordingStarted' will be sent to all
|
||||||
// existing participants when recorder first subscribe to a stream
|
// existing participants when recorder first subscribe to a stream
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (!participant.isRecorderOrSttParticipant()) {
|
||||||
JsonObject notifParams = new JsonObject();
|
JsonObject notifParams = new JsonObject();
|
||||||
|
|
||||||
// Metadata associated to new participant
|
// Metadata associated to new participant
|
||||||
|
@ -221,13 +221,14 @@ public class SessionEventsHandler {
|
||||||
|
|
||||||
public void onParticipantLeft(Participant participant, String sessionId, Set<Participant> remainingParticipants,
|
public void onParticipantLeft(Participant participant, String sessionId, Set<Participant> remainingParticipants,
|
||||||
Integer transactionId, OpenViduException error, EndReason reason, boolean scheduleWebsocketClose) {
|
Integer transactionId, OpenViduException error, EndReason reason, boolean scheduleWebsocketClose) {
|
||||||
|
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (participant.isRecorderOrSttParticipant()) {
|
||||||
// RECORDER participant
|
this.rpcNotificationService.immediatelyCloseRpcSession(participant.getParticipantPrivateId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,10 +254,8 @@ public class SessionEventsHandler {
|
||||||
this.rpcNotificationService.scheduleCloseRpcSession(participant.getParticipantPrivateId(), 10000);
|
this.rpcNotificationService.scheduleCloseRpcSession(participant.getParticipantPrivateId(), 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
|
||||||
CDR.recordParticipantLeft(participant, sessionId, reason);
|
CDR.recordParticipantLeft(participant, sessionId, reason);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void onPublishMedia(Participant participant, String streamId, Long createdAt, String sessionId,
|
public void onPublishMedia(Participant participant, String streamId, Long createdAt, String sessionId,
|
||||||
MediaOptions mediaOptions, String sdpAnswer, Set<Participant> participants, Integer transactionId,
|
MediaOptions mediaOptions, String sdpAnswer, Set<Participant> participants, Integer transactionId,
|
||||||
|
@ -357,32 +356,27 @@ public class SessionEventsHandler {
|
||||||
|
|
||||||
public void onSubscribeClientInitiatedNegotiation(Participant participant, Session session, String sdpAnswer,
|
public void onSubscribeClientInitiatedNegotiation(Participant participant, Session session, String sdpAnswer,
|
||||||
Integer transactionId, OpenViduException error) {
|
Integer transactionId, OpenViduException error) {
|
||||||
if (error != null) {
|
this.onSubscribeAux(participant, session, sdpAnswer, transactionId, error);
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JsonObject result = new JsonObject();
|
|
||||||
result.addProperty(ProtocolElements.RECEIVEVIDEO_SDPANSWER_PARAM, sdpAnswer);
|
|
||||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
|
||||||
|
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
|
||||||
recordingsToSendClientEvents.computeIfPresent(session.getSessionId(), (key, value) -> {
|
|
||||||
sendRecordingStartedNotification(session, value);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSubscribeServerInitiatedNegotiation(Participant participant, Session session, Integer transactionId,
|
public void onSubscribeServerInitiatedNegotiation(Participant participant, Session session, Integer transactionId,
|
||||||
OpenViduException error) {
|
OpenViduException error) {
|
||||||
|
this.onSubscribeAux(participant, session, null, transactionId, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSubscribeAux(Participant participant, Session session, String sdpAnswer, Integer transactionId,
|
||||||
|
OpenViduException error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JsonObject result = new JsonObject();
|
JsonObject result = new JsonObject();
|
||||||
|
if (sdpAnswer != null) {
|
||||||
|
result.addProperty(ProtocolElements.RECEIVEVIDEO_SDPANSWER_PARAM, sdpAnswer);
|
||||||
|
}
|
||||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
||||||
|
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (participant.isRecorderParticipant()) {
|
||||||
recordingsToSendClientEvents.computeIfPresent(session.getSessionId(), (key, value) -> {
|
recordingsToSendClientEvents.computeIfPresent(session.getSessionId(), (key, value) -> {
|
||||||
sendRecordingStartedNotification(session, value);
|
sendRecordingStartedNotification(session, value);
|
||||||
return null;
|
return null;
|
||||||
|
@ -464,7 +458,7 @@ public class SessionEventsHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRpcCall) {
|
if (participant != null && isRpcCall) {
|
||||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,13 +513,13 @@ public class SessionEventsHandler {
|
||||||
evictedParticipant.getParticipantPublicId());
|
evictedParticipant.getParticipantPublicId());
|
||||||
params.addProperty(ProtocolElements.PARTICIPANTEVICTED_REASON_PARAM, reason != null ? reason.name() : "");
|
params.addProperty(ProtocolElements.PARTICIPANTEVICTED_REASON_PARAM, reason != null ? reason.name() : "");
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(evictedParticipant.getParticipantPublicId())) {
|
if (evictedParticipant.isRecorderOrSttParticipant()) {
|
||||||
// Do not send a message when evicting RECORDER participant
|
// Do not send a message when evicting RECORDER or STT participant
|
||||||
rpcNotificationService.sendNotification(evictedParticipant.getParticipantPrivateId(),
|
rpcNotificationService.sendNotification(evictedParticipant.getParticipantPrivateId(),
|
||||||
ProtocolElements.PARTICIPANTEVICTED_METHOD, params);
|
ProtocolElements.PARTICIPANTEVICTED_METHOD, params);
|
||||||
}
|
}
|
||||||
for (Participant p : participants) {
|
for (Participant p : participants) {
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(evictedParticipant.getParticipantPublicId())) {
|
if (!evictedParticipant.isRecorderParticipant()) {
|
||||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(),
|
rpcNotificationService.sendNotification(p.getParticipantPrivateId(),
|
||||||
ProtocolElements.PARTICIPANTEVICTED_METHOD, params);
|
ProtocolElements.PARTICIPANTEVICTED_METHOD, params);
|
||||||
}
|
}
|
||||||
|
@ -691,6 +685,24 @@ public class SessionEventsHandler {
|
||||||
public void onMediaNodeRecovered(Kms kms, String environmentId, long timeOfConnection) {
|
public void onMediaNodeRecovered(Kms kms, String environmentId, long timeOfConnection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSubscribeToSpeechToText(Participant participant, Integer transactionId, OpenViduException error) {
|
||||||
|
if (error != null) {
|
||||||
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
|
} else {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUnsubscribeToSpeechToText(Participant participant, Integer transactionId, OpenViduException error) {
|
||||||
|
if (error != null) {
|
||||||
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
|
} else {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onSpeechToTextMessage(String sessionId, String connectionId, long timestamp, String text,
|
public void onSpeechToTextMessage(String sessionId, String connectionId, long timestamp, String text,
|
||||||
Set<Participant> subscribedParticipants) {
|
Set<Participant> subscribedParticipants) {
|
||||||
}
|
}
|
||||||
|
@ -701,7 +713,7 @@ public class SessionEventsHandler {
|
||||||
|
|
||||||
protected Set<Participant> filterParticipantsByRole(Set<OpenViduRole> roles, Set<Participant> participants) {
|
protected Set<Participant> filterParticipantsByRole(Set<OpenViduRole> roles, Set<Participant> participants) {
|
||||||
return participants.stream().filter(part -> {
|
return participants.stream().filter(part -> {
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(part.getParticipantPublicId())) {
|
if (part.isRecorderOrSttParticipant()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return roles.contains(part.getToken().getRole());
|
return roles.contains(part.getToken().getRole());
|
||||||
|
|
|
@ -444,6 +444,17 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Participant newSttParticipant(Session session, String participantPrivateId, Token token, String clientMetadata) {
|
||||||
|
String sessionId = session.getSessionId();
|
||||||
|
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
||||||
|
return newParticipantAux(sessionId, session.getUniqueSessionId(), null, participantPrivateId,
|
||||||
|
ProtocolElements.STT_PARTICIPANT_PUBLICID, token, clientMetadata, null, null,
|
||||||
|
EndpointType.WEBRTC_ENDPOINT);
|
||||||
|
} else {
|
||||||
|
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Participant newIpcamParticipant(Session session, String ipcamId, Token token, GeoLocation location,
|
public Participant newIpcamParticipant(Session session, String ipcamId, Token token, GeoLocation location,
|
||||||
String platform) {
|
String platform) {
|
||||||
String sessionId = session.getSessionId();
|
String sessionId = session.getSessionId();
|
||||||
|
|
|
@ -46,7 +46,6 @@ import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
|
||||||
import io.openvidu.java.client.OpenViduRole;
|
import io.openvidu.java.client.OpenViduRole;
|
||||||
import io.openvidu.server.cdr.WebrtcDebugEvent;
|
import io.openvidu.server.cdr.WebrtcDebugEvent;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
|
@ -284,8 +283,7 @@ public class KurentoParticipant extends Participant {
|
||||||
String sdpAnswer = subscriber.subscribe(sdpString, kSender.getPublisher());
|
String sdpAnswer = subscriber.subscribe(sdpString, kSender.getPublisher());
|
||||||
log.info("PARTICIPANT {}: Is now receiving video from {} in room {}",
|
log.info("PARTICIPANT {}: Is now receiving video from {} in room {}",
|
||||||
this.getParticipantPublicId(), senderName, this.session.getSessionId());
|
this.getParticipantPublicId(), senderName, this.session.getSessionId());
|
||||||
if (!silent && !ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
|
if (!silent && !this.isRecorderOrSttParticipant()) {
|
||||||
.equals(this.getParticipantPublicId())) {
|
|
||||||
endpointConfig.getCdr().recordNewSubscriber(this, sender.getPublisherStreamId(),
|
endpointConfig.getCdr().recordNewSubscriber(this, sender.getPublisherStreamId(),
|
||||||
sender.getParticipantPublicId(), subscriber.createdAt());
|
sender.getParticipantPublicId(), subscriber.createdAt());
|
||||||
}
|
}
|
||||||
|
@ -591,7 +589,7 @@ public class KurentoParticipant extends Participant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
|
if (!this.isRecorderOrSttParticipant()) {
|
||||||
endpointConfig.getCdr().stopSubscriber(this.getParticipantPublicId(), senderName,
|
endpointConfig.getCdr().stopSubscriber(this.getParticipantPublicId(), senderName,
|
||||||
subscriber.getStreamId(), reason);
|
subscriber.getStreamId(), reason);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
|
||||||
import io.openvidu.java.client.OpenViduRole;
|
import io.openvidu.java.client.OpenViduRole;
|
||||||
import io.openvidu.server.core.EndReason;
|
import io.openvidu.server.core.EndReason;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
|
@ -87,7 +86,7 @@ public class KurentoSession extends Session {
|
||||||
|
|
||||||
log.info("SESSION {}: Added participant {}", sessionId, participant);
|
log.info("SESSION {}: Added participant {}", sessionId, participant);
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (!participant.isRecorderOrSttParticipant()) {
|
||||||
kurentoEndpointConfig.getCdr().recordParticipantJoined(participant, sessionId);
|
kurentoEndpointConfig.getCdr().recordParticipantJoined(participant, sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,8 +380,8 @@ public class KurentoSession extends Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfWebrtcConnections() {
|
public int getNumberOfWebrtcConnections() {
|
||||||
return this.getActivePublishers() + this.participants.values().stream()
|
return this.getActivePublishers()
|
||||||
.filter(p -> !ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId()))
|
+ this.participants.values().stream().filter(p -> !p.isRecorderOrSttParticipant())
|
||||||
.mapToInt(p -> ((KurentoParticipant) p).getSubscribers().size()).reduce(0, Integer::sum);
|
.mapToInt(p -> ((KurentoParticipant) p).getSubscribers().size()).reduce(0, Integer::sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,6 +262,12 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
// If session is closed by a call to "DELETE /api/sessions" do NOT stop the
|
// If session is closed by a call to "DELETE /api/sessions" do NOT stop the
|
||||||
// recording. Will be stopped after in method
|
// recording. Will be stopped after in method
|
||||||
// "SessionManager.closeSessionAndEmptyCollections"
|
// "SessionManager.closeSessionAndEmptyCollections"
|
||||||
|
|
||||||
|
boolean recordingParticipantLeft = (remainingParticipants.size() == 1
|
||||||
|
&& remainingParticipants.iterator().next().isRecorderParticipant())
|
||||||
|
|| (remainingParticipants.size() == 2 && remainingParticipants.stream()
|
||||||
|
.allMatch(p -> p.isRecorderOrSttParticipant()));
|
||||||
|
|
||||||
if (remainingParticipants.isEmpty()) {
|
if (remainingParticipants.isEmpty()) {
|
||||||
if (openviduConfig.isRecordingModuleEnabled()
|
if (openviduConfig.isRecordingModuleEnabled()
|
||||||
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
||||||
|
@ -297,23 +303,19 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
sessionId);
|
sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (remainingParticipants.size() == 1 && openviduConfig.isRecordingModuleEnabled()
|
} else if (recordingParticipantLeft && openviduConfig.isRecordingModuleEnabled()
|
||||||
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
||||||
&& this.recordingManager.sessionIsBeingRecorded(sessionId)
|
&& this.recordingManager.sessionIsBeingRecorded(sessionId)) {
|
||||||
&& ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
|
// RECORDER or STT participant is the last one standing. Start countdown
|
||||||
.equals(remainingParticipants.iterator().next().getParticipantPublicId())) {
|
|
||||||
// RECORDER participant is the last one standing. Start countdown
|
|
||||||
log.info(
|
log.info(
|
||||||
"Last participant left. Starting {} seconds countdown for stopping recording of session {}",
|
"Last participant left. Starting {} seconds countdown for stopping recording of session {}",
|
||||||
this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId);
|
this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId);
|
||||||
recordingManager.initAutomaticRecordingStopThread(session);
|
recordingManager.initAutomaticRecordingStopThread(session);
|
||||||
|
|
||||||
} else if (remainingParticipants.size() == 1 && openviduConfig.isRecordingModuleEnabled()
|
} else if (recordingParticipantLeft && openviduConfig.isRecordingModuleEnabled()
|
||||||
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
|
||||||
&& session.getSessionProperties().defaultRecordingProperties().outputMode()
|
&& session.getSessionProperties().defaultRecordingProperties().outputMode()
|
||||||
.equals(Recording.OutputMode.COMPOSED_QUICK_START)
|
.equals(Recording.OutputMode.COMPOSED_QUICK_START)) {
|
||||||
&& ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
|
|
||||||
.equals(remainingParticipants.iterator().next().getParticipantPublicId())) {
|
|
||||||
// If no recordings are active in COMPOSED_QUICK_START output mode, stop
|
// If no recordings are active in COMPOSED_QUICK_START output mode, stop
|
||||||
// container
|
// container
|
||||||
recordingManager.stopComposedQuickStartContainer(session, reason);
|
recordingManager.stopComposedQuickStartContainer(session, reason);
|
||||||
|
@ -1200,10 +1202,14 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribeToSpeechToText(Participant participant, Integer transactionId, JsonArray connectionIds) {
|
public void onSubscribeToSpeechToText(Participant participant, Integer transactionId, JsonArray connectionIds) {
|
||||||
|
sessionEventsHandler.onUnsubscribeToSpeechToText(participant, transactionId, new OpenViduException(
|
||||||
|
Code.WRONG_OPENVIDU_EDITION, "Speech To text requires OpenVidu Pro/Enterprise edition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnsubscribeFromSpeechToText(Participant participant, Integer transactionId, JsonArray connectionIds) {
|
public void onUnsubscribeFromSpeechToText(Participant participant, Integer transactionId, JsonArray connectionIds) {
|
||||||
|
sessionEventsHandler.onUnsubscribeToSpeechToText(participant, transactionId, new OpenViduException(
|
||||||
|
Code.WRONG_OPENVIDU_EDITION, "Speech To text requires OpenVidu Pro/Enterprise edition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String mungeSdpOffer(Session kSession, Participant participant, String sdpOffer, boolean isPublisher) {
|
private String mungeSdpOffer(Session kSession, Participant participant, String sdpOffer, boolean isPublisher) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class Kms {
|
||||||
private String id; // Dynamic ID
|
private String id; // Dynamic ID
|
||||||
private String uri;
|
private String uri;
|
||||||
private String ip;
|
private String ip;
|
||||||
|
private String masterNodePrivateIp;
|
||||||
private KurentoClient client;
|
private KurentoClient client;
|
||||||
private MediaServer mediaServer;
|
private MediaServer mediaServer;
|
||||||
private UpdatableTimerTask clientReconnectTimer;
|
private UpdatableTimerTask clientReconnectTimer;
|
||||||
|
@ -119,6 +120,14 @@ public class Kms {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMasterNodePrivateIp() {
|
||||||
|
return masterNodePrivateIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMasterNodePrivateIp(String masterNodePrivateIp) {
|
||||||
|
this.masterNodePrivateIp = masterNodePrivateIp;
|
||||||
|
}
|
||||||
|
|
||||||
public double getLoad() {
|
public double getLoad() {
|
||||||
return loadManager.calculateLoad(this);
|
return loadManager.calculateLoad(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -673,8 +673,9 @@ public class RecordingManager {
|
||||||
if (session.isClosed()) {
|
if (session.isClosed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (session.getParticipants().size() == 0 || session.onlyRecorderParticipant()) {
|
if (session.getParticipants().size() == 0
|
||||||
// Close session if there are no participants connected (RECORDER does not
|
|| session.onlyRecorderAndOrSttParticipant()) {
|
||||||
|
// Close session if there are no participants connected (RECORDER or STT do not
|
||||||
// count) and publishing
|
// count) and publishing
|
||||||
log.info("Closing session {} after automatic stop of recording {}",
|
log.info("Closing session {} after automatic stop of recording {}",
|
||||||
session.getSessionId(), recordingId);
|
session.getSessionId(), recordingId);
|
||||||
|
@ -726,10 +727,10 @@ public class RecordingManager {
|
||||||
if (session.isClosed()) {
|
if (session.isClosed()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (session.getParticipants().size() == 0 || session.onlyRecorderParticipant()) {
|
if (session.getParticipants().size() == 0 || session.onlyRecorderAndOrSttParticipant()) {
|
||||||
// Close session if there are no participants connected (except for RECORDER).
|
// Close session if there are no participants connected (except for RECORDER or
|
||||||
// This code will only be executed if recording is manually stopped during the
|
// STT). This code will only be executed if recording is manually stopped during
|
||||||
// automatic stop timeout, so the session must be also closed
|
// the automatic stop timeout, so the session must be also closed
|
||||||
log.info(
|
log.info(
|
||||||
"Ongoing recording of session {} was explicetly stopped within timeout for automatic recording stop. Closing session",
|
"Ongoing recording of session {} was explicetly stopped within timeout for automatic recording stop. Closing session",
|
||||||
session.getSessionId());
|
session.getSessionId());
|
||||||
|
|
|
@ -48,6 +48,8 @@ import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.java.client.ConnectionProperties;
|
import io.openvidu.java.client.ConnectionProperties;
|
||||||
|
import io.openvidu.java.client.ConnectionType;
|
||||||
|
import io.openvidu.java.client.OpenViduRole;
|
||||||
import io.openvidu.java.client.utils.FormatChecker;
|
import io.openvidu.java.client.utils.FormatChecker;
|
||||||
import io.openvidu.server.config.OpenviduBuildInfo;
|
import io.openvidu.server.config.OpenviduBuildInfo;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
|
@ -257,28 +259,43 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean recorder = false;
|
boolean recorder = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
recorder = getBooleanParam(request, ProtocolElements.JOINROOM_RECORDER_PARAM);
|
recorder = getBooleanParam(request, ProtocolElements.JOINROOM_RECORDER_PARAM);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// Nothing happens. 'recorder' param to false
|
// Nothing happens. 'recorder' param to false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean stt = false;
|
||||||
|
try {
|
||||||
|
stt = getBooleanParam(request, ProtocolElements.JOINROOM_STT_PARAM);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Nothing happens. 'stt' param to false
|
||||||
|
}
|
||||||
|
|
||||||
boolean generateRecorderParticipant = false;
|
boolean generateRecorderParticipant = false;
|
||||||
|
boolean generateSttParticipant = false;
|
||||||
|
|
||||||
if (openviduConfig.isOpenViduSecret(secret)) {
|
if (openviduConfig.isOpenViduSecret(secret)) {
|
||||||
|
|
||||||
|
if (recorder) {
|
||||||
|
generateRecorderParticipant = true;
|
||||||
|
} else if (stt) {
|
||||||
|
generateSttParticipant = true;
|
||||||
|
}
|
||||||
|
|
||||||
sessionManager.newInsecureParticipant(participantPrivateId);
|
sessionManager.newInsecureParticipant(participantPrivateId);
|
||||||
|
|
||||||
token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
|
token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
|
||||||
+ RandomStringUtils.randomAlphanumeric(15);
|
+ RandomStringUtils.randomAlphanumeric(15);
|
||||||
|
ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC)
|
||||||
|
.role(OpenViduRole.SUBSCRIBER).build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sessionManager.newTokenForInsecureUser(session, token, new ConnectionProperties.Builder().build());
|
sessionManager.newTokenForInsecureUser(session, token, connectionProperties);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE,
|
throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE,
|
||||||
"Unable to create token for session " + sessionId + ": " + e.getMessage());
|
"Unable to create token for session " + sessionId + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
if (recorder) {
|
|
||||||
generateRecorderParticipant = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Token tokenObj = session.consumeToken(token);
|
Token tokenObj = session.consumeToken(token);
|
||||||
|
@ -298,12 +315,16 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
if (generateRecorderParticipant) {
|
if (generateRecorderParticipant) {
|
||||||
participant = sessionManager.newRecorderParticipant(session, participantPrivateId, tokenObj,
|
participant = sessionManager.newRecorderParticipant(session, participantPrivateId, tokenObj,
|
||||||
clientMetadata);
|
clientMetadata);
|
||||||
|
} else if (generateSttParticipant) {
|
||||||
|
participant = sessionManager.newSttParticipant(session, participantPrivateId, tokenObj,
|
||||||
|
clientMetadata);
|
||||||
} else {
|
} else {
|
||||||
participant = sessionManager.newParticipant(session, participantPrivateId, tokenObj,
|
participant = sessionManager.newParticipant(session, participantPrivateId, tokenObj,
|
||||||
clientMetadata, location, platform,
|
clientMetadata, location, platform,
|
||||||
httpSession.getId().substring(0, Math.min(16, httpSession.getId().length())));
|
httpSession.getId().substring(0, Math.min(16, httpSession.getId().length())));
|
||||||
log.info("New Connection {} in Session {} with IP {} and platform {}",
|
log.info("New Connection {} in Session {} with IP {} and platform {}",
|
||||||
participant.getParticipantPublicId(), sessionId, remoteAddress.getHostAddress(),
|
participant.getParticipantPublicId(), sessionId,
|
||||||
|
remoteAddress != null ? remoteAddress.getHostAddress() : "UNKNOWN",
|
||||||
participant.getPlatform());
|
participant.getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,7 +940,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
} catch (VersionMismatchException e) {
|
} catch (VersionMismatchException e) {
|
||||||
if (e.isIncompatible()) {
|
if (e.isIncompatible()) {
|
||||||
|
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (participant.isRecorderParticipant()) {
|
||||||
log.error(
|
log.error(
|
||||||
"The COMPOSED recording layout is using an incompatible version of openvidu-browser SDK ({}) for this OpenVidu deployment ({}). This may cause the system to malfunction",
|
"The COMPOSED recording layout is using an incompatible version of openvidu-browser SDK ({}) for this OpenVidu deployment ({}). This may cause the system to malfunction",
|
||||||
clientVersion, serverVersion);
|
clientVersion, serverVersion);
|
||||||
|
@ -936,7 +957,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
} else {
|
} else {
|
||||||
DefaultArtifactVersion v = new DefaultArtifactVersion(serverVersion);
|
DefaultArtifactVersion v = new DefaultArtifactVersion(serverVersion);
|
||||||
|
|
||||||
if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
if (participant.isRecorderParticipant()) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"The COMPOSED recording layout has an older version of openvidu-browser SDK ({}) for this OpenVidu deployment ({}). These versions are still compatible with each other, "
|
"The COMPOSED recording layout has an older version of openvidu-browser SDK ({}) for this OpenVidu deployment ({}). These versions are still compatible with each other, "
|
||||||
+ "but client SDK must be updated as soon as possible to {}.x. This recording layout using openvidu-browser {} will become incompatible with the next release of openvidu-server",
|
+ "but client SDK must be updated as soon as possible to {}.x. This recording layout using openvidu-browser {} will become incompatible with the next release of openvidu-server",
|
||||||
|
|
Loading…
Reference in New Issue