All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.mklinger.qetcher.liferay.client.impl.VideoProcessorImpl Maven / Gradle / Ivy

/*
 * Copyright 2013-present mklinger GmbH - http://www.mklinger.de
 *
 * All rights reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of mklinger GmbH and its suppliers, if any.
 * The intellectual and technical concepts contained herein are
 * proprietary to mklinger GmbH and its suppliers and are protected
 * by trade secret or copyright law. Dissemination of this
 * information or reproduction of this material is strictly forbidden
 * unless prior written permission is obtained from mklinger GmbH.
 */
package de.mklinger.qetcher.liferay.client.impl;

import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liferay.portal.kernel.image.ImageBag;
import com.liferay.portal.kernel.image.ImageToolUtil;
import com.liferay.portal.kernel.lar.PortletDataContext;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.repository.model.FileVersion;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
import com.liferay.portlet.documentlibrary.util.DLUtil;
import com.liferay.portlet.documentlibrary.util.VideoProcessor;

import de.mklinger.qetcher.liferay.client.impl.mediatype.MediaTypesService;

/**
 * @author Marc Klinger - mklinger[at]mklinger[dot]de
 */
public class VideoProcessorImpl extends MediaRegistryProcessor implements VideoProcessor {
	//	private static final String PARAM_PRESET_HTML5VIDEO = "preset-html5video";
	private static final Logger LOG = LoggerFactory.getLogger(VideoProcessorImpl.class);

	public VideoProcessorImpl() {
		super("video");
	}

	private void _generateVideoQetcher(final FileVersion fileVersion, final File srcFile, final File destFile, final String containerType) throws Exception {
		if (hasPreview(fileVersion, containerType)) {
			return;
		}

		final String sourceExtension = getExtension(fileVersion);
		if (sourceExtension == null) {
			return;
		}

		try (FileInputStream in = new FileInputStream(srcFile)) {
			try (FileOutputStream out = new FileOutputStream(destFile)) {
				if (sourceExtension.equals(containerType)) {
					LOG.info("Using original file as preview for type {}", sourceExtension);
					IOUtils.copy(in, out);
				} else {
					LOG.debug("Generating video preview from {} to {}", sourceExtension, containerType);
					QetcherLiferayServiceUtil.convert(in, out, sourceExtension, containerType, getVideoTargetParameters(containerType), getReferer(fileVersion));
					LOG.debug("Generating video preview done.");
				}
			}
		}

		addFileToStore(
				fileVersion.getCompanyId(), PREVIEW_PATH,
				getPreviewFilePath(fileVersion, containerType), destFile);
	}

	private Map getVideoTargetParameters(final String containerType) {
		//		if ("ogv".equals(containerType) || "mp4".equals(containerType) || "webm".equals(containerType)) {
		//			// use preset PARAM_PRESET_HTML5VIDEO
		//			LOG.info("Using HTML5 video presets");
		//			return Collections.singletonMap(PARAM_PRESET_HTML5VIDEO, String.valueOf(true));
		//		}
		return null;
	}

	private void _generateThumbnailQetcher(final FileVersion fileVersion, final File file, final int height, final int width) throws Exception {
		final String tempFileId = DLUtil.getTempFileId(fileVersion.getFileEntryId(), fileVersion.getVersion());
		final File thumbnailTempFile = getThumbnailTempFile(tempFileId);
		try {
			final String sourceExtension = getExtension(fileVersion);
			if (sourceExtension == null) {
				return;
			}
			LOG.debug("Generating video thumbnail from {} to {}", sourceExtension, THUMBNAIL_TYPE);

			// TODO PropsValues.DL_FILE_ENTRY_THUMBNAIL_VIDEO_FRAME_PERCENTAGE
			try (FileInputStream in = new FileInputStream(file)) {
				try (FileOutputStream out = new FileOutputStream(thumbnailTempFile)) {
					QetcherLiferayServiceUtil.convert(in, out, sourceExtension, THUMBNAIL_TYPE, null, getReferer(fileVersion));
				}
			}

			LOG.debug("Generating video thumbnail done.");

			storeThumbnailImages(fileVersion, thumbnailTempFile);
		} finally {
			FileUtil.delete(thumbnailTempFile);
		}
	}

