Enable google cloud storage uploading for recordings

pull/579/head
moboa 2020-12-20 16:46:19 -05:00
parent bd3b0f5b66
commit e3992b4383
4 changed files with 102 additions and 5 deletions

View File

@ -327,6 +327,18 @@
<artifactId>openvidu-java-client</artifactId> <artifactId>openvidu-java-client</artifactId>
<version>${version.openvidu.java.client}</version> <version>${version.openvidu.java.client}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>16.1.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-storage</artifactId>
<version>1.113.4</version>
</dependency>
<!-- Test dependencies --> <!-- Test dependencies -->

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import io.openvidu.server.recording.*;
import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Arrays;
import org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration; import org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration;
import org.kurento.jsonrpc.server.JsonRpcConfigurer; import org.kurento.jsonrpc.server.JsonRpcConfigurer;
@ -61,10 +62,6 @@ import io.openvidu.server.kurento.kms.DummyLoadManager;
import io.openvidu.server.kurento.kms.FixedOneKmsManager; import io.openvidu.server.kurento.kms.FixedOneKmsManager;
import io.openvidu.server.kurento.kms.KmsManager; import io.openvidu.server.kurento.kms.KmsManager;
import io.openvidu.server.kurento.kms.LoadManager; import io.openvidu.server.kurento.kms.LoadManager;
import io.openvidu.server.recording.DummyRecordingDownloader;
import io.openvidu.server.recording.DummyRecordingUploader;
import io.openvidu.server.recording.RecordingDownloader;
import io.openvidu.server.recording.RecordingUploader;
import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.recording.service.RecordingManagerUtils; import io.openvidu.server.recording.service.RecordingManagerUtils;
import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage; import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage;
@ -203,7 +200,11 @@ public class OpenViduServer implements JsonRpcConfigurer {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public RecordingUploader recordingUpload() { @DependsOn("openviduConfig")
public RecordingUploader recordingUpload(OpenviduConfig openviduConfig) {
if (openviduConfig.isGcpRecordingStorageEnabled()) {
return new GoogleCloudStorageRecordingUploader();
}
return new DummyRecordingUploader(); return new DummyRecordingUploader();
} }

View File

@ -190,6 +190,10 @@ public class OpenviduConfig {
private String dotenvPath; private String dotenvPath;
private boolean gcpRecordingStorageEnabled;
private String gcpStorageBucketName;
// Derived properties // Derived properties
public static String finalUrl; public static String finalUrl;
@ -338,6 +342,14 @@ public class OpenviduConfig {
return dotenvPath; return dotenvPath;
} }
public boolean isGcpRecordingStorageEnabled() {
return gcpRecordingStorageEnabled;
}
public String getGcpStorageBucketName() {
return gcpStorageBucketName;
}
// Derived properties methods // Derived properties methods
public String getSpringProfile() { public String getSpringProfile() {
@ -533,6 +545,10 @@ public class OpenviduConfig {
openviduForcedCodec = asEnumValue("OPENVIDU_STREAMS_FORCED_VIDEO_CODEC", VideoCodec.class); openviduForcedCodec = asEnumValue("OPENVIDU_STREAMS_FORCED_VIDEO_CODEC", VideoCodec.class);
openviduAllowTranscoding = asBoolean("OPENVIDU_STREAMS_ALLOW_TRANSCODING"); openviduAllowTranscoding = asBoolean("OPENVIDU_STREAMS_ALLOW_TRANSCODING");
gcpRecordingStorageEnabled = asBoolean("OPENVIDU_GCP_RECORDING_STORAGE_ENABLED");
gcpStorageBucketName = gcpRecordingStorageEnabled ? asNonEmptyString("OPENVIDU_GCP_STORAGE_BUCKET_NAME")
: null;
kmsUrisList = checkKmsUris(); kmsUrisList = checkKmsUris();
checkCoturnIp(); checkCoturnIp();

View File

@ -0,0 +1,68 @@
package io.openvidu.server.recording;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import io.openvidu.server.config.OpenviduConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class GoogleCloudStorageRecordingUploader implements RecordingUploader {
private static final Logger log = LoggerFactory.getLogger(GoogleCloudStorageRecordingUploader.class);
@Autowired
private OpenviduConfig config;
@Autowired
private Storage gcpStorage;
private final Set<String> recordingsBeingCurrentlyUploaded = ConcurrentHashMap.newKeySet();
@Override
public void uploadRecording(Recording recording, Runnable successCallback, Runnable errorCallback) {
recordingsBeingCurrentlyUploaded.add(recording.getId());
String bucketName = config.getGcpStorageBucketName();
BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, recording.getName())).build();
String filePath = getComposedRecordingLocalFilePath(recording);
try {
gcpStorage.create(blobInfo, Files.readAllBytes(Paths.get(filePath)));
} catch (StorageException | IOException e) {
log.error(e.getMessage(), e);
errorCallback.run();
} finally {
recordingsBeingCurrentlyUploaded.remove(recording.getId());
}
successCallback.run();
}
private String getComposedRecordingLocalFilePath(Recording recording) {
// Audio-only recordings are in WEBM file format
String fileExt = recording.hasVideo() ? ".mp4" : ".webm";
return config.getOpenViduRecordingPath() + "/" + recording.getId() + "/" + recording.getName() + fileExt;
}
// Prevent uploading recordings from being retrieved from REST API with "ready"
// status. This will force their status back to "stopped" on GET until upload
// process has finished
@Override
public void storeAsUploadingRecording(String recordingId) {
recordingsBeingCurrentlyUploaded.add(recordingId);
}
@Override
public boolean isBeingUploaded(String recordingId) {
return recordingsBeingCurrentlyUploaded.contains(recordingId);
}
}