From a7332aac70b251217ee9b53881bd56cf7809b92f Mon Sep 17 00:00:00 2001 From: Juan Navarro Date: Tue, 2 Nov 2021 11:40:42 +0100 Subject: [PATCH] openvidu-server: add MKV recording profile as part of MediaServer enum (#658) Uses the MediaServer enum to contain information that is specific about each particular media server. Specifically, * kurento must record with the WEBM profile and ".webm" file extension * mediasoup must record with the MKV profile and ".mkv" file extension Integrating this as part of the global Openvidu config object makes it trivial to replace the static or hardcoded lines with others that simply obtain the data from the current media server mode in use. --- .../io/openvidu/server/core/MediaServer.java | 24 ++++++++++++- .../recording/RecorderEndpointWrapper.java | 11 +++--- .../recording/service/RecordingManager.java | 2 +- .../recording/service/RecordingService.java | 2 +- .../service/SingleStreamRecordingService.java | 34 +++++++++---------- 5 files changed, 48 insertions(+), 25 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/MediaServer.java b/openvidu-server/src/main/java/io/openvidu/server/core/MediaServer.java index 3f398843..0d6dcde5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/MediaServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/MediaServer.java @@ -1,7 +1,29 @@ package io.openvidu.server.core; +import org.kurento.client.MediaProfileSpecType; + public enum MediaServer { + kurento(MediaProfileSpecType.WEBM), mediasoup(MediaProfileSpecType.MKV); - kurento, mediasoup + private final MediaProfileSpecType recordingProfile; + MediaServer(MediaProfileSpecType recordingProfile) { + this.recordingProfile = recordingProfile; + } + + public MediaProfileSpecType getRecordingProfile() { + return recordingProfile; + } + + public MediaProfileSpecType getRecordingProfileAudioOnly() { + return MediaProfileSpecType.valueOf(recordingProfile.name() + "_AUDIO_ONLY"); + } + + public MediaProfileSpecType getRecordingProfileVideoOnly() { + return MediaProfileSpecType.valueOf(recordingProfile.name() + "_VIDEO_ONLY"); + } + + public String getRecordingFileExtension() { + return "." + recordingProfile.name().toLowerCase(); + } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index f6b7dc29..52bcd754 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -30,6 +30,7 @@ public class RecorderEndpointWrapper { private RecorderEndpoint recorder; private KurentoParticipant kParticipant; private String name; + private String fileExtension; private String connectionId; private String recordingId; private String streamId; @@ -44,8 +45,9 @@ public class RecorderEndpointWrapper { private long size; public RecorderEndpointWrapper(RecorderEndpoint recorder, KurentoParticipant kParticipant, String recordingId, - String name) { + String name, String fileExtension) { this.name = name; + this.fileExtension = fileExtension; this.recorder = recorder; this.kParticipant = kParticipant; this.recordingId = recordingId; @@ -58,10 +60,11 @@ public class RecorderEndpointWrapper { this.typeOfVideo = kParticipant.getPublisher().getMediaOptions().getTypeOfVideo(); } - public RecorderEndpointWrapper(JsonObject json) { + public RecorderEndpointWrapper(JsonObject json, String fileExtension) { String nameAux = json.get("name").getAsString(); // If the name includes the extension, remove it - this.name = StringUtils.removeEnd(nameAux, RecordingService.INDIVIDUAL_RECORDING_EXTENSION); + this.name = StringUtils.removeEnd(nameAux, fileExtension); + this.fileExtension = fileExtension; this.connectionId = json.get("connectionId").getAsString(); this.streamId = json.get("streamId").getAsString(); this.clientData = (json.has("clientData") && !json.get("clientData").isJsonNull()) @@ -91,7 +94,7 @@ public class RecorderEndpointWrapper { } public String getNameWithExtension() { - return this.name + RecordingService.INDIVIDUAL_RECORDING_EXTENSION; + return this.name + fileExtension; } public String getConnectionId() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java index ed7d4c2d..5033bd1b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java @@ -764,7 +764,7 @@ public class RecordingManager { final String testFolderPath = openviduRecordingPath + "/TEST_RECORDING_PATH_" + System.currentTimeMillis(); final String testFilePath = testFolderPath + "/TEST_RECORDING_PATH" - + RecordingService.INDIVIDUAL_RECORDING_EXTENSION; + + openviduConfig.getMediaServer().getRecordingFileExtension(); // Check Kurento Media Server write permissions in recording path if (this.kmsManager.getKmss().isEmpty()) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java index 73d9ac0d..fb21c601 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java @@ -54,9 +54,9 @@ public abstract class RecordingService { public final static String RECORDING_ENTITY_FILE = ".recording."; public final static String COMPOSED_RECORDING_EXTENSION = ".mp4"; + public final static String COMPOSED_RECORDING_AUDIO_ONLY_EXTENSION = ".webm"; public final static String COMPOSED_THUMBNAIL_EXTENSION = ".jpg"; public final static String COMPOSED_INFO_FILE_EXTENSION = ".info"; - public final static String INDIVIDUAL_RECORDING_EXTENSION = ".webm"; public final static String INDIVIDUAL_STREAM_METADATA_FILE = ".stream."; public final static String INDIVIDUAL_RECORDING_COMPRESSED_EXTENSION = ".zip"; diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java index ea26a61a..fc6ab286 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java @@ -240,13 +240,14 @@ public class SingleStreamRecordingService extends RecordingService { final List wrapperList = storedRecorders.get(recordingId).get(streamId); final int streamCounter = wrapperList != null ? wrapperList.size() : 0; String fileName = streamCounter == 0 ? streamId : (streamId + "-" + streamCounter); + String fileExtension = openviduConfig.getMediaServer().getRecordingFileExtension(); KurentoParticipant kurentoParticipant = (KurentoParticipant) participant; MediaPipeline pipeline = kurentoParticipant.getPublisher().getPipeline(); RecorderEndpoint recorder = new RecorderEndpoint.Builder(pipeline, "file://" + openviduConfig.getOpenViduRemoteRecordingPath() + recordingId + "/" + fileName - + RecordingService.INDIVIDUAL_RECORDING_EXTENSION).withMediaProfile(profile) + + fileExtension).withMediaProfile(profile) .build(); recorder.addRecordingListener(new EventListener() { @@ -271,7 +272,7 @@ public class SingleStreamRecordingService extends RecordingService { }); RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder, kurentoParticipant, - recordingId, fileName); + recordingId, fileName, fileExtension); activeRecorders.get(recordingId).put(streamId, wrapper); if (wrapperList != null) { wrapperList.add(wrapper); @@ -406,13 +407,13 @@ public class SingleStreamRecordingService extends RecordingService { boolean recordAudio = streamHasAudio && propertiesHasAudio; boolean recordVideo = streamHasVideo && propertiesHasVideo; if (recordAudio && recordVideo) { - profile = MediaProfileSpecType.WEBM; + profile = openviduConfig.getMediaServer().getRecordingProfile(); } else if (recordAudio) { - profile = MediaProfileSpecType.WEBM_AUDIO_ONLY; + profile = openviduConfig.getMediaServer().getRecordingProfileAudioOnly(); } else if (recordVideo) { - profile = MediaProfileSpecType.WEBM_VIDEO_ONLY; + profile = openviduConfig.getMediaServer().getRecordingProfileVideoOnly(); } return profile; @@ -422,19 +423,15 @@ public class SingleStreamRecordingService extends RecordingService { MediaProfileSpecType profile) { // Perform blocking connections, to ensure that elements are // already connected when `RecorderEndpoint.record()` is called. - switch (profile) { - case WEBM: + if (profile.name().contains("AUDIO_ONLY")) { + publisherEndpoint.connect(recorder, MediaType.AUDIO, true); + } + else if (profile.name().contains("VIDEO_ONLY")) { + publisherEndpoint.connect(recorder, MediaType.VIDEO, true); + } + else { publisherEndpoint.connect(recorder, MediaType.AUDIO, true); publisherEndpoint.connect(recorder, MediaType.VIDEO, true); - break; - case WEBM_AUDIO_ONLY: - publisherEndpoint.connect(recorder, MediaType.AUDIO, true); - break; - case WEBM_VIDEO_ONLY: - publisherEndpoint.connect(recorder, MediaType.VIDEO, true); - break; - default: - throw new UnsupportedOperationException("Unsupported profile when single stream recording: " + profile); } } @@ -491,7 +488,8 @@ public class SingleStreamRecordingService extends RecordingService { log.error("Error reading file {}. Error: {}", files[i].getAbsolutePath(), e.getMessage()); } RecorderEndpointWrapper wr = new RecorderEndpointWrapper( - JsonParser.parseReader(reader).getAsJsonObject()); + JsonParser.parseReader(reader).getAsJsonObject(), + openviduConfig.getMediaServer().getRecordingFileExtension()); minStartTime = Math.min(minStartTime, wr.getStartTime()); maxEndTime = Math.max(maxEndTime, wr.getEndTime()); accumulatedSize += wr.getSize(); @@ -542,7 +540,7 @@ public class SingleStreamRecordingService extends RecordingService { String fileExtension = FilenameUtils.getExtension(files[i].getName()); if (files[i].isFile() && (fileExtension.equals("json") - || RecordingService.INDIVIDUAL_RECORDING_EXTENSION.equals("." + fileExtension))) { + || openviduConfig.getMediaServer().getRecordingFileExtension().equals("." + fileExtension))) { // Zip video files and json sync metadata file FileInputStream fis = new FileInputStream(files[i]);