	private String getReferer(final FileVersion fileVersion) {
		return "companyId=" + fileVersion.getCompanyId() + ",fileEntryId=" + fileVersion.getFileEntryId();
	}

	private String getExtension(final FileVersion fileVersion) {
		final String mimeTypeString = fileVersion.getMimeType();
		LOG.debug("Original source file mime type: {}", mimeTypeString);
		LOG.debug("Original source file extension: {}", fileVersion.getExtension());
		final String sourceExtension = MediaTypesService.getInstance().getFileExtensionByMimeType(mimeTypeString)
				.orElse(fileVersion.getExtension());
		if (sourceExtension == null || sourceExtension.isEmpty()) {
			LOG.warn("Could not determine source file extension for file entry {}", fileVersion.getFileEntryId());
			return null;
		}
		return sourceExtension;
	}

	// ---------

	@Override
	public void afterPropertiesSet() {
		FileUtil.mkdirs(PREVIEW_TMP_PATH);
		FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
	}

	@Override
	public void generateVideo(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) throws Exception {
		_generateVideo(sourceFileVersion, destinationFileVersion);
	}

	@Override
	public InputStream getPreviewAsStream(final FileVersion fileVersion, final String type) throws Exception {
		return doGetPreviewAsStream(fileVersion, type);
	}

	@Override
	public long getPreviewFileSize(final FileVersion fileVersion, final String type) throws Exception {
		return doGetPreviewFileSize(fileVersion, type);
	}

	@Override
	public InputStream getThumbnailAsStream(final FileVersion fileVersion, final int index) throws Exception {
		return doGetThumbnailAsStream(fileVersion, index);
	}

	@Override
	public long getThumbnailFileSize(final FileVersion fileVersion, final int index) throws Exception {
		return doGetThumbnailFileSize(fileVersion, index);
	}

	@Override
	public Set getVideoMimeTypes() {
		return getSupportedSourceMimeTypes();
	}

	@Override
	public boolean hasVideo(final FileVersion fileVersion) {
		boolean hasVideo = false;

		try {
			hasVideo = _hasVideo(fileVersion);

			if (!hasVideo && isSupported(fileVersion)) {
				_queueGeneration(null, fileVersion);
			}
		}
		catch (final Exception e) {
			_log.error(e, e);
		}

		return hasVideo;
	}

	@Override
	public boolean isSupported(final String mimeType) {
		if (Validator.isNull(mimeType)) {
			return false;
		}
		return getVideoMimeTypes().contains(mimeType);
	}

	@Override
	public boolean isVideoSupported(final FileVersion fileVersion) {
		return isSupported(fileVersion);
	}

	@Override
	public boolean isVideoSupported(final String mimeType) {
		return isSupported(mimeType);
	}

	@Override
	public void trigger(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) {
		super.trigger(sourceFileVersion, destinationFileVersion);
		_queueGeneration(sourceFileVersion, destinationFileVersion);
	}

	@Override
	protected void doExportGeneratedFiles(final PortletDataContext portletDataContext, final FileEntry fileEntry, final Element fileEntryElement) throws Exception {
		exportThumbnails(portletDataContext, fileEntry, fileEntryElement, "video");
		exportPreviews(portletDataContext, fileEntry, fileEntryElement);
	}

