openvidu-server: recording small fixes (duplicate recording start notification, do not init automatic stop on session closed by API REST, loggin improved)

pull/203/head
pabloFuente 2019-01-24 14:44:48 +01:00
parent 98d029a729
commit 718c7f9e63
4 changed files with 87 additions and 43 deletions

View File

@ -169,41 +169,48 @@ public class KurentoSessionManager extends SessionManager {
sessionEventsHandler.onParticipantLeft(participant, sessionId, remainingParticipants, transactionId, null, sessionEventsHandler.onParticipantLeft(participant, sessionId, remainingParticipants, transactionId, null,
reason); reason);
if (remainingParticipants.isEmpty()) { if (!"sessionClosedByServer".equals(reason)) {
if (openviduConfig.isRecordingModuleEnabled() // If session is closed by a call to "DELETE /api/sessions" do NOT stop the
// recording. Will be stopped after in method
// "SessionManager.closeSessionAndEmptyCollections"
if (remainingParticipants.isEmpty()) {
if (openviduConfig.isRecordingModuleEnabled()
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
&& (this.recordingManager.sessionIsBeingRecordedIndividual(sessionId)
|| (this.recordingManager.sessionIsBeingRecordedComposed(sessionId)
&& this.recordingManager.sessionIsBeingRecordedOnlyAudio(sessionId)))) {
// Start countdown to stop recording if INDIVIDUAL mode or COMPOSED audio-only
// (will be aborted if a Publisher starts before timeout)
log.info(
"Last participant left. Starting {} seconds countdown for stopping recording of session {}",
this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId);
recordingManager.initAutomaticRecordingStopThread(session);
} else {
log.info("No more participants in session '{}', removing it and closing it", sessionId);
this.closeSessionAndEmptyCollections(session, reason);
showTokens();
}
} else if (remainingParticipants.size() == 1 && openviduConfig.isRecordingModuleEnabled()
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode()) && MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
&& (this.recordingManager.sessionIsBeingRecordedIndividual(sessionId) && this.recordingManager.sessionIsBeingRecordedComposed(sessionId)
|| (this.recordingManager.sessionIsBeingRecordedComposed(sessionId) && !this.recordingManager.sessionIsBeingRecordedOnlyAudio(sessionId)
&& this.recordingManager.sessionIsBeingRecordedOnlyAudio(sessionId)))) { && ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
// Start countdown to stop recording if INDIVIDUAL mode or COMPOSED audio-only .equals(remainingParticipants.iterator().next().getParticipantPublicId())) {
// (will be aborted if a Publisher starts before timeout) if (RecordingMode.ALWAYS.equals(session.getSessionProperties().recordingMode())) {
log.info("Last participant left. Starting {} seconds countdown for stopping recording of session {}", // Immediately stop recording when last real participant left if
this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId); // RecordingMode.ALWAYS
recordingManager.initAutomaticRecordingStopThread(session); log.info("Last participant left. Stopping recording for session {}", sessionId);
} else { recordingManager.stopRecording(session, null, reason);
log.info("No more participants in session '{}', removing it and closing it", sessionId); evictParticipant(session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID),
this.closeSessionAndEmptyCollections(session, reason); null, null, "EVICT_RECORDER");
showTokens(); } else if (RecordingMode.MANUAL.equals(session.getSessionProperties().recordingMode())) {
} // Start countdown to stop recording if RecordingMode.MANUAL (will be aborted if
} else if (remainingParticipants.size() == 1 && openviduConfig.isRecordingModuleEnabled() // a Publisher starts before timeout)
&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode()) log.info(
&& this.recordingManager.sessionIsBeingRecordedComposed(sessionId) "Last participant left. Starting {} seconds countdown for stopping recording of session {}",
&& !this.recordingManager.sessionIsBeingRecordedOnlyAudio(sessionId) this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId);
&& ProtocolElements.RECORDER_PARTICIPANT_PUBLICID recordingManager.initAutomaticRecordingStopThread(session);
.equals(remainingParticipants.iterator().next().getParticipantPublicId())) { }
if (RecordingMode.ALWAYS.equals(session.getSessionProperties().recordingMode())) {
// Immediately stop recording when last real participant left if
// RecordingMode.ALWAYS
log.info("Last participant left. Stopping recording for session {}", sessionId);
recordingManager.stopRecording(session, null, reason);
evictParticipant(session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null,
null, "EVICT_RECORDER");
} else if (RecordingMode.MANUAL.equals(session.getSessionProperties().recordingMode())) {
// Start countdown to stop recording if RecordingMode.MANUAL (will be aborted if
// a Publisher starts before timeout)
log.info("Last participant left. Starting {} seconds countdown for stopping recording of session {}",
this.openviduConfig.getOpenviduRecordingAutostopTimeout(), sessionId);
recordingManager.initAutomaticRecordingStopThread(session);
} }
} }

View File

@ -93,8 +93,8 @@ public class ComposedRecordingService extends RecordingService {
recording = this.startRecordingAudioOnly(session, recording, properties); recording = this.startRecordingAudioOnly(session, recording, properties);
} }
// Update collections and return recording this.updateRecordingManagerCollections(session, recording);
this.updateCollectionsAndSendNotifCauseRecordingStarted(session, recording);
return recording; return recording;
} }
@ -111,7 +111,7 @@ public class ComposedRecordingService extends RecordingService {
throws OpenViduException { throws OpenViduException {
log.info("Joining single stream {} to Composite in session {}", participant.getPublisherStreamId(), log.info("Joining single stream {} to Composite in session {}", participant.getPublisherStreamId(),
session.getSessionId()); session.getSessionId());
KurentoParticipant kurentoParticipant = (KurentoParticipant) participant; KurentoParticipant kurentoParticipant = (KurentoParticipant) participant;
CompositeWrapper compositeWrapper = this.composites.get(session.getSessionId()); CompositeWrapper compositeWrapper = this.composites.get(session.getSessionId());
@ -132,6 +132,10 @@ public class ComposedRecordingService extends RecordingService {
private Recording startRecordingWithVideo(Session session, Recording recording, RecordingProperties properties) private Recording startRecordingWithVideo(Session session, Recording recording, RecordingProperties properties)
throws OpenViduException { throws OpenViduException {
log.info("Starting composed ({}) recording {} of session {}",
properties.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId());
List<String> envs = new ArrayList<>(); List<String> envs = new ArrayList<>();
String layoutUrl = this.getLayoutUrl(recording, this.getShortSessionId(session)); String layoutUrl = this.getLayoutUrl(recording, this.getShortSessionId(session));
@ -173,6 +177,9 @@ public class ComposedRecordingService extends RecordingService {
private Recording startRecordingAudioOnly(Session session, Recording recording, RecordingProperties properties) private Recording startRecordingAudioOnly(Session session, Recording recording, RecordingProperties properties)
throws OpenViduException { throws OpenViduException {
log.info("Starting composed (audio-only) recording {} of session {}", recording.getId(),
recording.getSessionId());
CompositeWrapper compositeWrapper = new CompositeWrapper((KurentoSession) session, CompositeWrapper compositeWrapper = new CompositeWrapper((KurentoSession) session,
"file://" + this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/" + properties.name() "file://" + this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/" + properties.name()
+ ".webm"); + ".webm");
@ -191,12 +198,17 @@ public class ComposedRecordingService extends RecordingService {
} }
this.generateRecordingMetadataFile(recording); this.generateRecordingMetadataFile(recording);
this.sendRecordingStartedNotification(session, recording);
return recording; return recording;
} }
private Recording stopRecordingWithVideo(Session session, Recording recording, String reason) { private Recording stopRecordingWithVideo(Session session, Recording recording, String reason) {
log.info("Stopping composed ({}) recording {} of session {}. Reason: {}",
recording.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId(),
RecordingManager.finalReason(reason));
String containerId = this.sessionsContainers.remove(recording.getSessionId()); String containerId = this.sessionsContainers.remove(recording.getSessionId());
this.cleanRecordingMaps(recording); this.cleanRecordingMaps(recording);
@ -218,13 +230,14 @@ public class ComposedRecordingService extends RecordingService {
log.warn("Session closed while starting recording container"); log.warn("Session closed while starting recording container");
boolean containerClosed = false; boolean containerClosed = false;
String containerIdAux; String containerIdAux;
int timeOut = 0; int i = 0;
while (!containerClosed && (timeOut < 30)) { final int timeout = 30;
while (!containerClosed && (i < timeout)) {
containerIdAux = this.sessionsContainers.remove(session.getSessionId()); containerIdAux = this.sessionsContainers.remove(session.getSessionId());
if (containerIdAux == null) { if (containerIdAux == null) {
try { try {
log.warn("Waiting for container to be launched..."); log.warn("Waiting for container to be launched...");
timeOut++; i++;
Thread.sleep(500); Thread.sleep(500);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
@ -244,6 +257,10 @@ public class ComposedRecordingService extends RecordingService {
} }
} }
} }
if (i == timeout) {
log.error("Container did not launched in {} seconds", timeout / 2);
return;
}
}).start(); }).start();
} else { } else {
@ -309,6 +326,10 @@ public class ComposedRecordingService extends RecordingService {
} }
private Recording stopRecordingAudioOnly(Session session, Recording recording, String reason) { private Recording stopRecordingAudioOnly(Session session, Recording recording, String reason) {
log.info("Stopping composed (audio-only) recording {} of session {}. Reason: {}", recording.getId(),
recording.getSessionId(), reason);
String sessionId; String sessionId;
if (session == null) { if (session == null) {
log.warn( log.warn(

View File

@ -83,11 +83,17 @@ public abstract class RecordingService {
* Changes recording from starting to started, updates global recording * Changes recording from starting to started, updates global recording
* collections and sends RPC response to clients * collections and sends RPC response to clients
*/ */
protected void updateCollectionsAndSendNotifCauseRecordingStarted(Session session, Recording recording) { protected void updateRecordingManagerCollections(Session session, Recording recording) {
this.recordingManager.sessionHandler.setRecordingStarted(session.getSessionId(), recording); this.recordingManager.sessionHandler.setRecordingStarted(session.getSessionId(), recording);
this.recordingManager.sessionsRecordings.put(session.getSessionId(), recording); this.recordingManager.sessionsRecordings.put(session.getSessionId(), recording);
this.recordingManager.startingRecordings.remove(recording.getId()); this.recordingManager.startingRecordings.remove(recording.getId());
this.recordingManager.startedRecordings.put(recording.getId(), recording); this.recordingManager.startedRecordings.put(recording.getId(), recording);
}
/**
* Sends RPC response for recording started event
*/
protected void sendRecordingStartedNotification(Session session, Recording recording) {
this.recordingManager.getSessionEventsHandler().sendRecordingStartedNotification(session, recording); this.recordingManager.getSessionEventsHandler().sendRecordingStartedNotification(session, recording);
} }
@ -126,6 +132,7 @@ public abstract class RecordingService {
} }
protected OpenViduException failStartRecording(Session session, Recording recording, String errorMessage) { protected OpenViduException failStartRecording(Session session, Recording recording, String errorMessage) {
log.error("Recording start failed for session {}: {}", session.getSessionId(), errorMessage);
recording.setStatus(io.openvidu.java.client.Recording.Status.failed); recording.setStatus(io.openvidu.java.client.Recording.Status.failed);
this.recordingManager.startingRecordings.remove(recording.getId()); this.recordingManager.startingRecordings.remove(recording.getId());
this.stopRecording(session, recording, null); this.stopRecording(session, recording, null);

View File

@ -78,7 +78,11 @@ public class SingleStreamRecordingService extends RecordingService {
properties); properties);
properties = updatePropertiesAndRecordingId.properties; properties = updatePropertiesAndRecordingId.properties;
String recordingId = updatePropertiesAndRecordingId.recordingId; String recordingId = updatePropertiesAndRecordingId.recordingId;
log.info("Starting individual ({}) recording {} of session {}",
properties.hasVideo() ? (properties.hasAudio() ? "video+audio" : "video-only") : "audioOnly",
recordingId, session.getSessionId());
Recording recording = new Recording(session.getSessionId(), recordingId, properties); Recording recording = new Recording(session.getSessionId(), recordingId, properties);
this.recordingManager.startingRecordings.put(recording.getId(), recording); this.recordingManager.startingRecordings.put(recording.getId(), recording);
@ -120,7 +124,8 @@ public class SingleStreamRecordingService extends RecordingService {
} }
this.generateRecordingMetadataFile(recording); this.generateRecordingMetadataFile(recording);
this.updateCollectionsAndSendNotifCauseRecordingStarted(session, recording); this.updateRecordingManagerCollections(session, recording);
this.sendRecordingStartedNotification(session, recording);
return recording; return recording;
} }
@ -128,6 +133,10 @@ public class SingleStreamRecordingService extends RecordingService {
@Override @Override
public Recording stopRecording(Session session, Recording recording, String reason) { public Recording stopRecording(Session session, Recording recording, String reason) {
log.info("Stopping individual ({}) recording {} of session {}. Reason: {}",
recording.hasVideo() ? (recording.hasAudio() ? "video+audio" : "video-only") : "audioOnly",
recording.getId(), recording.getSessionId(), reason);
final int numberOfActiveRecorders = recorders.get(recording.getSessionId()).size(); final int numberOfActiveRecorders = recorders.get(recording.getSessionId()).size();
final CountDownLatch stoppedCountDown = new CountDownLatch(numberOfActiveRecorders); final CountDownLatch stoppedCountDown = new CountDownLatch(numberOfActiveRecorders);