diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java
index 876b72f6..e12d868a 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java
@@ -195,8 +195,11 @@ public class OpenVidu {
json.put("session", sessionId);
json.put("name", properties.name());
json.put("outputMode", properties.outputMode());
+ json.put("hasAudio", properties.hasAudio());
+ json.put("hasVideo", properties.hasVideo());
if (Recording.OutputMode.COMPOSED.equals(properties.outputMode())) {
+ json.put("resolution", properties.resolution());
json.put("recordingLayout",
(properties.recordingLayout() != null) ? properties.recordingLayout().name() : "");
if (RecordingLayout.CUSTOM.equals(properties.recordingLayout())) {
diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java
index ed803b6d..6f7973b5 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java
@@ -99,6 +99,7 @@ public class Recording {
.outputMode(outputMode).hasAudio((boolean) json.get("hasAudio"))
.hasVideo((boolean) json.get("hasVideo"));
if (OutputMode.COMPOSED.equals(outputMode)) {
+ builder.resolution((String) json.get("resolution"));
builder.recordingLayout(RecordingLayout.valueOf((String) json.get("recordingLayout")));
String customLayout = (String) json.get("customLayout");
if (customLayout != null) {
@@ -152,8 +153,8 @@ public class Recording {
* {@link io.openvidu.java.client.RecordingProperties.Builder#customLayout(String)}
* has been called
*/
- public RecordingLayout getCustomLayout() {
- return this.recordingProperties.recordingLayout();
+ public String getCustomLayout() {
+ return this.recordingProperties.customLayout();
}
/**
@@ -195,6 +196,14 @@ public class Recording {
return url;
}
+ /**
+ * Resolution of the video file. Only defined if OutputMode of the Recording is
+ * set to {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED}
+ */
+ public String getResolution() {
+ return this.recordingProperties.resolution();
+ }
+
/**
* true
if the recording has an audio track, false
* otherwise (currently fixed to true)
diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java
index 1224775d..d9ea42a9 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java
@@ -27,6 +27,7 @@ public class RecordingProperties {
private Recording.OutputMode outputMode;
private RecordingLayout recordingLayout;
private String customLayout;
+ private String resolution;
private boolean hasAudio;
private boolean hasVideo;
@@ -37,8 +38,9 @@ public class RecordingProperties {
private String name = "";
private Recording.OutputMode outputMode = Recording.OutputMode.COMPOSED;
- private RecordingLayout recordingLayout;
+ private RecordingLayout recordingLayout = RecordingLayout.BEST_FIT;
private String customLayout = "";
+ private String resolution = "1920x1080";
private boolean hasAudio = true;
private boolean hasVideo = true;
@@ -47,7 +49,7 @@ public class RecordingProperties {
*/
public RecordingProperties build() {
return new RecordingProperties(this.name, this.outputMode, this.recordingLayout, this.customLayout,
- this.hasAudio, this.hasVideo);
+ this.resolution, this.hasAudio, this.hasVideo);
}
/**
@@ -100,6 +102,21 @@ public class RecordingProperties {
return this;
}
+ /**
+ * Call this method to specify the recording resolution. Will only have effect
+ * if
+ * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)}
+ * has been called with value
+ * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED}. For
+ * {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all
+ * individual video files will have the native resolution of the published
+ * stream
+ */
+ public RecordingProperties.Builder resolution(String resolution) {
+ this.resolution = resolution;
+ return this;
+ }
+
/**
* Call this method to specify whether or not to record the audio track
*/
@@ -119,11 +136,12 @@ public class RecordingProperties {
}
protected RecordingProperties(String name, Recording.OutputMode outputMode, RecordingLayout layout,
- String customLayout, boolean hasAudio, boolean hasVideo) {
+ String customLayout, String resolution, boolean hasAudio, boolean hasVideo) {
this.name = name;
this.outputMode = outputMode;
this.recordingLayout = layout;
this.customLayout = customLayout;
+ this.resolution = resolution;
this.hasAudio = hasAudio;
this.hasVideo = hasVideo;
}
@@ -164,6 +182,13 @@ public class RecordingProperties {
return this.customLayout;
}
+ /**
+ * Defines the resolution of the recorded video
+ */
+ public String resolution() {
+ return this.resolution;
+ }
+
/**
* Defines if the recording has an audio track or not
*/
diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts
index 24bc56ac..1d002023 100644
--- a/openvidu-node-client/src/OpenVidu.ts
+++ b/openvidu-node-client/src/OpenVidu.ts
@@ -22,6 +22,7 @@ import { Recording } from './Recording';
import { RecordingProperties } from './RecordingProperties';
import { Session } from './Session';
import { SessionProperties } from './SessionProperties';
+import { RecordingLayout } from './RecordingLayout';
/**
* @hidden
@@ -142,26 +143,29 @@ export class OpenVidu {
data = JSON.stringify({
session: sessionId,
name: !!properties.name ? properties.name : '',
- outputMode: !!properties.outputMode ? properties.outputMode : '',
- recordingLayout: !!properties.recordingLayout ? properties.recordingLayout : '',
- customLayout: !!properties.customLayout ? properties.customLayout : ''
+ outputMode: !!properties.outputMode ? properties.outputMode : Recording.OutputMode.COMPOSED,
+ hasAudio: !!(properties.hasAudio),
+ hasVideo: !!(properties.hasVideo)
});
+ if (data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]) {
+ data.resolution = !!properties.resolution ? properties.resolution : '1920x1080';
+ data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : RecordingLayout.BEST_FIT;
+ if (data.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
+ data.customLayout = !!properties.customLayout ? properties.customLayout : '';
+ }
+ }
} else {
data = JSON.stringify({
session: sessionId,
name: param2,
- outputMode: '',
- recordingLayout: '',
- customLayout: ''
+ outputMode: Recording.OutputMode.COMPOSED
});
}
} else {
data = JSON.stringify({
session: sessionId,
name: '',
- outputMode: '',
- recordingLayout: '',
- customLayout: ''
+ outputMode: Recording.OutputMode.COMPOSED
});
}
diff --git a/openvidu-node-client/src/Recording.ts b/openvidu-node-client/src/Recording.ts
index 3c2d0659..2db328b2 100644
--- a/openvidu-node-client/src/Recording.ts
+++ b/openvidu-node-client/src/Recording.ts
@@ -83,6 +83,7 @@ export class Recording {
hasVideo: !!json['hasVideo']
};
if (this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED]) {
+ this.properties.resolution = !!(json['resolution']) ? json['resolution'] : '1920x1080';
this.properties.recordingLayout = !!(json['recordingLayout']) ? json['recordingLayout'] : RecordingLayout.BEST_FIT;
if (this.properties.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) {
this.properties.customLayout = json['customLayout'];
diff --git a/openvidu-node-client/src/RecordingProperties.ts b/openvidu-node-client/src/RecordingProperties.ts
index 8379a2a3..ee1b1181 100644
--- a/openvidu-node-client/src/RecordingProperties.ts
+++ b/openvidu-node-client/src/RecordingProperties.ts
@@ -48,6 +48,14 @@ export interface RecordingProperties {
*/
customLayout?: string;
+ /**
+ * Recording video file resolution.
+ * Will only have effect if [[RecordingProperties.outputMode]]
+ * is set to [[Recording.OutputMode.COMPOSED]]. For [[Recording.OutputMode.INDIVIDUAL]] all
+ * individual video files will have the native resolution of the published stream
+ */
+ resolution?: string;
+
/**
* Whether or not to record the audio track (currently fixed to true)
*/
diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventRecording.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventRecording.java
index 72b0800f..d1a4fdb7 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventRecording.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventRecording.java
@@ -2,6 +2,7 @@ package io.openvidu.server.cdr;
import com.google.gson.JsonObject;
+import io.openvidu.java.client.RecordingLayout;
import io.openvidu.server.recording.Recording;
public class CDREventRecording extends CDREventEnd {
@@ -25,7 +26,15 @@ public class CDREventRecording extends CDREventEnd {
JsonObject json = super.toJson();
json.addProperty("id", this.recording.getId());
json.addProperty("name", this.recording.getName());
- json.addProperty("recordingLayout", this.recording.getRecordingLayout().name());
+ json.addProperty("outputMode", this.recording.getOutputMode().name());
+ if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(this.recording.getOutputMode())) {
+ json.addProperty("resolution", this.recording.getResolution());
+ json.addProperty("recordingLayout", this.recording.getRecordingLayout().name());
+ if (RecordingLayout.CUSTOM.equals(this.recording.getRecordingLayout())
+ && this.recording.getCustomLayout() != null && !this.recording.getCustomLayout().isEmpty()) {
+ json.addProperty("customLayout", this.recording.getCustomLayout());
+ }
+ }
json.addProperty("hasAudio", this.recording.hasAudio());
json.addProperty("hasVideo", this.recording.hasVideo());
json.addProperty("size", this.recording.getSize());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java
index a94e06a5..1a84b39d 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java
@@ -42,8 +42,8 @@ import io.openvidu.server.recording.service.RecordingManager;
* - 'participantLeft': {sessionId, timestamp, participantId, startTime, duration, reason}
* - 'webrtcConnectionCreated' {sessionId, timestamp, participantId, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate]}
* - 'webrtcConnectionDestroyed' {sessionId, timestamp, participantId, startTime, duration, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate], reason}
- * - 'recordingStarted' {sessionId, timestamp, id, name, hasAudio, hasVideo, recordingLayout, size}
- * - 'recordingStopped' {sessionId, timestamp, id, name, hasAudio, hasVideo, recordingLayout, size}
+ * - 'recordingStarted' {sessionId, timestamp, id, name, hasAudio, hasVideo, resolution, recordingLayout, size}
+ * - 'recordingStopped' {sessionId, timestamp, id, name, hasAudio, hasVideo, resolution, recordingLayout, size}
*
* PROPERTIES VALUES:
*
@@ -63,6 +63,7 @@ import io.openvidu.server.recording.service.RecordingManager;
* - name: string
* - hasAudio: boolean
* - hasVideo: boolean
+ * - resolution string
* - recordingLayout: string
* - size: number
* - webrtcConnectionDestroyed.reason: "unsubscribe", "unpublish", "disconnect", "networkDisconnect", "openviduServerStopped"
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java b/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java
index 392a693c..39ac8f4b 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java
@@ -32,6 +32,7 @@ public class Recording {
private long size = 0; // bytes
private double duration = 0; // seconds
private String url;
+ private String resolution;
private boolean hasAudio = true;
private boolean hasVideo = true;
private RecordingProperties recordingProperties;
@@ -42,6 +43,9 @@ public class Recording {
this.id = id;
this.status = io.openvidu.java.client.Recording.Status.started;
this.recordingProperties = recordingProperties;
+ this.resolution = this.recordingProperties.resolution();
+ this.hasAudio = this.recordingProperties.hasAudio();
+ this.hasVideo = this.recordingProperties.hasVideo();
}
public Recording(JsonObject json) {
@@ -66,8 +70,11 @@ public class Recording {
io.openvidu.java.client.Recording.OutputMode outputMode = io.openvidu.java.client.Recording.OutputMode
.valueOf(json.get("outputMode").getAsString());
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(json.get("name").getAsString())
- .outputMode(outputMode);
+ .outputMode(outputMode).hasAudio(json.get("hasAudio").getAsBoolean())
+ .hasVideo(json.get("hasVideo").getAsBoolean());
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(outputMode)) {
+ this.resolution = json.get("resolution").getAsString();
+ builder.resolution(this.resolution);
RecordingLayout recordingLayout = RecordingLayout.valueOf(json.get("recordingLayout").getAsString());
builder.recordingLayout(recordingLayout);
if (RecordingLayout.CUSTOM.equals(recordingLayout)) {
@@ -153,6 +160,14 @@ public class Recording {
this.url = url;
}
+ public String getResolution() {
+ return resolution;
+ }
+
+ public void setResolution(String resolution) {
+ this.resolution = resolution;
+ }
+
public boolean hasAudio() {
return hasAudio;
}
@@ -175,6 +190,7 @@ public class Recording {
json.addProperty("name", this.recordingProperties.name());
json.addProperty("outputMode", this.getOutputMode().name());
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(this.recordingProperties.outputMode())) {
+ json.addProperty("resolution", this.resolution);
json.addProperty("recordingLayout", this.recordingProperties.recordingLayout().name());
if (RecordingLayout.CUSTOM.equals(this.recordingProperties.recordingLayout())) {
json.addProperty("customLayout", this.recordingProperties.customLayout());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index d673b02f..c3ba4c54 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -94,7 +94,7 @@ public class ComposedRecordingService extends RecordingService {
String layoutUrl = this.getLayoutUrl(recording, this.getShortSessionId(session));
envs.add("URL=" + layoutUrl);
- envs.add("RESOLUTION=1920x1080");
+ envs.add("RESOLUTION=" + properties.resolution());
envs.add("FRAMERATE=30");
envs.add("VIDEO_ID=" + recordingId);
envs.add("VIDEO_NAME=" + properties.name());
@@ -216,6 +216,7 @@ public class ComposedRecordingService extends RecordingService {
recording.setStatus(io.openvidu.java.client.Recording.Status.stopped);
recording.setDuration(infoUtils.getDurationInSeconds());
recording.setSize(infoUtils.getSizeInBytes());
+ recording.setResolution(infoUtils.videoWidth() + "x" + infoUtils.videoHeight());
recording.setHasAudio(infoUtils.hasAudio());
recording.setHasVideo(infoUtils.hasVideo());
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 6c07d119..9ffc0230 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
@@ -50,8 +50,10 @@ public abstract class RecordingService {
if (properties.name() == null || properties.name().isEmpty()) {
// No name provided for the recording file. Use recordingId
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(recordingId)
- .outputMode(properties.outputMode());
+ .outputMode(properties.outputMode()).hasAudio(properties.hasAudio())
+ .hasVideo(properties.hasVideo());
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(properties.outputMode())) {
+ builder.resolution(properties.resolution());
builder.recordingLayout(properties.recordingLayout());
if (RecordingLayout.CUSTOM.equals(properties.recordingLayout())) {
builder.customLayout(properties.customLayout());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index b5646831..3ec30b0a 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -53,6 +53,7 @@ import io.openvidu.server.core.SessionManager;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
import io.openvidu.server.recording.Recording;
import io.openvidu.server.recording.service.RecordingManager;
+import io.openvidu.server.utils.FormatChecker;
/**
*
@@ -298,6 +299,7 @@ public class SessionRestController {
String sessionId = (String) params.get("session");
String name = (String) params.get("name");
String outputModeString = (String) params.get("outputMode");
+ String resolution = (String) params.get("resolution");
String recordingLayoutString = (String) params.get("recordingLayout");
String customLayout = (String) params.get("customLayout");
@@ -336,6 +338,15 @@ public class SessionRestController {
RecordingProperties.Builder builder = new RecordingProperties.Builder().name(name).outputMode(outputMode);
if (outputMode.equals(io.openvidu.java.client.Recording.OutputMode.COMPOSED)) {
+
+ if (resolution != null) {
+ if (new FormatChecker().isAcceptableResolution(resolution)) {
+ builder.resolution(resolution);
+ } else {
+ return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
+ }
+ }
+
RecordingLayout recordingLayout;
if (recordingLayoutString == null || recordingLayoutString.isEmpty()) {
// "recordingLayout" parameter not defined. Use global layout from
@@ -354,8 +365,6 @@ public class SessionRestController {
: customLayout;
builder.customLayout(customLayout);
}
-
- builder.build();
}
try {
diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java b/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java
new file mode 100644
index 00000000..d3849603
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2017-2019 OpenVidu (https://openvidu.io/)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.openvidu.server.utils;
+
+public class FormatChecker {
+
+ public boolean isAcceptableResolution(String stringResolution) {
+ // Matches every string with format "AxB", being A and B any number not starting
+ // with 0 and 3 digits long or 4 digits long if they start with 1
+ return stringResolution.matches("^(?!(0))(([0-9]{3})|1([0-9]{3}))x(?!0)(([0-9]{3})|1([0-9]{3}))$");
+ }
+
+}