	@Override
	protected void doImportGeneratedFiles(final PortletDataContext portletDataContext, final FileEntry fileEntry, final FileEntry importedFileEntry, final Element fileEntryElement) throws Exception {
		importThumbnails(portletDataContext, fileEntry, importedFileEntry, fileEntryElement, "video");
		importPreviews(portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
	}

	protected void exportPreviews(final PortletDataContext portletDataContext, final FileEntry fileEntry, final Element fileEntryElement) throws Exception {
		final FileVersion fileVersion = fileEntry.getFileVersion();
		if (!isSupported(fileVersion) || !hasPreviews(fileVersion)) {
			return;
		}

		if (!portletDataContext.isPerformDirectBinaryImport()) {
			for (final String previewType : _PREVIEW_TYPES) {
				exportPreview(portletDataContext, fileEntry, fileEntryElement, "video", previewType);
			}
		}
	}

	@Override
	protected List getFileVersionIds() {
		return _fileVersionIds;
	}

	@Override
	protected String getPreviewType(final FileVersion fileVersion) {
		return _PREVIEW_TYPES[0];
	}

	@Override
	protected String[] getPreviewTypes() {
		return _PREVIEW_TYPES;
	}

	@Override
	protected String getThumbnailType(final FileVersion fileVersion) {
		return THUMBNAIL_TYPE;
	}

	protected void importPreviews(final PortletDataContext portletDataContext, final FileEntry fileEntry, final FileEntry importedFileEntry, final Element fileEntryElement) throws Exception {
		for (final String previewType : _PREVIEW_TYPES) {
			importPreview(portletDataContext, fileEntry, importedFileEntry, fileEntryElement, "video", previewType);
		}
	}

	@Override
	protected void storeThumbnailImages(final FileVersion fileVersion, final File file) throws Exception {
		if (!hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) {
			addFileToStore(
					fileVersion.getCompanyId(), THUMBNAIL_PATH,
					getThumbnailFilePath(fileVersion, THUMBNAIL_INDEX_DEFAULT),
					file);
		}

		if (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_1) || isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_2)) {
			final ImageBag imageBag = ImageToolUtil.read(file);
			final RenderedImage renderedImage = imageBag.getRenderedImage();
			storeThumbnailImage(fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_1);
			storeThumbnailImage(fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_2);
		}
	}

	private void _generateVideo(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) throws Exception {
		if (_hasVideo(destinationFileVersion)) {
			return;
		}

		InputStream inputStream = null;

		File videoTempFile = null;

		try {
			if (sourceFileVersion != null) {
				copy(sourceFileVersion, destinationFileVersion);
				return;
			}

			File file = null;

			if (!hasPreviews(destinationFileVersion) || !hasThumbnails(destinationFileVersion)) {
				if (destinationFileVersion instanceof LiferayFileVersion) {
					try {
						final LiferayFileVersion liferayFileVersion = (LiferayFileVersion)destinationFileVersion;
						file = liferayFileVersion.getFile(false);
					} catch (final UnsupportedOperationException uoe) {
					}
				}

				if (file == null) {
					inputStream = destinationFileVersion.getContentStream(false);
					videoTempFile = FileUtil.createTempFile(destinationFileVersion.getExtension());
					FileUtil.write(videoTempFile, inputStream);
					file = videoTempFile;
				}
			}

			if (!hasPreviews(destinationFileVersion)) {
				final String tempFileId = DLUtil.getTempFileId(
						destinationFileVersion.getFileEntryId(),
						destinationFileVersion.getVersion());
				for (final String previewType : _PREVIEW_TYPES) {
					final File previewTempFile = getPreviewTempFile(tempFileId, previewType);
					try {
						_generateVideoQetcher(destinationFileVersion, file, previewTempFile, previewType);
					} catch (final Exception e) {
						_log.error(e, e);
					} finally {
						FileUtil.delete(previewTempFile);
					}
				}
			}

			if (!hasThumbnails(destinationFileVersion)) {
				try {
					_generateThumbnailQetcher(
							destinationFileVersion, file,
							PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_HEIGHT,
							PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_WIDTH);
				}
				catch (final Exception e) {
					_log.error(e, e);
				}
			}
		} catch (final NoSuchFileEntryException nsfee) {
		} finally {
			StreamUtil.cleanUp(inputStream);
			_fileVersionIds.remove(destinationFileVersion.getFileVersionId());
			FileUtil.delete(videoTempFile);
		}
	}

	private boolean _hasVideo(final FileVersion fileVersion) throws Exception {
		if (!isSupported(fileVersion)) {
			return false;
		}

		return hasPreviews(fileVersion) && hasThumbnails(fileVersion);
	}

	private void _queueGeneration(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) {
		if (_fileVersionIds.contains(destinationFileVersion.getFileVersionId()) || !isSupported(destinationFileVersion)) {
			return;
		}

		_fileVersionIds.add(destinationFileVersion.getFileVersionId());

		sendGenerationMessage(
				DestinationNames.DOCUMENT_LIBRARY_VIDEO_PROCESSOR,
				sourceFileVersion, destinationFileVersion);
	}

	private static final String[] _PREVIEW_TYPES = PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_CONTAINERS;

	private static Log _log = LogFactoryUtil.getLog(VideoProcessorImpl.class);

	private final List _fileVersionIds = new Vector<>();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy