mirror of https://github.com/OpenVidu/openvidu.git
openvidu server: Experimental parameter to enable GPU in recording containers. Add custom recording image configuration parameter.
parent
a22ceb2d84
commit
ad1dca04cb
|
@ -111,6 +111,8 @@ public class OpenviduConfig {
|
|||
|
||||
protected Map<String, ?> propertiesSource;
|
||||
|
||||
public static final String DEFAULT_RECORDING_IMAGE_REPO = "openvidu/openvidu-recording";
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
@ -141,6 +143,10 @@ public class OpenviduConfig {
|
|||
|
||||
private String openviduRecordingVersion;
|
||||
|
||||
private String openviduRecordingImageRepo;
|
||||
|
||||
private boolean openviduRecordingEnableGPU;
|
||||
|
||||
private Integer openviduStreamsVideoMaxRecvBandwidth;
|
||||
|
||||
private Integer openviduStreamsVideoMinRecvBandwidth;
|
||||
|
@ -292,6 +298,14 @@ public class OpenviduConfig {
|
|||
return this.openviduRecordingAutostopTimeout;
|
||||
}
|
||||
|
||||
public String getOpenviduRecordingImageRepo() {
|
||||
return this.openviduRecordingImageRepo;
|
||||
}
|
||||
|
||||
public boolean isOpenviduRecordingGPUEnabled() {
|
||||
return this.openviduRecordingEnableGPU;
|
||||
}
|
||||
|
||||
public int getVideoMaxRecvBandwidth() {
|
||||
return this.openviduStreamsVideoMaxRecvBandwidth;
|
||||
}
|
||||
|
@ -507,7 +521,8 @@ public class OpenviduConfig {
|
|||
|
||||
protected List<String> getNonUserProperties() {
|
||||
return Arrays.asList("server.port", "SERVER_PORT", "DOTENV_PATH", "COTURN_IP", "COTURN_REDIS_IP",
|
||||
"COTURN_REDIS_DBNAME", "COTURN_REDIS_PASSWORD", "COTURN_REDIS_CONNECT_TIMEOUT");
|
||||
"COTURN_REDIS_DBNAME", "COTURN_REDIS_PASSWORD", "COTURN_REDIS_CONNECT_TIMEOUT",
|
||||
"COTURN_INTERNAL_RELAY", "OPENVIDU_RECORDING_IMAGE", "OPENVIDU_RECORDING_ENABLE_GPU");
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
@ -549,6 +564,8 @@ public class OpenviduConfig {
|
|||
openviduRecordingComposedBasicauth = asBoolean("OPENVIDU_RECORDING_COMPOSED_BASICAUTH");
|
||||
openviduRecordingVersion = asNonEmptyString("OPENVIDU_RECORDING_VERSION");
|
||||
openviduRecordingComposedUrl = asOptionalURL("OPENVIDU_RECORDING_COMPOSED_URL");
|
||||
openviduRecordingEnableGPU = asBoolean("OPENVIDU_RECORDING_ENABLE_GPU");
|
||||
configureRecordingImage("OPENVIDU_RECORDING_IMAGE");
|
||||
checkOpenviduRecordingNotification();
|
||||
|
||||
openviduStreamsVideoMaxRecvBandwidth = asNonNegativeInteger("OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH");
|
||||
|
@ -1018,6 +1035,24 @@ public class OpenviduConfig {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void configureRecordingImage(String recordingImageProperty) {
|
||||
String configuredImage = asOptionalString(recordingImageProperty);
|
||||
if (configuredImage == null || configuredImage.isEmpty()) {
|
||||
openviduRecordingImageRepo = DEFAULT_RECORDING_IMAGE_REPO;
|
||||
} else {
|
||||
String[] customImageSplit = configuredImage.split(":");
|
||||
if (customImageSplit.length != 2) {
|
||||
addError(recordingImageProperty, "The docker image configured is not valid. " +
|
||||
"This parameter must have this format: '<image>:<tag>'");
|
||||
} else {
|
||||
String customImageName = customImageSplit[0];
|
||||
String customVersion = customImageSplit[1];
|
||||
openviduRecordingImageRepo = customImageName;
|
||||
openviduRecordingVersion = customVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> loadMediaNodePublicIps(String propertyName) {
|
||||
String mediaNodesPublicIpsRaw = this.asOptionalString(propertyName);
|
||||
final Map<String, String> mediaNodesPublicIps = new HashMap<>();
|
||||
|
|
|
@ -219,7 +219,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
|
|||
|
||||
String containerId = null;
|
||||
try {
|
||||
final String container = RecordingManager.IMAGE_NAME + ":" + openviduConfig.getOpenViduRecordingVersion();
|
||||
final String container = openviduConfig.getOpenviduRecordingImageRepo() + ":" + openviduConfig.getOpenViduRecordingVersion();
|
||||
final String containerName = "recording_" + session.getSessionId();
|
||||
Volume volume1 = new Volume("/recordings");
|
||||
List<Volume> volumes = new ArrayList<>();
|
||||
|
@ -228,7 +228,8 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
|
|||
List<Bind> binds = new ArrayList<>();
|
||||
binds.add(bind1);
|
||||
containerId = dockerManager.runContainer(properties.mediaNode(), container, containerName, null, volumes,
|
||||
binds, "host", envs, null, properties.shmSize(), false, null);
|
||||
binds, "host", envs, null, properties.shmSize(), false, null,
|
||||
openviduConfig.isOpenviduRecordingGPUEnabled());
|
||||
containers.put(containerId, containerName);
|
||||
this.sessionsContainers.put(session.getSessionId(), containerId);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -164,7 +164,7 @@ public class ComposedRecordingService extends RecordingService {
|
|||
|
||||
String containerId;
|
||||
try {
|
||||
final String container = RecordingManager.IMAGE_NAME + ":" + openviduConfig.getOpenViduRecordingVersion();
|
||||
final String container = openviduConfig.getOpenviduRecordingImageRepo() + ":" + openviduConfig.getOpenViduRecordingVersion();
|
||||
final String containerName = "recording_" + recording.getId();
|
||||
Volume volume1 = new Volume("/recordings");
|
||||
List<Volume> volumes = new ArrayList<>();
|
||||
|
@ -173,7 +173,8 @@ public class ComposedRecordingService extends RecordingService {
|
|||
List<Bind> binds = new ArrayList<>();
|
||||
binds.add(bind1);
|
||||
containerId = dockerManager.runContainer(properties.mediaNode(), container, containerName, null, volumes,
|
||||
binds, "host", envs, null, properties.shmSize(), false, null);
|
||||
binds, "host", envs, null, properties.shmSize(), false, null,
|
||||
openviduConfig.isOpenviduRecordingGPUEnabled());
|
||||
containers.put(containerId, containerName);
|
||||
} catch (Exception e) {
|
||||
this.cleanRecordingMaps(recording);
|
||||
|
@ -605,4 +606,4 @@ public class ComposedRecordingService extends RecordingService {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,8 +128,6 @@ public class RecordingManager {
|
|||
private ScheduledExecutorService automaticRecordingStopExecutor = Executors
|
||||
.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
public static final String IMAGE_NAME = "openvidu/openvidu-recording";
|
||||
|
||||
private static final List<EndReason> LAST_PARTICIPANT_LEFT_REASONS = Arrays
|
||||
.asList(new EndReason[] { EndReason.disconnect, EndReason.forceDisconnectByUser,
|
||||
EndReason.forceDisconnectByServer, EndReason.networkDisconnect });
|
||||
|
@ -187,7 +185,7 @@ public class RecordingManager {
|
|||
}
|
||||
|
||||
// Clean any stranded openvidu/openvidu-recording container on startup
|
||||
dockMng.cleanStrandedContainers(RecordingManager.IMAGE_NAME);
|
||||
dockMng.cleanStrandedContainers(openviduConfig.getOpenviduRecordingImageRepo());
|
||||
}
|
||||
|
||||
public void checkRecordingRequirements(String openviduRecordingPath, String openviduRecordingCustomLayout)
|
||||
|
@ -223,7 +221,7 @@ public class RecordingManager {
|
|||
log.info("Recording module required: Downloading openvidu/openvidu-recording:"
|
||||
+ openviduConfig.getOpenViduRecordingVersion() + " Docker image (350MB aprox)");
|
||||
|
||||
if (dockMng.dockerImageExistsLocally(IMAGE_NAME + ":" + openviduConfig.getOpenViduRecordingVersion())) {
|
||||
if (dockMng.dockerImageExistsLocally(openviduConfig.getOpenviduRecordingImageRepo() + ":" + openviduConfig.getOpenViduRecordingVersion())) {
|
||||
log.info("Docker image already exists locally");
|
||||
} else {
|
||||
Thread t = new Thread(() -> {
|
||||
|
@ -241,9 +239,9 @@ public class RecordingManager {
|
|||
});
|
||||
t.start();
|
||||
try {
|
||||
dockMng.downloadDockerImage(IMAGE_NAME + ":" + openviduConfig.getOpenViduRecordingVersion(), 600);
|
||||
dockMng.downloadDockerImage(openviduConfig.getOpenviduRecordingImageRepo() + ":" + openviduConfig.getOpenViduRecordingVersion(), 600);
|
||||
} catch (Exception e) {
|
||||
log.error("Error downloading docker image {}:{}", IMAGE_NAME,
|
||||
log.error("Error downloading docker image {}:{}", openviduConfig.getOpenviduRecordingImageRepo(),
|
||||
openviduConfig.getOpenViduRecordingVersion());
|
||||
}
|
||||
t.interrupt();
|
||||
|
|
|
@ -13,7 +13,7 @@ public interface DockerManager {
|
|||
|
||||
public String runContainer(String mediaNodeId, String image, String containerName, String user,
|
||||
List<Volume> volumes, List<Bind> binds, String networkMode, List<String> envs, List<String> command,
|
||||
Long shmSize, boolean privileged, Map<String, String> labels) throws Exception;
|
||||
Long shmSize, boolean privileged, Map<String, String> labels, boolean enableGPU) throws Exception;
|
||||
|
||||
public void removeContainer(String mediaNodeId, String containerId, boolean force);
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import javax.ws.rs.ProcessingException;
|
||||
|
||||
import com.github.dockerjava.api.model.*;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -39,10 +41,6 @@ import com.github.dockerjava.api.exception.ConflictException;
|
|||
import com.github.dockerjava.api.exception.DockerClientException;
|
||||
import com.github.dockerjava.api.exception.InternalServerErrorException;
|
||||
import com.github.dockerjava.api.exception.NotFoundException;
|
||||
import com.github.dockerjava.api.model.Bind;
|
||||
import com.github.dockerjava.api.model.Container;
|
||||
import com.github.dockerjava.api.model.HostConfig;
|
||||
import com.github.dockerjava.api.model.Volume;
|
||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||
import com.github.dockerjava.core.DockerClientBuilder;
|
||||
import com.github.dockerjava.core.DockerClientConfig;
|
||||
|
@ -118,7 +116,7 @@ public class LocalDockerManager implements DockerManager {
|
|||
@Override
|
||||
public String runContainer(String mediaNodeId, String image, String containerName, String user,
|
||||
List<Volume> volumes, List<Bind> binds, String networkMode, List<String> envs, List<String> command,
|
||||
Long shmSize, boolean privileged, Map<String, String> labels) throws Exception {
|
||||
Long shmSize, boolean privileged, Map<String, String> labels, boolean enableGPU) throws Exception {
|
||||
|
||||
CreateContainerCmd cmd = dockerClient.createContainerCmd(image).withEnv(envs);
|
||||
if (containerName != null) {
|
||||
|
@ -133,6 +131,15 @@ public class LocalDockerManager implements DockerManager {
|
|||
if (shmSize != null) {
|
||||
hostConfig.withShmSize(shmSize);
|
||||
}
|
||||
|
||||
if (enableGPU) {
|
||||
DeviceRequest deviceRequest = new DeviceRequest()
|
||||
.withCapabilities(ImmutableList.of(ImmutableList.of("gpu")))
|
||||
.withCount(-1)
|
||||
.withOptions(null);
|
||||
hostConfig.withDeviceRequests(ImmutableList.of(deviceRequest));
|
||||
}
|
||||
|
||||
if (volumes != null) {
|
||||
cmd.withVolumes(volumes);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ OPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/custom-layout
|
|||
OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT=120
|
||||
OPENVIDU_RECORDING_COMPOSED_URL=
|
||||
OPENVIDU_RECORDING_COMPOSED_BASICAUTH=true
|
||||
OPENVIDU_RECORDING_IMAGE=
|
||||
OPENVIDU_RECORDING_ENABLE_GPU=false
|
||||
|
||||
OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH=1000
|
||||
OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH=300
|
||||
|
|
Loading…
Reference in New Issue