openvidu-server: recording status refactoring

pull/375/head
pabloFuente 2019-06-27 14:04:02 +02:00
parent a528e1da8e
commit 690900a45b
14 changed files with 132 additions and 128 deletions

View File

@ -450,8 +450,9 @@ public class OpenVidu {
/** /**
* Deletes a recording. The recording must have status * Deletes a recording. The recording must have status
* {@link io.openvidu.java.client.Recording.Status#stopped} or * {@link io.openvidu.java.client.Recording.Status#stopped},
* {@link io.openvidu.java.client.Recording.Status#available} * {@link io.openvidu.java.client.Recording.Status#ready} or
* {@link io.openvidu.java.client.Recording.Status#failed}
* *
* @param recordingId The id property of the recording you want to delete * @param recordingId The id property of the recording you want to delete
* *

View File

@ -30,7 +30,8 @@ public class Recording {
public enum Status { public enum Status {
/** /**
* The recording is starting (cannot be stopped) * The recording is starting (cannot be stopped). Some recording may not go
* through this status and directly reach "started" status
*/ */
starting, starting,
@ -40,27 +41,21 @@ public class Recording {
started, started,
/** /**
* The recording has finished OK * The recording has stopped and is being processed. At some point it will reach
* "ready" status
*/ */
stopped, stopped,
/** /**
* The recording has stopped but is being processed. This status will change to * The recording has finished OK and is available for download through OpenVidu
* stopped/available or failed * Server recordings endpoint:
* https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
*/ */
processing, ready,
/** /**
* The recording is available for downloading. This status is reached for all * The recording has failed. This status may be reached from "starting",
* stopped recordings if * "started" and "stopped" status
* <a href="https://openvidu.io/docs/reference-docs/openvidu-server-params/"
* target="_blank">OpenVidu Server configuration</a> property
* <code>openvidu.recording.public-access</code> is true
*/
available,
/**
* The recording has failed
*/ */
failed; failed;
} }

View File

@ -359,7 +359,7 @@ export class OpenVidu {
} }
/** /**
* Deletes a [[Recording]]. The recording must have status `stopped` or `available` * Deletes a [[Recording]]. The recording must have status `stopped`, `ready` or `failed`
* *
* @param recordingId * @param recordingId
* *

View File

@ -101,7 +101,8 @@ export namespace Recording {
export enum Status { export enum Status {
/** /**
* The recording is starting (cannot be stopped) * The recording is starting (cannot be stopped). Some recording may not go
* through this status and directly reach "started" status
*/ */
starting = 'starting', starting = 'starting',
@ -111,25 +112,21 @@ export namespace Recording {
started = 'started', started = 'started',
/** /**
* The recording has finished OK * The recording has stopped and is being processed. At some point it will reach
*/ * "ready" status
*/
stopped = 'stopped', stopped = 'stopped',
/** /**
* The recording has stopped but is being processed. This status will change to * The recording has finished OK and is available for download through OpenVidu
* stopped/available or failed when processing ends * Server recordings endpoint:
*/ * https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION}
processing = 'processing',
/**
* The recording is available for downloading. This status is reached for all
* stopped recordings if [OpenVidu Server configuration](https://openvidu.io/docs/reference-docs/openvidu-server-params/)
* property `openvidu.recording.public-access` is true
*/ */
available = 'available', ready = 'ready',
/** /**
* The recording has failed * The recording has failed. This status may be reached from "starting",
* "started" and "stopped" status
*/ */
failed = 'failed' failed = 'failed'
} }

View File

@ -28,8 +28,8 @@ public class CDREventRecording extends CDREventEnd {
protected Recording recording; protected Recording recording;
// recordingStarted // recordingStarted
public CDREventRecording(String sessionId, Recording recording) { public CDREventRecording(Recording recording) {
super(CDREventName.recordingStarted, sessionId, recording.getCreatedAt()); super(CDREventName.recordingStarted, recording.getSessionId(), recording.getCreatedAt());
this.recording = recording; this.recording = recording;
} }

View File

@ -20,33 +20,41 @@ package io.openvidu.server.cdr;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import io.openvidu.java.client.Recording.Status; import io.openvidu.java.client.Recording.Status;
import io.openvidu.java.client.RecordingLayout;
import io.openvidu.server.core.EndReason; import io.openvidu.server.core.EndReason;
import io.openvidu.server.recording.Recording; import io.openvidu.server.recording.Recording;
public class CDREventRecordingStatus extends CDREventRecording { public class CDREventRecordingStatus extends CDREventEnd {
private Recording recording;
private Status status; private Status status;
public CDREventRecordingStatus(String sessionId, Recording recording, Status status) { public CDREventRecordingStatus(Recording recording, Long startTime, EndReason reason, Long timestamp,
super(sessionId, recording); Status status) {
this.eventName = CDREventName.recordingStatusChanged; super(CDREventName.recordingStatusChanged, recording.getSessionId(), startTime, reason, timestamp);
this.recording = recording;
this.status = status; this.status = status;
} }
public CDREventRecordingStatus(CDREventRecording recordingStartedEvent, Recording recording, EndReason finalReason,
long timestamp, Status status) {
super(recordingStartedEvent, recording, finalReason, timestamp);
this.eventName = CDREventName.recordingStatusChanged;
this.status = status;
}
public Status getStatus() {
return status;
}
@Override @Override
public JsonObject toJson() { public JsonObject toJson() {
JsonObject json = super.toJson(); JsonObject json = super.toJson();
json.addProperty("id", this.recording.getId());
json.addProperty("name", this.recording.getName());
json.addProperty("outputMode", this.recording.getOutputMode().name());
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(this.recording.getOutputMode())
&& this.recording.hasVideo()) {
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());
json.addProperty("duration", this.recording.getDuration());
json.addProperty("status", this.status.name()); json.addProperty("status", this.status.name());
return json; return json;
} }

View File

@ -198,34 +198,25 @@ public class CallDetailRecord {
} }
} }
public void recordRecordingStarted(String sessionId, Recording recording) { public void recordRecordingStarted(Recording recording) {
CDREventRecording recordingStartedEvent = new CDREventRecording(sessionId, recording); CDREventRecording recordingStartedEvent = new CDREventRecording(recording);
this.recordings.putIfAbsent(recording.getId(), recordingStartedEvent); this.recordings.putIfAbsent(recording.getId(), recordingStartedEvent);
this.log(new CDREventRecording(sessionId, recording)); this.log(recordingStartedEvent);
this.recordRecordingStatusChanged(sessionId, recording, Status.started);
} }
public void recordRecordingStopped(String sessionId, Recording recording, EndReason reason) { public void recordRecordingStopped(Recording recording, EndReason reason, long timestamp) {
CDREventRecording recordingStartedEvent = this.recordings.remove(recording.getId()); CDREventRecording recordingStartedEvent = this.recordings.remove(recording.getId());
final long timestamp = System.currentTimeMillis();
CDREventRecording recordingStoppedEvent = new CDREventRecording(recordingStartedEvent, recording, CDREventRecording recordingStoppedEvent = new CDREventRecording(recordingStartedEvent, recording,
RecordingManager.finalReason(reason), timestamp); RecordingManager.finalReason(reason), timestamp);
this.log(recordingStoppedEvent); this.log(recordingStoppedEvent);
this.recordRecordingStatusChanged(recordingStartedEvent, recording, RecordingManager.finalReason(reason),
timestamp, Status.stopped);
// Summary: update ended recording // Summary: update ended recording
sessionManager.getAccumulatedRecordings(sessionId).add(recordingStoppedEvent); sessionManager.getAccumulatedRecordings(recording.getSessionId()).add(recordingStoppedEvent);
} }
public void recordRecordingStatusChanged(String sessionId, Recording recording, Status status) { public void recordRecordingStatusChanged(Recording recording, EndReason finalReason, long timestamp,
this.log(new CDREventRecordingStatus(sessionId, recording, status)); Status status) {
} this.log(new CDREventRecordingStatus(recording, recording.getCreatedAt(), finalReason, timestamp, status));
public void recordRecordingStatusChanged(CDREventRecording recordingStartedEvent, Recording recording,
EndReason finalReason, long timestamp, Status status) {
this.log(new CDREventRecordingStatus(recordingStartedEvent, recording, finalReason, timestamp, status));
} }
private void log(CDREvent event) { private void log(CDREvent event) {

View File

@ -13,4 +13,8 @@ public class DummyRecordingDownloader implements RecordingDownloader {
return; return;
} }
@Override
public void cancelDownload(String recordingId) {
}
} }

View File

@ -25,4 +25,6 @@ public interface RecordingDownloader {
public void downloadRecording(Recording recording, Collection<String> streamIds, Runnable callback) public void downloadRecording(Recording recording, Collection<String> streamIds, Runnable callback)
throws IOException; throws IOException;
public void cancelDownload(String recordingId);
} }

View File

@ -94,10 +94,10 @@ public class ComposedRecordingService extends RecordingService {
@Override @Override
public Recording stopRecording(Session session, Recording recording, EndReason reason) { public Recording stopRecording(Session session, Recording recording, EndReason reason) {
recording = this.sealRecordingMetadataFileAsStopped(recording);
if (recording.hasVideo()) { if (recording.hasVideo()) {
return this.stopRecordingWithVideo(session, recording, reason); return this.stopRecordingWithVideo(session, recording, reason);
} else { } else {
recording = this.sealRecordingMetadataFileAsProcessing(recording);
return this.stopRecordingAudioOnly(session, recording, reason, 0); return this.stopRecordingAudioOnly(session, recording, reason, 0);
} }
} }
@ -240,7 +240,7 @@ public class ComposedRecordingService extends RecordingService {
if (containerId == null) { if (containerId == null) {
// Session was closed while recording container was initializing // Session was closed while recording container was initializing
// Wait until containerId is available and force its stop and removal // Wait until containerId is available and force its stop and deletion
new Thread(() -> { new Thread(() -> {
log.warn("Session closed while starting recording container"); log.warn("Session closed while starting recording container");
boolean containerClosed = false; boolean containerClosed = false;
@ -311,25 +311,23 @@ public class ComposedRecordingService extends RecordingService {
log.error("COMPOSED recording {} with hasVideo=true has not video track", recordingId); log.error("COMPOSED recording {} with hasVideo=true has not video track", recordingId);
recording.setStatus(io.openvidu.java.client.Recording.Status.failed); recording.setStatus(io.openvidu.java.client.Recording.Status.failed);
} else { } else {
recording.setStatus(io.openvidu.java.client.Recording.Status.stopped); recording.setStatus(io.openvidu.java.client.Recording.Status.ready);
recording.setDuration(infoUtils.getDurationInSeconds()); recording.setDuration(infoUtils.getDurationInSeconds());
recording.setSize(infoUtils.getSizeInBytes()); recording.setSize(infoUtils.getSizeInBytes());
recording.setResolution(infoUtils.videoWidth() + "x" + infoUtils.videoHeight()); recording.setResolution(infoUtils.videoWidth() + "x" + infoUtils.videoHeight());
recording.setHasAudio(infoUtils.hasAudio()); recording.setHasAudio(infoUtils.hasAudio());
recording.setHasVideo(infoUtils.hasVideo()); recording.setHasVideo(infoUtils.hasVideo());
} }
infoUtils.deleteFilePath(); infoUtils.deleteFilePath();
recording = this.recordingManager.updateRecordingUrl(recording);
} catch (IOException e) { } catch (IOException e) {
recording.setStatus(io.openvidu.java.client.Recording.Status.failed); recording.setStatus(io.openvidu.java.client.Recording.Status.failed);
throw new OpenViduException(Code.RECORDING_REPORT_ERROR_CODE, throw new OpenViduException(Code.RECORDING_REPORT_ERROR_CODE,
"There was an error generating the metadata report file for the recording"); "There was an error generating the metadata report file for the recording");
} }
this.cdr.recordRecordingStopped(recording.getSessionId(), recording, reason); final long timestamp = System.currentTimeMillis();
this.cdr.recordRecordingStopped(recording, reason, timestamp);
this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, recording.getStatus());
if (session != null && reason != null) { if (session != null && reason != null) {
this.recordingManager.sessionHandler.sendRecordingStoppedNotification(session, recording, reason); this.recordingManager.sessionHandler.sendRecordingStoppedNotification(session, recording, reason);
@ -383,9 +381,13 @@ public class ComposedRecordingService extends RecordingService {
long finalSize = videoFile.length(); long finalSize = videoFile.length();
double finalDuration = (double) compositeWrapper.getDuration() / 1000; double finalDuration = (double) compositeWrapper.getDuration() / 1000;
this.updateFilePermissions(filesPath); this.updateFilePermissions(filesPath);
finalRecordingArray[0] = this.sealRecordingMetadataFileAsStopped(recording, finalSize, finalDuration, finalRecordingArray[0] = this.sealRecordingMetadataFileAsReady(recording, finalSize, finalDuration,
filesPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId()); filesPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId());
cdr.recordRecordingStopped(finalRecordingArray[0].getSessionId(), finalRecordingArray[0], reason);
final long timestamp = System.currentTimeMillis();
cdr.recordRecordingStopped(finalRecordingArray[0], reason, timestamp);
cdr.recordRecordingStatusChanged(finalRecordingArray[0], reason, timestamp,
finalRecordingArray[0].getStatus());
}); });
} catch (IOException e) { } catch (IOException e) {
log.error("Error while downloading recording {}: {}", recording.getName(), e.getMessage()); log.error("Error while downloading recording {}: {}", recording.getName(), e.getMessage());

View File

@ -55,6 +55,7 @@ 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.Recording.OutputMode; import io.openvidu.java.client.Recording.OutputMode;
import io.openvidu.java.client.Recording.Status;
import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.RecordingProperties;
import io.openvidu.server.cdr.CallDetailRecord; import io.openvidu.server.cdr.CallDetailRecord;
import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.config.OpenviduConfig;
@ -187,7 +188,9 @@ public class RecordingManager {
} }
this.updateRecordingManagerCollections(session, recording); this.updateRecordingManagerCollections(session, recording);
this.cdr.recordRecordingStarted(session.getSessionId(), recording); this.cdr.recordRecordingStarted(recording);
this.cdr.recordRecordingStatusChanged(recording, null, recording.getCreatedAt(),
io.openvidu.java.client.Recording.Status.started);
if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) { if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) {
// Directly send recording started notification for all cases except for // Directly send recording started notification for all cases except for
@ -211,6 +214,10 @@ public class RecordingManager {
} else { } else {
recording = this.sessionsRecordings.get(session.getSessionId()); recording = this.sessionsRecordings.get(session.getSessionId());
} }
final long timestamp = System.currentTimeMillis();
this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, Status.stopped);
switch (recording.getOutputMode()) { switch (recording.getOutputMode()) {
case COMPOSED: case COMPOSED:
recording = this.composedRecordingService.stopRecording(session, recording, reason); recording = this.composedRecordingService.stopRecording(session, recording, reason);
@ -312,8 +319,7 @@ public class RecordingManager {
public Collection<Recording> getFinishedRecordings() { public Collection<Recording> getFinishedRecordings() {
return this.getAllRecordingsFromHost().stream() return this.getAllRecordingsFromHost().stream()
.filter(recording -> (recording.getStatus().equals(io.openvidu.java.client.Recording.Status.stopped) .filter(recording -> recording.getStatus().equals(io.openvidu.java.client.Recording.Status.ready))
|| recording.getStatus().equals(io.openvidu.java.client.Recording.Status.available)))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@ -352,6 +358,11 @@ public class RecordingManager {
if (recording == null) { if (recording == null) {
return HttpStatus.NOT_FOUND; return HttpStatus.NOT_FOUND;
} }
if (io.openvidu.java.client.Recording.Status.stopped.equals(recording.getStatus())) {
// Recording is being downloaded from remote host
log.warn("Cancelling ongoing download process of recording {}", recording.getId());
this.recordingDownloader.cancelDownload(recording.getId());
}
File folder = new File(this.openviduConfig.getOpenViduRecordingPath()); File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
File[] files = folder.listFiles(); File[] files = folder.listFiles();
@ -443,30 +454,6 @@ public class RecordingManager {
} }
} }
public Recording updateRecordingUrl(Recording recording) {
if (openviduConfig.getOpenViduRecordingPublicAccess()) {
if (io.openvidu.java.client.Recording.Status.stopped.equals(recording.getStatus())) {
String extension;
switch (recording.getOutputMode()) {
case COMPOSED:
extension = recording.hasVideo() ? "mp4" : "webm";
break;
case INDIVIDUAL:
extension = "zip";
break;
default:
extension = "mp4";
}
recording.setUrl(this.openviduConfig.getFinalUrl() + "recordings/" + recording.getId() + "/"
+ recording.getName() + "." + extension);
recording.setStatus(io.openvidu.java.client.Recording.Status.available);
}
}
return recording;
}
private Recording getRecordingFromHost(String recordingId) { private Recording getRecordingFromHost(String recordingId) {
log.info(this.openviduConfig.getOpenViduRecordingPath() + recordingId + "/" log.info(this.openviduConfig.getOpenViduRecordingPath() + recordingId + "/"
+ RecordingManager.RECORDING_ENTITY_FILE + recordingId); + RecordingManager.RECORDING_ENTITY_FILE + recordingId);
@ -474,9 +461,6 @@ public class RecordingManager {
+ RecordingManager.RECORDING_ENTITY_FILE + recordingId); + RecordingManager.RECORDING_ENTITY_FILE + recordingId);
log.info("File exists: " + file.exists()); log.info("File exists: " + file.exists());
Recording recording = this.getRecordingFromEntityFile(file); Recording recording = this.getRecordingFromEntityFile(file);
if (recording != null) {
this.updateRecordingUrl(recording);
}
return recording; return recording;
} }
@ -491,7 +475,6 @@ public class RecordingManager {
for (int j = 0; j < innerFiles.length; j++) { for (int j = 0; j < innerFiles.length; j++) {
Recording recording = this.getRecordingFromEntityFile(innerFiles[j]); Recording recording = this.getRecordingFromEntityFile(innerFiles[j]);
if (recording != null) { if (recording != null) {
this.updateRecordingUrl(recording);
recordingEntities.add(recording); recordingEntities.add(recording);
} }
} }

View File

@ -24,7 +24,6 @@ import org.slf4j.LoggerFactory;
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.Recording.Status;
import io.openvidu.java.client.RecordingLayout; import io.openvidu.java.client.RecordingLayout;
import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.RecordingProperties;
import io.openvidu.server.cdr.CallDetailRecord; import io.openvidu.server.cdr.CallDetailRecord;
@ -82,31 +81,29 @@ public abstract class RecordingService {
} }
/** /**
* Update and overwrites metadata recording file to set it in "processing" * Update and overwrites metadata recording file to set it in "stopped" status.
* status. Recording size and duration will remain as 0 * Recording size and duration will remain as 0
* *
* @return updated Recording object * @return updated Recording object
*/ */
protected Recording sealRecordingMetadataFileAsProcessing(Recording recording) { protected Recording sealRecordingMetadataFileAsStopped(Recording recording) {
final String entityFile = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/" final String entityFile = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"
+ RecordingManager.RECORDING_ENTITY_FILE + recording.getId(); + RecordingManager.RECORDING_ENTITY_FILE + recording.getId();
Recording rec = this.sealRecordingMetadataFile(recording, 0, 0, return this.sealRecordingMetadataFile(recording, 0, 0, io.openvidu.java.client.Recording.Status.stopped,
io.openvidu.java.client.Recording.Status.processing, entityFile); entityFile);
this.cdr.recordRecordingStatusChanged(recording.getSessionId(), recording, Status.processing);
return rec;
} }
/** /**
* Update and overwrites metadata recording file to set it in "stopped" (or * Update and overwrites metadata recording file to set it in "ready" (or
* "failed") status * "failed") status
* *
* @return updated Recording object * @return updated Recording object
*/ */
protected Recording sealRecordingMetadataFileAsStopped(Recording recording, long size, double duration, protected Recording sealRecordingMetadataFileAsReady(Recording recording, long size, double duration,
String metadataFilePath) { String metadataFilePath) {
io.openvidu.java.client.Recording.Status status = io.openvidu.java.client.Recording.Status.failed io.openvidu.java.client.Recording.Status status = io.openvidu.java.client.Recording.Status.failed
.equals(recording.getStatus()) ? io.openvidu.java.client.Recording.Status.failed .equals(recording.getStatus()) ? io.openvidu.java.client.Recording.Status.failed
: io.openvidu.java.client.Recording.Status.stopped; : io.openvidu.java.client.Recording.Status.ready;
final String entityFile = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/" final String entityFile = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"
+ RecordingManager.RECORDING_ENTITY_FILE + recording.getId(); + RecordingManager.RECORDING_ENTITY_FILE + recording.getId();
@ -119,7 +116,6 @@ public abstract class RecordingService {
recording.setSize(size); // Size in bytes recording.setSize(size); // Size in bytes
recording.setDuration(duration > 0 ? duration : 0); // Duration in seconds recording.setDuration(duration > 0 ? duration : 0); // Duration in seconds
this.fileWriter.overwriteFile(metadataFilePath, recording.toJson().toString()); this.fileWriter.overwriteFile(metadataFilePath, recording.toJson().toString());
recording = this.recordingManager.updateRecordingUrl(recording);
log.info("Sealed recording metadata file at {} with status [{}]", metadataFilePath, status.name()); log.info("Sealed recording metadata file at {} with status [{}]", metadataFilePath, status.name());

View File

@ -131,7 +131,7 @@ public class SingleStreamRecordingService extends RecordingService {
@Override @Override
public Recording stopRecording(Session session, Recording recording, EndReason reason) { public Recording stopRecording(Session session, Recording recording, EndReason reason) {
recording = this.sealRecordingMetadataFileAsProcessing(recording); recording = this.sealRecordingMetadataFileAsStopped(recording);
return this.stopRecording(session, recording, reason, 0); return this.stopRecording(session, recording, reason, 0);
} }
@ -171,7 +171,11 @@ public class SingleStreamRecordingService extends RecordingService {
} }
} }
finalRecordingArray[0] = this.sealMetadataFiles(recording); finalRecordingArray[0] = this.sealMetadataFiles(recording);
cdr.recordRecordingStopped(finalRecordingArray[0].getSessionId(), finalRecordingArray[0], reason);
final long timestamp = System.currentTimeMillis();
cdr.recordRecordingStopped(finalRecordingArray[0], reason, timestamp);
cdr.recordRecordingStatusChanged(finalRecordingArray[0], reason, timestamp,
finalRecordingArray[0].getStatus());
}); });
} catch (IOException e) { } catch (IOException e) {
log.error("Error while downloading recording {}", recording.getName()); log.error("Error while downloading recording {}", recording.getName());
@ -427,7 +431,7 @@ public class SingleStreamRecordingService extends RecordingService {
double duration = (double) (maxEndTime - minStartTime) / 1000; double duration = (double) (maxEndTime - minStartTime) / 1000;
duration = duration > 0 ? duration : 0; duration = duration > 0 ? duration : 0;
recording = this.sealRecordingMetadataFileAsStopped(recording, accumulatedSize, duration, metadataFilePath); recording = this.sealRecordingMetadataFileAsReady(recording, accumulatedSize, duration, metadataFilePath);
return recording; return recording;
} }

View File

@ -2209,8 +2209,8 @@ public class OpenViduTestAppE2eTest {
Assert.assertTrue("Wrong recording size. Excepected > 0 and was " + recording.getSize(), Assert.assertTrue("Wrong recording size. Excepected > 0 and was " + recording.getSize(),
recording.getSize() > 0); recording.getSize() > 0);
Assert.assertNull("Wrong recording url. Expected not null and was null", recording.getUrl()); Assert.assertNull("Wrong recording url. Expected not null and was null", recording.getUrl());
Assert.assertEquals("Wrong recording status. Expected stopped and was " + recording.getStatus().name(), Assert.assertEquals("Wrong recording status. Expected ready and was " + recording.getStatus().name(),
Recording.Status.stopped, recording.getStatus()); Recording.Status.ready, recording.getStatus());
Assert.assertFalse("Session shouldn't be being recorded", session.isBeingRecorded()); Assert.assertFalse("Session shouldn't be being recorded", session.isBeingRecorded());
Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch()); Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch());
@ -2261,7 +2261,7 @@ public class OpenViduTestAppE2eTest {
Assert.assertTrue("Wrong recording duration", recording2.getDuration() > 0); Assert.assertTrue("Wrong recording duration", recording2.getDuration() > 0);
Assert.assertTrue("Wrong recording size", recording2.getSize() > 0); Assert.assertTrue("Wrong recording size", recording2.getSize() > 0);
Assert.assertNull("Wrong recording url", recording2.getUrl()); Assert.assertNull("Wrong recording url", recording2.getUrl());
Assert.assertEquals("Wrong recording status", Recording.Status.stopped, recording2.getStatus()); Assert.assertEquals("Wrong recording status", Recording.Status.ready, recording2.getStatus());
Assert.assertFalse("Session shouldn't be being recorded", session.isBeingRecorded()); Assert.assertFalse("Session shouldn't be being recorded", session.isBeingRecorded());
Assert.assertFalse("Session.fetch() should return false", session.fetch()); Assert.assertFalse("Session.fetch() should return false", session.fetch());
@ -2773,6 +2773,9 @@ public class OpenViduTestAppE2eTest {
event.get("outputMode").getAsString()); event.get("outputMode").getAsString());
Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("size").getAsLong()); Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("size").getAsLong());
Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("duration").getAsLong()); Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("duration").getAsLong());
Assert.assertEquals("Wrong recording startTime/timestamp in webhook event",
event.get("startTime").getAsLong(), event.get("timestamp").getAsLong());
Assert.assertNull("Wrong recording reason in webhook event (should be null)", event.get("reason"));
user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
@ -2796,16 +2799,34 @@ public class OpenViduTestAppE2eTest {
CustomWebhook.waitForEvent("participantLeft", 2); CustomWebhook.waitForEvent("participantLeft", 2);
event = CustomWebhook.waitForEvent("recordingStatusChanged", 2); event = CustomWebhook.waitForEvent("recordingStatusChanged", 2);
Assert.assertEquals("Wrong recording status in webhook event", "processing", OV.fetch();
List<Recording> recs = OV.listRecordings();
Assert.assertEquals("Wrong number of recording entities", 1, recs.size());
Recording rec = recs.get(0);
Assert.assertEquals("Wrong recording status in webhook event", "stopped",
event.get("status").getAsString()); event.get("status").getAsString());
Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("size").getAsLong()); Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("size").getAsLong());
Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("duration").getAsLong()); Assert.assertEquals("Wrong recording outputMode in webhook event", 0, event.get("duration").getAsLong());
Assert.assertEquals("Wrong recording reason in webhook event", "sessionClosedByServer",
event.get("reason").getAsString());
Assert.assertEquals("Wrong recording reason in webhook event", rec.getCreatedAt(),
event.get("startTime").getAsLong());
event = CustomWebhook.waitForEvent("recordingStatusChanged", 2); event = CustomWebhook.waitForEvent("recordingStatusChanged", 2);
Assert.assertEquals("Wrong recording status in webhook event", "stopped",
event.get("status").getAsString()); OV.fetch();
recs = OV.listRecordings();
Assert.assertEquals("Wrong number of recording entities", 1, recs.size());
rec = recs.get(0);
Assert.assertEquals("Wrong recording status in webhook event", "ready", event.get("status").getAsString());
Assert.assertTrue("Wrong recording outputMode in webhook event", event.get("size").getAsLong() > 0); Assert.assertTrue("Wrong recording outputMode in webhook event", event.get("size").getAsLong() > 0);
Assert.assertTrue("Wrong recording outputMode in webhook event", event.get("duration").getAsLong() > 0); Assert.assertTrue("Wrong recording outputMode in webhook event", event.get("duration").getAsLong() > 0);
Assert.assertEquals("Wrong recording reason in webhook event", "sessionClosedByServer",
event.get("reason").getAsString());
Assert.assertEquals("Wrong recording reason in webhook event", rec.getCreatedAt(),
event.get("startTime").getAsLong());
CustomWebhook.waitForEvent("sessionDestroyed", 2); CustomWebhook.waitForEvent("sessionDestroyed", 2);