Skip to content
Snippets Groups Projects
Commit f4954dd8 authored by gnaegi's avatar gnaegi
Browse files

OO-725 rename type to resolution, use getter/setter conventions, missing i18n...

OO-725 rename type to resolution, use getter/setter conventions, missing i18n keys, fix modul initialization
parent a4f0e588
No related branches found
No related tags found
No related merge requests found
Showing
with 170 additions and 101 deletions
...@@ -148,11 +148,14 @@ public interface VideoManager { ...@@ -148,11 +148,14 @@ public interface VideoManager {
* Create and add a new transcoding version to the video resource. The * Create and add a new transcoding version to the video resource. The
* version is set to "isTransforming". * version is set to "isTransforming".
* *
* @param video The video resource * @param video
* @param resolution The resolution for the transcoding process * The video resource
* @param resolution
* The resolution for the transcoding process. This is the height
* of the target video size (e.g. 720 for 720p resolution)
* @return VideoQualityVersion for this new version * @return VideoQualityVersion for this new version
*/ */
public abstract VideoQualityVersion addNewVersionForTranscoding(OLATResource video, String resolution); public abstract VideoQualityVersion addNewVersionForTranscoding(OLATResource video, int resolution);
/** /**
* Update an already existing version or add as new version. * Update an already existing version or add as new version.
......
...@@ -19,11 +19,18 @@ ...@@ -19,11 +19,18 @@
*/ */
package org.olat.modules.video; package org.olat.modules.video;
import java.util.Arrays;
import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.CoordinatorManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
...@@ -39,8 +46,6 @@ public class VideoModule extends AbstractSpringModule { ...@@ -39,8 +46,6 @@ public class VideoModule extends AbstractSpringModule {
private static final String VIDEO_ENABLED = "video.enabled"; private static final String VIDEO_ENABLED = "video.enabled";
private static final String VIDEOCOURSENODE_ENABLED = "video.coursenode.enabled"; private static final String VIDEOCOURSENODE_ENABLED = "video.coursenode.enabled";
private static final String VIDEOTRANSCODING_ENABLED = "video.transcoding.enabled"; private static final String VIDEOTRANSCODING_ENABLED = "video.transcoding.enabled";
@Value("${video.transcoding.provider:handbrake}")
private String transcodingProvider;
@Value("${video.enabled:true}") @Value("${video.enabled:true}")
private boolean enabled; private boolean enabled;
...@@ -48,7 +53,18 @@ public class VideoModule extends AbstractSpringModule { ...@@ -48,7 +53,18 @@ public class VideoModule extends AbstractSpringModule {
private boolean coursenodeEnabled; private boolean coursenodeEnabled;
@Value("${video.transcoding.enabled:false}") @Value("${video.transcoding.enabled:false}")
private boolean transcodingEnabled; private boolean transcodingEnabled;
@Value("${video.transcoding.resolutions}")
private int[] transcodingResolutions;
@Value("${video.transcoding.taskset.cpuconfig}")
private String transcodingTasksetConfig;
@Bean
public static ConversionService conversionService() {
// needed to create the transcodingResolutions property by spring
return new DefaultFormattingConversionService();
}
private static final OLog log = Tracing.createLoggerFor(VideoModule.class);
@Autowired @Autowired
public VideoModule(CoordinatorManager coordinatorManager) { public VideoModule(CoordinatorManager coordinatorManager) {
...@@ -72,7 +88,33 @@ public class VideoModule extends AbstractSpringModule { ...@@ -72,7 +88,33 @@ public class VideoModule extends AbstractSpringModule {
transcodingEnabled = "true".equals(enabledTranscodingObj); transcodingEnabled = "true".equals(enabledTranscodingObj);
} }
log.info("video.enabled=" + isEnabled());
log.info("video.coursenode.enabled=" + isCoursenodeEnabled());
log.info("video.transcoding.enabled=" + isTranscodingEnabled());
log.info("video.transcoding.resolutions=" + Arrays.toString(getTranscodingResolutions()));
log.info("video.transcoding.taskset.cpuconfig=" + getTranscodingTasksetConfig());
}
/**
* @return Array of transcoding resolutions. The values represent the target
* height of the transcoded video, 1080 for 1080p video size etc.
*/
public int[] getTranscodingResolutions() {
return transcodingResolutions;
} }
/**
* @return null to indicate that taskset is disabled or the -c options to control the number of cores, e.g. "0,1"
*/
public String getTranscodingTasksetConfig() {
if (StringHelper.containsNonWhitespace(transcodingTasksetConfig)) {
return transcodingTasksetConfig.trim();
} else {
return null;
}
}
@Override @Override
protected void initFromChangedProperties() { protected void initFromChangedProperties() {
init(); init();
...@@ -107,5 +149,6 @@ public class VideoModule extends AbstractSpringModule { ...@@ -107,5 +149,6 @@ public class VideoModule extends AbstractSpringModule {
public void setTranscodingEnabled(boolean transcodingEnabled) { public void setTranscodingEnabled(boolean transcodingEnabled) {
this.transcodingEnabled = transcodingEnabled; this.transcodingEnabled = transcodingEnabled;
setStringProperty(VIDEOTRANSCODING_ENABLED, Boolean.toString(transcodingEnabled), true); setStringProperty(VIDEOTRANSCODING_ENABLED, Boolean.toString(transcodingEnabled), true);
//TODO: check all video resources if there are missing versions
} }
} }
...@@ -40,7 +40,6 @@ import javax.imageio.ImageIO; ...@@ -40,7 +40,6 @@ import javax.imageio.ImageIO;
import org.jcodec.api.FrameGrab; import org.jcodec.api.FrameGrab;
import org.jcodec.common.FileChannelWrapper; import org.jcodec.common.FileChannelWrapper;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.services.image.Size; import org.olat.core.commons.services.image.Size;
import org.olat.core.commons.services.taskexecutor.TaskExecutorManager; import org.olat.core.commons.services.taskexecutor.TaskExecutorManager;
import org.olat.core.commons.services.video.MovieService; import org.olat.core.commons.services.video.MovieService;
...@@ -88,6 +87,8 @@ public class VideoManagerImpl implements VideoManager { ...@@ -88,6 +87,8 @@ public class VideoManagerImpl implements VideoManager {
private VideoModule videoModule; private VideoModule videoModule;
@Autowired @Autowired
private RepositoryManager repositoryManager; private RepositoryManager repositoryManager;
@Autowired
private TaskExecutorManager taskManager;
private static final OLog log = Tracing.createLoggerFor(VideoManagerImpl.class); private static final OLog log = Tracing.createLoggerFor(VideoManagerImpl.class);
...@@ -327,14 +328,13 @@ public class VideoManagerImpl implements VideoManager { ...@@ -327,14 +328,13 @@ public class VideoManagerImpl implements VideoManager {
//TODO: check for existing version, add option to force rebuild of all versions //TODO: check for existing version, add option to force rebuild of all versions
Size size = getVideoSize(video); Size size = getVideoSize(video);
int height = size.getHeight(); int height = size.getHeight();
TaskExecutorManager taskManager = CoreSpringFactory.getImpl(TaskExecutorManager.class); //TODO: GUI to admin console to manage transcoding resolutions
//TODO: add to module and admin console which version to generate int[] resolutions = videoModule.getTranscodingResolutions();
int[] resolutions = {1080, 720, 480, 360, 240, 144};
for (int resolution : resolutions) { for (int resolution : resolutions) {
if (height < resolution) { if (height < resolution) {
continue; continue;
} }
VideoQualityVersion version = addNewVersionForTranscoding(video, Integer.toString(resolution)); VideoQualityVersion version = addNewVersionForTranscoding(video, resolution);
VideoTranscodingTask task = new VideoTranscodingTask(video, version); VideoTranscodingTask task = new VideoTranscodingTask(video, version);
taskManager.execute(task, null, video, null, new Date()); taskManager.execute(task, null, video, null, new Date());
} }
...@@ -554,10 +554,10 @@ public class VideoManagerImpl implements VideoManager { ...@@ -554,10 +554,10 @@ public class VideoManagerImpl implements VideoManager {
@Override @Override
public VideoQualityVersion addNewVersionForTranscoding(OLATResource video, String resolution) { public VideoQualityVersion addNewVersionForTranscoding(OLATResource video, int resolution) {
List<VideoQualityVersion> versions = getQualityVersions(video); List<VideoQualityVersion> versions = getQualityVersions(video);
VideoQualityVersion version = new VideoQualityVersion(resolution, null, null, VideoManagerImpl.FILETYPE_MP4); VideoQualityVersion version = new VideoQualityVersion(resolution, null, null, VideoManagerImpl.FILETYPE_MP4);
version.setIsTransforming(true); version.setTranscodingStatus(VideoQualityVersion.TRANSCODING_STATUS_WAITING);
versions.add(version); versions.add(version);
// Store on disk // Store on disk
VFSContainer optimizedDataContainer = getOptimizedDataContainer(video); VFSContainer optimizedDataContainer = getOptimizedDataContainer(video);
...@@ -573,12 +573,11 @@ public class VideoManagerImpl implements VideoManager { ...@@ -573,12 +573,11 @@ public class VideoManagerImpl implements VideoManager {
List<VideoQualityVersion> versions = getQualityVersions(video); List<VideoQualityVersion> versions = getQualityVersions(video);
boolean found = false; boolean found = false;
for (VideoQualityVersion existingVersion : versions) { for (VideoQualityVersion existingVersion : versions) {
if (updatedVersion.getType().equals(existingVersion.getType())) { if (updatedVersion.getResolution() == existingVersion.getResolution()) {
// update properties // update properties
existingVersion.setDimension(updatedVersion.getDimension()); existingVersion.setDimension(updatedVersion.getDimension());
existingVersion.setFileSize(updatedVersion.getFileSize()); existingVersion.setFileSize(updatedVersion.getFileSize());
existingVersion.setFormat(updatedVersion.getFormat()); existingVersion.setFormat(updatedVersion.getFormat());
existingVersion.setIsTransforming(updatedVersion.getIsTransforming());
existingVersion.setTranscodingStatus(updatedVersion.getTranscodingStatus()); existingVersion.setTranscodingStatus(updatedVersion.getTranscodingStatus());
found = true; found = true;
break; break;
......
...@@ -30,8 +30,6 @@ import org.olat.core.CoreSpringFactory; ...@@ -30,8 +30,6 @@ import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.services.image.Size; import org.olat.core.commons.services.image.Size;
import org.olat.core.commons.services.taskexecutor.LongRunnable; import org.olat.core.commons.services.taskexecutor.LongRunnable;
import org.olat.core.commons.services.taskexecutor.Sequential; import org.olat.core.commons.services.taskexecutor.Sequential;
import org.olat.core.commons.services.taskexecutor.Task;
import org.olat.core.commons.services.taskexecutor.TaskAwareRunnable;
import org.olat.core.commons.services.video.MovieService; import org.olat.core.commons.services.video.MovieService;
import org.olat.core.logging.OLog; import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
...@@ -39,49 +37,52 @@ import org.olat.core.util.Formatter; ...@@ -39,49 +37,52 @@ import org.olat.core.util.Formatter;
import org.olat.core.util.vfs.LocalFileImpl; import org.olat.core.util.vfs.LocalFileImpl;
import org.olat.fileresource.FileResourceManager; import org.olat.fileresource.FileResourceManager;
import org.olat.modules.video.VideoManager; import org.olat.modules.video.VideoManager;
import org.olat.modules.video.VideoModule;
import org.olat.modules.video.model.VideoQualityVersion; import org.olat.modules.video.model.VideoQualityVersion;
import org.olat.resource.OLATResource; import org.olat.resource.OLATResource;
/** /**
* This task implements transcoding of a single video file using the Handbrake CLI.
*
* Initial date: 22.04.2016<br> * Initial date: 22.04.2016<br>
* @author gnaegi, gnaegi@frentix.com, http://www.frentix.com * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com
* *
*/ */
public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Sequential { public class VideoTranscodingTask implements LongRunnable, Sequential {
private static final long serialVersionUID = 2982868860465334552L;
private static final OLog log = Tracing.createLoggerFor(VideoTranscodingTask.class); private static final OLog log = Tracing.createLoggerFor(VideoTranscodingTask.class);
private transient Task task;
private OLATResource video; private OLATResource video;
private String resolution;
private VideoQualityVersion version; private VideoQualityVersion version;
private File transcodedFile; private File transcodedFile;
/**
*
* @param video
* @param version
*/
VideoTranscodingTask(OLATResource video, VideoQualityVersion version) { VideoTranscodingTask(OLATResource video, VideoQualityVersion version) {
this.video = video; this.video = video;
this.version = version; this.version = version;
this.resolution = version.getType();
}
@Override
public void setTask(Task task) {
this.task = task;
} }
@Override @Override
public void run() { public void run() {
VideoModule videoModule = CoreSpringFactory.getImpl(VideoModule.class);
VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class); VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
File masterFile = videoManager.getVideoFile(video); File masterFile = videoManager.getVideoFile(video);
FileResourceManager fileResourceManager = CoreSpringFactory.getImpl(FileResourceManager.class); FileResourceManager fileResourceManager = CoreSpringFactory.getImpl(FileResourceManager.class);
File videoResourceFileroot = fileResourceManager.getFileResourceRoot(video); File videoResourceFileroot = fileResourceManager.getFileResourceRoot(video);
File optimizedFolder = new File(videoResourceFileroot, VideoManagerImpl.DIRNAME_OPTIMIZED_VIDEO_DATA); File optimizedFolder = new File(videoResourceFileroot, VideoManagerImpl.DIRNAME_OPTIMIZED_VIDEO_DATA);
transcodedFile = new File(optimizedFolder, resolution + masterFile.getName()); transcodedFile = new File(optimizedFolder, Integer.toString(version.getResolution()) + masterFile.getName());
ArrayList<String> cmd = new ArrayList<String>(); ArrayList<String> cmd = new ArrayList<>();
//TODO make configurable (taskset on osx not available) String tasksetConfig = videoModule.getTranscodingTasksetConfig();
// cmd.add("taskset"); if (tasksetConfig != null) {
// cmd.add("-c"); cmd.add("taskset");
// cmd.add("0,1"); cmd.add("-c");
cmd.add(tasksetConfig);
}
cmd.add("HandBrakeCLI"); cmd.add("HandBrakeCLI");
cmd.add("-i"); cmd.add("-i");
cmd.add(masterFile.getAbsolutePath()); cmd.add(masterFile.getAbsolutePath());
...@@ -91,7 +92,7 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se ...@@ -91,7 +92,7 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se
cmd.add("--preset"); cmd.add("--preset");
cmd.add("Normal"); cmd.add("Normal");
cmd.add("--height"); cmd.add("--height");
cmd.add(resolution); cmd.add(Integer.toString(version.getResolution()));
cmd.add("--deinterlace"); cmd.add("--deinterlace");
cmd.add("--crop"); cmd.add("--crop");
cmd.add("0:0:0:0"); cmd.add("0:0:0:0");
...@@ -110,11 +111,15 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se ...@@ -110,11 +111,15 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se
process.destroy(); process.destroy();
process = null; process = null;
} }
//TODO: remove version file, cleanup //TODO: remove version file, cleanup, remove job
} }
} }
/**
* Internal helper to deal with the handbrake console output and update the transcoding metadata
* @param proc
*/
private final void executeProcess(Process proc) { private final void executeProcess(Process proc) {
VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class); VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
...@@ -122,6 +127,7 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se ...@@ -122,6 +127,7 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
String line; String line;
// Read from standard input and parse percentages of transcoding process
InputStream stdout = proc.getInputStream(); InputStream stdout = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdout); InputStreamReader isr = new InputStreamReader(stdout);
BufferedReader br = new BufferedReader(isr); BufferedReader br = new BufferedReader(isr);
...@@ -148,7 +154,9 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se ...@@ -148,7 +154,9 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se
// //
} }
InputStream stderr = proc.getErrorStream(); // Read and ignore errors, Handbrake outputs a lot info on startup. Only
// display errors in debug level
InputStream stderr = proc.getErrorStream();
InputStreamReader iserr = new InputStreamReader(stderr); InputStreamReader iserr = new InputStreamReader(stderr);
BufferedReader berr = new BufferedReader(iserr); BufferedReader berr = new BufferedReader(iserr);
line = null; line = null;
...@@ -162,22 +170,19 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se ...@@ -162,22 +170,19 @@ public class VideoTranscodingTask implements LongRunnable, TaskAwareRunnable, Se
} }
try { try {
// On finish, update metadata file
int exitValue = proc.waitFor(); int exitValue = proc.waitFor();
if (exitValue == 0) { if (exitValue == 0) {
// done, update metadata file
MovieService movieService = CoreSpringFactory.getImpl(MovieService.class); MovieService movieService = CoreSpringFactory.getImpl(MovieService.class);
Size videoSize = movieService.getSize(new LocalFileImpl(transcodedFile), VideoManagerImpl.FILETYPE_MP4); Size videoSize = movieService.getSize(new LocalFileImpl(transcodedFile), VideoManagerImpl.FILETYPE_MP4);
version.setDimension(videoSize); version.setDimension(videoSize);
version.setFileSize(Formatter.formatBytes(transcodedFile.length())); version.setFileSize(Formatter.formatBytes(transcodedFile.length()));
version.setIsTransforming(false); version.setTranscodingStatus(VideoQualityVersion.TRANSCODING_STATUS_DONE);
version.setTranscodingStatus(100);
videoManager.updateVersion(video, version); videoManager.updateVersion(video, version);
//TODO: do I need to remove task from DB?
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
// //
//TODO: do I need to remove task from DB?
} }
} }
} }
...@@ -22,33 +22,46 @@ package org.olat.modules.video.model; ...@@ -22,33 +22,46 @@ package org.olat.modules.video.model;
import org.olat.core.commons.services.image.Size; import org.olat.core.commons.services.image.Size;
/** /**
* Model of quality-versions to save in a seperate xml-file * Model of quality-versions to save in a separate xml-file
* *
* @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com * @author Dirk Furrer, dirk.furrer@frentix.com, http://www.frentix.com
* *
*/ */
public class VideoQualityVersion{ public class VideoQualityVersion {
public static final int TRANSCODING_STATUS_WAITING = 0;
public static final int TRANSCODING_STATUS_DONE = 100;
// Properties // Properties
private String type; private int resolution;
private String fileSize; private String fileSize;
private Size dimension; private Size dimension;
private String format; private String format;
private boolean isTransforming;
private int transcodingStatus = 0; private int transcodingStatus = 0;
public VideoQualityVersion(String type, String fileSize, Size dimension, String format){ public VideoQualityVersion(int resolution, String fileSize, Size dimension, String format) {
this.type = type; this.resolution = resolution;
this.fileSize = fileSize; this.fileSize = fileSize;
this.dimension = dimension; this.dimension = dimension;
this.format = format; this.format = format;
} }
public String getType() { /**
return type; * The resolution of the transcoded video. The resolution if defined using
* the video height. E.g. a 1080p video has a resolution of 1080
*
* @return The height of the transcoded video
*/
public int getResolution() {
return resolution;
} }
public void setType(String type) { /**
this.type = type; * @param resolution
* The resolution if defined using the video height. E.g. a 1080p
* video has a resolution of 1080
*/
public void setResolution(int resolution) {
this.resolution = resolution;
} }
public String getFileSize() { public String getFileSize() {
...@@ -74,15 +87,7 @@ public class VideoQualityVersion{ ...@@ -74,15 +87,7 @@ public class VideoQualityVersion{
public void setFormat(String format) { public void setFormat(String format) {
this.format = format; this.format = format;
} }
public boolean getIsTransforming() {
return isTransforming;
}
public void setIsTransforming(boolean isTranscoding) {
this.isTransforming = isTranscoding;
}
/** /**
* @return 0: transcoding has not yet startet; 100: transcoding is done * @return 0: transcoding has not yet startet; 100: transcoding is done
*/ */
...@@ -91,10 +96,14 @@ public class VideoQualityVersion{ ...@@ -91,10 +96,14 @@ public class VideoQualityVersion{
} }
/** /**
* Set transcoding status in percent * Set transcoding status in percent (0-100)
*
* @param status * @param status
*/ */
public void setTranscodingStatus(int status) { public void setTranscodingStatus(int status) {
if (status > 100 || status < 0) {
status = TRANSCODING_STATUS_DONE;
}
this.transcodingStatus = status; this.transcodingStatus = status;
} }
} }
\ No newline at end of file
...@@ -31,7 +31,7 @@ import org.olat.core.gui.components.form.flexible.elements.FormLink; ...@@ -31,7 +31,7 @@ import org.olat.core.gui.components.form.flexible.elements.FormLink;
*/ */
public class QualityTableRow { public class QualityTableRow {
String type; String resolution;
String dimension; String dimension;
String size; String size;
String format; String format;
...@@ -39,8 +39,8 @@ public class QualityTableRow { ...@@ -39,8 +39,8 @@ public class QualityTableRow {
protected FormUIFactory uifactory = FormUIFactory.getInstance(); protected FormUIFactory uifactory = FormUIFactory.getInstance();
public QualityTableRow(String type, String dimension, String size, String format, FormLink viewLink) { public QualityTableRow(String resolution, String dimension, String size, String format, FormLink viewLink) {
this.type = type; this.resolution = resolution;
this.dimension = dimension; this.dimension = dimension;
this.size = size; this.size = size;
this.format = format; this.format = format;
...@@ -49,12 +49,12 @@ public class QualityTableRow { ...@@ -49,12 +49,12 @@ public class QualityTableRow {
} }
public String getType() { public String getResolution() {
return type; return resolution;
} }
public void setType(String type) { public void setType(String type) {
this.type = type; this.resolution = type;
} }
public String getDimension() { public String getDimension() {
......
...@@ -80,7 +80,7 @@ public class VideoQualityTableFormController extends FormBasicController { ...@@ -80,7 +80,7 @@ public class VideoQualityTableFormController extends FormBasicController {
formLayout.add(generalCont); formLayout.add(generalCont);
FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.type.i18nKey(), QualityTableCols.type.ordinal(), true, QualityTableCols.type.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.resolution.i18nKey(), QualityTableCols.resolution.ordinal(), true, QualityTableCols.resolution.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.dimension.i18nKey(), QualityTableCols.dimension.ordinal(), true, QualityTableCols.dimension.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.dimension.i18nKey(), QualityTableCols.dimension.ordinal(), true, QualityTableCols.dimension.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.size.i18nKey(), QualityTableCols.size.ordinal(), true, QualityTableCols.size.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.size.i18nKey(), QualityTableCols.size.ordinal(), true, QualityTableCols.size.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.format.i18nKey(), QualityTableCols.format.ordinal(), true, QualityTableCols.format.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, QualityTableCols.format.i18nKey(), QualityTableCols.format.ordinal(), true, QualityTableCols.format.name()));
...@@ -92,11 +92,11 @@ public class VideoQualityTableFormController extends FormBasicController { ...@@ -92,11 +92,11 @@ public class VideoQualityTableFormController extends FormBasicController {
Size origSize = videoManager.getVideoSize(videoResource); Size origSize = videoManager.getVideoSize(videoResource);
viewButton = uifactory.addFormLink("view", "viewQuality", "quality.view", "qulaity.view", null, Link.LINK); viewButton = uifactory.addFormLink("view", "viewQuality", "quality.view", "qulaity.view", null, Link.LINK);
rows.add(new QualityTableRow("original", origSize.getWidth() +"x"+ origSize.getHeight(), FileUtils.byteCountToDisplaySize(videoManager.getVideoFile(videoResource).length()), "mp4",viewButton)); rows.add(new QualityTableRow(translate("quality.resolution.original"), origSize.getWidth() +"x"+ origSize.getHeight(), FileUtils.byteCountToDisplaySize(videoManager.getVideoFile(videoResource).length()), "mp4",viewButton));
List<VideoQualityVersion> versions = videoManager.getQualityVersions(videoResource); List<VideoQualityVersion> versions = videoManager.getQualityVersions(videoResource);
for(VideoQualityVersion version:versions){ for(VideoQualityVersion version:versions){
viewButton = uifactory.addFormLink(version.getType(), "viewQuality", "quality.view", "qulaity.view", null, Link.LINK); viewButton = uifactory.addFormLink(Integer.toString(version.getResolution()), "viewQuality", "quality.view", "qulaity.view", null, Link.LINK);
Size size = version.getDimension(); Size size = version.getDimension();
String dimension = ""; String dimension = "";
if (size != null) { if (size != null) {
...@@ -105,15 +105,12 @@ public class VideoQualityTableFormController extends FormBasicController { ...@@ -105,15 +105,12 @@ public class VideoQualityTableFormController extends FormBasicController {
String fileSize = ""; String fileSize = "";
if (version.getFileSize() != null) { if (version.getFileSize() != null) {
fileSize = version.getFileSize(); fileSize = version.getFileSize();
} else if (version.getIsTransforming()) { } else if (version.getTranscodingStatus() == VideoQualityVersion.TRANSCODING_STATUS_WAITING) {
// TODO refactor to separate column fileSize = translate("transcoding.waiting");
if (version.getTranscodingStatus() == 0) { } else if (version.getTranscodingStatus() == VideoQualityVersion.TRANSCODING_STATUS_DONE){
fileSize = translate("transcoding.waiting"); fileSize = translate("transcoding.processing") + ": " + version.getTranscodingStatus() + "%";
} else {
fileSize = translate("transcoding.processing") + ": " + version.getTranscodingStatus() + "%";
}
} }
rows.add(new QualityTableRow(translate("quality.type." + version.getType()), dimension, fileSize, version.getFormat(),viewButton)); rows.add(new QualityTableRow(translate("quality.resolution." + version.getResolution()), dimension, fileSize, version.getFormat(),viewButton));
} }
tableModel.setObjects(rows); tableModel.setObjects(rows);
......
...@@ -50,7 +50,7 @@ public class VideoQualityTableModel extends DefaultFlexiTableDataModel<QualityTa ...@@ -50,7 +50,7 @@ public class VideoQualityTableModel extends DefaultFlexiTableDataModel<QualityTa
public Object getValueAt(int row, int col) { public Object getValueAt(int row, int col) {
QualityTableRow video = getObject(row); QualityTableRow video = getObject(row);
switch(QualityTableCols.values()[col]) { switch(QualityTableCols.values()[col]) {
case type: return video.getType(); case resolution: return video.getResolution();
case dimension: return video.getDimension(); case dimension: return video.getDimension();
case size: return video.getSize(); case size: return video.getSize();
case format: return video.getFormat(); case format: return video.getFormat();
...@@ -60,7 +60,7 @@ public class VideoQualityTableModel extends DefaultFlexiTableDataModel<QualityTa ...@@ -60,7 +60,7 @@ public class VideoQualityTableModel extends DefaultFlexiTableDataModel<QualityTa
} }
public enum QualityTableCols { public enum QualityTableCols {
type("quality.table.header.type"), resolution("quality.table.header.resolution"),
dimension("quality.table.header.dimension"), dimension("quality.table.header.dimension"),
size("quality.table.header.size"), size("quality.table.header.size"),
format("quality.table.header.format"), format("quality.table.header.format"),
......
<div class="o_video_run o_clearfix"> <div class="o_video_run o_clearfix">
<div class="olatFlashMovieViewer"> <div class="olatFlashMovieViewer">
<video id="$r.getId("o_vid")" width="$width" height="$height" poster="$mediaUrl/poster.jpg" controls #if( $autoplay ) autoplay #end class="o_video"> <video id="$r.getId("o_vid")" width="$width" height="$height" poster="$mediaUrl/poster.jpg" controls #if( $autoplay ) autoplay #end class="o_video">
#set( $hasOptimizedVideo = false)
#foreach( $video in $videos) #foreach( $video in $videos)
#if(!$video.getIsTransforming()) #if($video.getTranscodingStatus() == 100)
#set( $hasOptimizedVideo = true) #set( $hasOptimizedVideo = true)
<source type="video/mp4" src="$mediaUrl/optimizedVideoData/${video.getType()}video.mp4" title="$r.translate("quality.type.${video.getType()}") (${video.getFileSize()})"/> <source type="video/mp4" src="$mediaUrl/optimizedVideoData/${video.getResolution()}video.mp4" title="$r.translate("quality.type.${video.getType()}") (${video.getFileSize()})"/>
#end #end
#end #end
## Use master video file if not optimized video is found ## Use master video file if not optimized video is found
......
...@@ -10,15 +10,14 @@ poster.select=Dieses Vorschaubild ausw\u00E4hlen ...@@ -10,15 +10,14 @@ poster.select=Dieses Vorschaubild ausw\u00E4hlen
quality.table.header.dimension=Dimension quality.table.header.dimension=Dimension
quality.table.header.format=Format quality.table.header.format=Format
quality.table.header.size=Gr\u00F6sse quality.table.header.size=Gr\u00F6sse
quality.table.header.type=Typ quality.table.header.resolution=Auflsung
quality.table.header.view=ansehen quality.table.header.view=ansehen
quality.view=vorschau quality.view=vorschau
quality.type.1080=1080p Full-HD quality.resolution.original=Master Video
quality.type.720=720p HD quality.resolution.1080=1080p Full-HD
quality.type.480=480p quality.resolution.720=720p HD
quality.type.360=360p quality.resolution.480=480p
quality.type.240=240p quality.resolution.360=360p
quality.type.144=144p
transcoding.waiting=In Warteschlange transcoding.waiting=In Warteschlange
transcoding.processing=In Bearbeitung transcoding.processing=In Bearbeitung
tab.video.metaDataConfig=Metadaten konfigurieren tab.video.metaDataConfig=Metadaten konfigurieren
......
...@@ -11,6 +11,7 @@ tab.video.metaDataConfig=Metadata configuration ...@@ -11,6 +11,7 @@ tab.video.metaDataConfig=Metadata configuration
tab.video.posterConfig=Poster configuration tab.video.posterConfig=Poster configuration
tab.video.settings=Video settings tab.video.settings=Video settings
tab.video.trackConfig=Subtitle configuration tab.video.trackConfig=Subtitle configuration
tab.video.qualityConfig=Video quality
table.header.delete=Delete table.header.delete=Delete
table.header.file=File table.header.file=File
table.header.language=Language table.header.language=Language
...@@ -37,11 +38,16 @@ video.config.tracks.table.add=add ...@@ -37,11 +38,16 @@ video.config.tracks.table.add=add
video.config.tracks.table.delete=delete video.config.tracks.table.delete=delete
video.config.tracks.table.lang=language video.config.tracks.table.lang=language
video.config.width=Width video.config.width=Width
quality.type.1080=1080p Full-HD quality.resolution.original=Master video
quality.type.720=720p HD quality.resolution.1080=1080p Full-HD
quality.type.480=480p quality.resolution.720=720p HD
quality.type.360=360p quality.resolution.480=480p
quality.type.240=240p quality.resolution.360=360p
quality.type.144=144p quality.table.header.dimension=Dimension
quality.table.header.format=Format
quality.table.header.size=Size
quality.table.header.resolution=Resolution
quality.table.header.view=Preview
quality.view=preview
transcoding.waiting=Queuing transcoding.waiting=Queuing
transcoding.processing=Processing transcoding.processing=Processing
...@@ -1157,7 +1157,6 @@ vc.openmeetings.customerid=1 ...@@ -1157,7 +1157,6 @@ vc.openmeetings.customerid=1
vc.gotomeetings.enabled=false vc.gotomeetings.enabled=false
vc.gotomeetings.consumerKey= vc.gotomeetings.consumerKey=
######################################## ########################################
# Options for monitoring # Options for monitoring
######################################## ########################################
...@@ -1166,6 +1165,14 @@ monitoring.instance.description=OpenOLAT instance ...@@ -1166,6 +1165,14 @@ monitoring.instance.description=OpenOLAT instance
monitored.probes=Runtime,System,Database,Memory,OpenOLAT,Release,Environment,Indexer monitored.probes=Runtime,System,Database,Memory,OpenOLAT,Release,Environment,Indexer
monitoring.dependency.server=myserver monitoring.dependency.server=myserver
# Video resource
video.enabled=true
video.coursenode.enabled=true
# The binary "HandBrakeCLI" must be installed to make transcoding work
video.transcoding.enabled=false
video.transcoding.resolutions=1080,720,480,360
# Use tasklist to limit CPU usage.
video.transcoding.taskset.cpuconfig=0,1
video.transcoding.taskset.cpuconfig.values=0,1 to indicate usage of 2 cores, set empty value to disable taskset (e.g. on osx not available)
#
video.transcoding.provider=handbrake
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment