mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: added RecordingProperties feature
parent
b8d6ac5f3e
commit
a228b1242e
|
@ -2,6 +2,7 @@ package io.openvidu.server.cdr;
|
||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import io.openvidu.java.client.RecordingLayout;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.recording.Recording;
|
import io.openvidu.server.recording.Recording;
|
||||||
|
@ -33,6 +34,7 @@ public class CDREvent implements Comparable<CDREvent> {
|
||||||
private String name;
|
private String name;
|
||||||
private Boolean hasAudio;
|
private Boolean hasAudio;
|
||||||
private Boolean hasVideo;
|
private Boolean hasVideo;
|
||||||
|
private RecordingLayout layout;
|
||||||
|
|
||||||
public CDREvent(String eventName, CDREvent event) {
|
public CDREvent(String eventName, CDREvent event) {
|
||||||
this(eventName, event.participant, event.sessionId, event.mediaOptions, event.receivingFrom, event.startTime, event.reason);
|
this(eventName, event.participant, event.sessionId, event.mediaOptions, event.receivingFrom, event.startTime, event.reason);
|
||||||
|
@ -69,6 +71,7 @@ public class CDREvent implements Comparable<CDREvent> {
|
||||||
this.size = recording.getSize();
|
this.size = recording.getSize();
|
||||||
this.hasAudio = recording.hasAudio();
|
this.hasAudio = recording.hasAudio();
|
||||||
this.hasVideo = recording.hasVideo();
|
this.hasVideo = recording.hasVideo();
|
||||||
|
this.layout = recording.getLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CDREvent(String eventName, Participant participant, String sessionId) {
|
public CDREvent(String eventName, Participant participant, String sessionId) {
|
||||||
|
@ -146,6 +149,9 @@ public class CDREvent implements Comparable<CDREvent> {
|
||||||
if (this.hasVideo != null) {
|
if (this.hasVideo != null) {
|
||||||
json.put("hasVideo", this.hasVideo);
|
json.put("hasVideo", this.hasVideo);
|
||||||
}
|
}
|
||||||
|
if (this.layout != null) {
|
||||||
|
json.put("layout", this.layout.name());
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject root = new JSONObject();
|
JSONObject root = new JSONObject();
|
||||||
root.put(this.eventName, json);
|
root.put(this.eventName, json);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.java.client.RecordingLayout;
|
import io.openvidu.java.client.RecordingLayout;
|
||||||
import io.openvidu.java.client.RecordingMode;
|
import io.openvidu.java.client.RecordingMode;
|
||||||
|
import io.openvidu.java.client.RecordingProperties;
|
||||||
import io.openvidu.java.client.MediaMode;
|
import io.openvidu.java.client.MediaMode;
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
import io.openvidu.server.core.SessionManager;
|
import io.openvidu.server.core.SessionManager;
|
||||||
|
@ -55,7 +56,8 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
SessionProperties properties = sessionProperties.get(sessionId);
|
SessionProperties properties = sessionProperties.get(sessionId);
|
||||||
if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||||
properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
||||||
.recordingMode(RecordingMode.ALWAYS).recordingLayout(RecordingLayout.BEST_FIT).build();
|
.recordingMode(RecordingMode.ALWAYS).defaultRecordingLayout(RecordingLayout.BEST_FIT)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
createSession(kcSessionInfo, properties);
|
createSession(kcSessionInfo, properties);
|
||||||
}
|
}
|
||||||
|
@ -235,7 +237,8 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
&& session.getActivePublishers() == 0) {
|
&& session.getActivePublishers() == 0) {
|
||||||
// Insecure session recording
|
// Insecure session recording
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
recordingService.startRecording(session, null);
|
recordingService.startRecording(session, new RecordingProperties.Builder().name("")
|
||||||
|
.recordingLayout(session.getSessionProperties().defaultRecordingLayout()).build());
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ import com.github.dockerjava.core.command.PullImageResultCallback;
|
||||||
|
|
||||||
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.java.client.RecordingProperties;
|
||||||
import io.openvidu.server.CommandExecutor;
|
import io.openvidu.server.CommandExecutor;
|
||||||
import io.openvidu.server.OpenViduServer;
|
import io.openvidu.server.OpenViduServer;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
|
@ -81,19 +82,20 @@ public class ComposedRecordingService {
|
||||||
this.dockerClient = DockerClientBuilder.getInstance(config).build();
|
this.dockerClient = DockerClientBuilder.getInstance(config).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recording startRecording(Session session, String name) {
|
public Recording startRecording(Session session, RecordingProperties properties) {
|
||||||
List<String> envs = new ArrayList<>();
|
List<String> envs = new ArrayList<>();
|
||||||
String shortSessionId = session.getSessionId().substring(session.getSessionId().lastIndexOf('/') + 1,
|
String shortSessionId = session.getSessionId().substring(session.getSessionId().lastIndexOf('/') + 1,
|
||||||
session.getSessionId().length());
|
session.getSessionId().length());
|
||||||
String recordingId = this.getFreeRecordingId(session.getSessionId(), shortSessionId);
|
String recordingId = this.getFreeRecordingId(session.getSessionId(), shortSessionId);
|
||||||
String secret = openviduConfig.getOpenViduSecret();
|
String secret = openviduConfig.getOpenViduSecret();
|
||||||
|
|
||||||
if (name == null || name.isEmpty()) {
|
if (properties.name() == null || properties.name().isEmpty()) {
|
||||||
// No name provided for the recording file
|
// No name provided for the recording file
|
||||||
name = recordingId;
|
properties = new RecordingProperties.Builder().name(recordingId)
|
||||||
|
.recordingLayout(properties.recordingLayout()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Recording recording = new Recording(session.getSessionId(), recordingId, name);
|
Recording recording = new Recording(session.getSessionId(), recordingId, properties);
|
||||||
|
|
||||||
this.sessionsRecordings.put(session.getSessionId(), recording);
|
this.sessionsRecordings.put(session.getSessionId(), recording);
|
||||||
this.sessionHandler.setRecordingStarted(session.getSessionId(), recording);
|
this.sessionHandler.setRecordingStarted(session.getSessionId(), recording);
|
||||||
|
@ -110,14 +112,14 @@ public class ComposedRecordingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
String location = OpenViduServer.publicUrl.replaceFirst("wss://", "");
|
String location = OpenViduServer.publicUrl.replaceFirst("wss://", "");
|
||||||
String layoutUrl = session.getSessionProperties().recordingLayout().name().toLowerCase().replaceAll("_", "-");
|
String layoutUrl = properties.recordingLayout().name().toLowerCase().replaceAll("_", "-");
|
||||||
|
|
||||||
envs.add("URL=https://OPENVIDUAPP:" + secret + "@" + location + "/#/layout-" + layoutUrl + "/" + shortSessionId
|
envs.add("URL=https://OPENVIDUAPP:" + secret + "@" + location + "/#/layout-" + layoutUrl + "/" + shortSessionId
|
||||||
+ "/" + secret);
|
+ "/" + secret);
|
||||||
envs.add("RESOLUTION=1920x1080");
|
envs.add("RESOLUTION=1920x1080");
|
||||||
envs.add("FRAMERATE=30");
|
envs.add("FRAMERATE=30");
|
||||||
envs.add("VIDEO_ID=" + recordingId);
|
envs.add("VIDEO_ID=" + recordingId);
|
||||||
envs.add("VIDEO_NAME=" + name);
|
envs.add("VIDEO_NAME=" + properties.name());
|
||||||
envs.add("VIDEO_FORMAT=mp4");
|
envs.add("VIDEO_FORMAT=mp4");
|
||||||
envs.add("USER_ID=" + uid);
|
envs.add("USER_ID=" + uid);
|
||||||
envs.add("RECORDING_JSON=" + recording.toJson().toJSONString());
|
envs.add("RECORDING_JSON=" + recording.toJson().toJSONString());
|
||||||
|
@ -128,7 +130,7 @@ public class ComposedRecordingService {
|
||||||
|
|
||||||
String containerId = this.runRecordingContainer(envs, "recording_" + recordingId);
|
String containerId = this.runRecordingContainer(envs, "recording_" + recordingId);
|
||||||
|
|
||||||
this.waitForVideoFileNotEmpty(name);
|
this.waitForVideoFileNotEmpty(properties.name());
|
||||||
|
|
||||||
this.sessionsContainers.put(session.getSessionId(), containerId);
|
this.sessionsContainers.put(session.getSessionId(), containerId);
|
||||||
|
|
||||||
|
@ -378,7 +380,7 @@ public class ComposedRecordingService {
|
||||||
// Cannot delete an active recording
|
// Cannot delete an active recording
|
||||||
return HttpStatus.CONFLICT;
|
return HttpStatus.CONFLICT;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = getRecordingFromHost(recordingId).getName();
|
String name = getRecordingFromHost(recordingId).getName();
|
||||||
|
|
||||||
File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
|
File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
|
||||||
|
|
|
@ -2,6 +2,9 @@ package io.openvidu.server.recording;
|
||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import io.openvidu.java.client.RecordingLayout;
|
||||||
|
import io.openvidu.java.client.RecordingProperties;
|
||||||
|
|
||||||
public class Recording {
|
public class Recording {
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
|
@ -9,14 +12,13 @@ public class Recording {
|
||||||
started, // The recording has started and is going on
|
started, // The recording has started and is going on
|
||||||
stopped, // The recording has finished OK
|
stopped, // The recording has finished OK
|
||||||
available, // The recording is available for downloading. This status is reached for all
|
available, // The recording is available for downloading. This status is reached for all
|
||||||
// stopped recordings if property 'openvidu.recording.free-access' is true
|
// stopped recordings if property 'openvidu.recording.free-access' is true
|
||||||
failed; // The recording has failed
|
failed; // The recording has failed
|
||||||
}
|
}
|
||||||
|
|
||||||
private Status status;
|
private Recording.Status status;
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
private long createdAt; // milliseconds (UNIX Epoch time)
|
private long createdAt; // milliseconds (UNIX Epoch time)
|
||||||
private long size = 0; // bytes
|
private long size = 0; // bytes
|
||||||
|
@ -24,18 +26,18 @@ public class Recording {
|
||||||
private String url;
|
private String url;
|
||||||
private boolean hasAudio = true;
|
private boolean hasAudio = true;
|
||||||
private boolean hasVideo = true;
|
private boolean hasVideo = true;
|
||||||
|
private RecordingProperties recordingProperties;
|
||||||
|
|
||||||
public Recording(String sessionId, String id, String name) {
|
public Recording(String sessionId, String id, RecordingProperties recordingProperties) {
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.createdAt = System.currentTimeMillis();
|
this.createdAt = System.currentTimeMillis();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
|
||||||
this.status = Status.started;
|
this.status = Status.started;
|
||||||
|
this.recordingProperties = recordingProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recording(JSONObject json) {
|
public Recording(JSONObject json) {
|
||||||
this.id = (String) json.get("id");
|
this.id = (String) json.get("id");
|
||||||
this.name = (String) json.get("name");
|
|
||||||
this.sessionId = (String) json.get("sessionId");
|
this.sessionId = (String) json.get("sessionId");
|
||||||
this.createdAt = (long) json.get("createdAt");
|
this.createdAt = (long) json.get("createdAt");
|
||||||
this.size = (long) json.get("size");
|
this.size = (long) json.get("size");
|
||||||
|
@ -44,6 +46,8 @@ public class Recording {
|
||||||
this.hasAudio = (boolean) json.get("hasAudio");
|
this.hasAudio = (boolean) json.get("hasAudio");
|
||||||
this.hasVideo = (boolean) json.get("hasVideo");
|
this.hasVideo = (boolean) json.get("hasVideo");
|
||||||
this.status = Status.valueOf((String) json.get("status"));
|
this.status = Status.valueOf((String) json.get("status"));
|
||||||
|
this.recordingProperties = new RecordingProperties.Builder().name((String) json.get("name"))
|
||||||
|
.recordingLayout(RecordingLayout.valueOf((String) json.get("layout"))).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Status getStatus() {
|
public Status getStatus() {
|
||||||
|
@ -62,13 +66,21 @@ public class Recording {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return this.recordingProperties.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String setName() {
|
||||||
|
return this.recordingProperties.name();
|
||||||
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public RecordingLayout getLayout() {
|
||||||
this.name = name;
|
return this.recordingProperties.recordingLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RecordingLayout setLayout() {
|
||||||
|
return this.recordingProperties.recordingLayout();
|
||||||
|
}
|
||||||
|
|
||||||
public String getSessionId() {
|
public String getSessionId() {
|
||||||
return sessionId;
|
return sessionId;
|
||||||
|
@ -130,7 +142,8 @@ public class Recording {
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
json.put("id", this.id);
|
json.put("id", this.id);
|
||||||
json.put("name", this.name);
|
json.put("name", this.recordingProperties.name());
|
||||||
|
json.put("layout", this.recordingProperties.recordingLayout().name());
|
||||||
json.put("sessionId", this.sessionId);
|
json.put("sessionId", this.sessionId);
|
||||||
json.put("createdAt", this.createdAt);
|
json.put("createdAt", this.createdAt);
|
||||||
json.put("size", this.size);
|
json.put("size", this.size);
|
||||||
|
|
|
@ -37,6 +37,7 @@ import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.java.client.RecordingLayout;
|
import io.openvidu.java.client.RecordingLayout;
|
||||||
import io.openvidu.java.client.RecordingMode;
|
import io.openvidu.java.client.RecordingMode;
|
||||||
|
import io.openvidu.java.client.RecordingProperties;
|
||||||
import io.openvidu.java.client.MediaMode;
|
import io.openvidu.java.client.MediaMode;
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
import io.openvidu.server.core.ParticipantRole;
|
import io.openvidu.server.core.ParticipantRole;
|
||||||
|
@ -72,7 +73,7 @@ public class SessionRestController {
|
||||||
SessionProperties.Builder builder = new SessionProperties.Builder();
|
SessionProperties.Builder builder = new SessionProperties.Builder();
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
String recordingModeString = (String) params.get("recordingMode");
|
String recordingModeString = (String) params.get("recordingMode");
|
||||||
String recordingLayoutString = (String) params.get("recordingLayout");
|
String defaultRecordingLayoutString = (String) params.get("defaultRecordingLayout");
|
||||||
String mediaModeString = (String) params.get("mediaMode");
|
String mediaModeString = (String) params.get("mediaMode");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -80,18 +81,18 @@ public class SessionRestController {
|
||||||
RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString);
|
RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString);
|
||||||
builder = builder.recordingMode(recordingMode);
|
builder = builder.recordingMode(recordingMode);
|
||||||
}
|
}
|
||||||
if (recordingLayoutString != null) {
|
if (defaultRecordingLayoutString != null) {
|
||||||
RecordingLayout recordingLayout = RecordingLayout.valueOf(recordingLayoutString);
|
RecordingLayout defaultRecordingLayout = RecordingLayout.valueOf(defaultRecordingLayoutString);
|
||||||
builder = builder.recordingLayout(recordingLayout);
|
builder = builder.defaultRecordingLayout(defaultRecordingLayout);
|
||||||
}
|
}
|
||||||
if (mediaModeString != null) {
|
if (mediaModeString != null) {
|
||||||
MediaMode mediaMode = MediaMode.valueOf(mediaModeString);
|
MediaMode mediaMode = MediaMode.valueOf(mediaModeString);
|
||||||
builder = builder.mediaMode(mediaMode);
|
builder = builder.mediaMode(mediaMode);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return this.generateErrorResponse("RecordingMode " + params.get("recordingMode") + " | " + "RecordingLayout "
|
return this.generateErrorResponse("RecordingMode " + params.get("recordingMode") + " | "
|
||||||
+ params.get("recordingLayout") + " | " + "MediaMode " + params.get("mediaMode")
|
+ "Default RecordingLayout " + params.get("defaultRecordingLayout") + " | " + "MediaMode "
|
||||||
+ " are not defined", "/api/tokens", HttpStatus.BAD_REQUEST);
|
+ params.get("mediaMode") + " are not defined", "/api/tokens", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,9 +110,20 @@ public class SessionRestController {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String sessionId = (String) params.get("session");
|
String sessionId = (String) params.get("session");
|
||||||
ParticipantRole role = ParticipantRole.valueOf((String) params.get("role"));
|
String roleString = (String) params.get("role");
|
||||||
String metadata = (String) params.get("data");
|
String metadata = (String) params.get("data");
|
||||||
|
|
||||||
|
ParticipantRole role;
|
||||||
|
if (roleString != null) {
|
||||||
|
role = ParticipantRole.valueOf(roleString);
|
||||||
|
} else {
|
||||||
|
role = ParticipantRole.PUBLISHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadata == null) {
|
||||||
|
metadata = "";
|
||||||
|
}
|
||||||
|
|
||||||
String token = sessionManager.newToken(sessionId, role, metadata);
|
String token = sessionManager.newToken(sessionId, role, metadata);
|
||||||
JSONObject responseJson = new JSONObject();
|
JSONObject responseJson = new JSONObject();
|
||||||
responseJson.put("id", token);
|
responseJson.put("id", token);
|
||||||
|
@ -136,6 +148,7 @@ public class SessionRestController {
|
||||||
|
|
||||||
String sessionId = (String) params.get("session");
|
String sessionId = (String) params.get("session");
|
||||||
String name = (String) params.get("name");
|
String name = (String) params.get("name");
|
||||||
|
String recordingLayoutString = (String) params.get("recordingLayout");
|
||||||
|
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
// "session" parameter not found
|
// "session" parameter not found
|
||||||
|
@ -158,7 +171,18 @@ public class SessionRestController {
|
||||||
return new ResponseEntity<JSONObject>(HttpStatus.CONFLICT);
|
return new ResponseEntity<JSONObject>(HttpStatus.CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Recording startedRecording = this.recordingService.startRecording(session, name);
|
RecordingLayout recordingLayout;
|
||||||
|
if (recordingLayoutString == null || recordingLayoutString.isEmpty()) {
|
||||||
|
// "recordingLayout" parameter not defined. Use global layout from
|
||||||
|
// SessionProperties
|
||||||
|
// (it is always configured as it has RecordingLayout.BEST_FIT as default value)
|
||||||
|
recordingLayout = session.getSessionProperties().defaultRecordingLayout();
|
||||||
|
} else {
|
||||||
|
recordingLayout = RecordingLayout.valueOf(recordingLayoutString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Recording startedRecording = this.recordingService.startRecording(session,
|
||||||
|
new RecordingProperties.Builder().name(name).recordingLayout(recordingLayout).build());
|
||||||
return new ResponseEntity<>(startedRecording.toJson(), HttpStatus.OK);
|
return new ResponseEntity<>(startedRecording.toJson(), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,14 +208,14 @@ public class SessionRestController {
|
||||||
// Session is not being recorded
|
// Session is not being recorded
|
||||||
return new ResponseEntity<JSONObject>(HttpStatus.CONFLICT);
|
return new ResponseEntity<JSONObject>(HttpStatus.CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Session session = sessionManager.getSession(recording.getSessionId());
|
Session session = sessionManager.getSession(recording.getSessionId());
|
||||||
|
|
||||||
Recording stoppedRecording = this.recordingService
|
Recording stoppedRecording = this.recordingService.stopRecording(session);
|
||||||
.stopRecording(session);
|
|
||||||
|
sessionManager.evictParticipant(session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID)
|
||||||
sessionManager.evictParticipant(session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID).getParticipantPrivateId(), "EVICT_RECORDER");
|
.getParticipantPrivateId(), "EVICT_RECORDER");
|
||||||
|
|
||||||
return new ResponseEntity<>(stoppedRecording.toJson(), HttpStatus.OK);
|
return new ResponseEntity<>(stoppedRecording.toJson(), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue