001/*
002 * (C) Copyright 2010-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 */
018package org.nuxeo.ecm.platform.video.convert;
019
020import static org.nuxeo.ecm.platform.video.convert.Constants.POSITION_PARAMETER;
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.Map;
025
026import org.apache.commons.io.FilenameUtils;
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.core.api.Blob;
030import org.nuxeo.ecm.core.api.Blobs;
031import org.nuxeo.ecm.core.api.CloseableFile;
032import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
033import org.nuxeo.ecm.core.convert.api.ConversionException;
034import org.nuxeo.ecm.core.convert.cache.SimpleCachableBlobHolder;
035import org.nuxeo.ecm.core.convert.extension.Converter;
036import org.nuxeo.ecm.core.convert.extension.ConverterDescriptor;
037import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
038import org.nuxeo.ecm.platform.commandline.executor.api.CommandException;
039import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService;
040import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable;
041import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult;
042import org.nuxeo.runtime.api.Framework;
043
044/**
045 * Extract a JPEG screenshot of the video at a given time offset (position).
046 *
047 * @author ogrisel
048 */
049public class ScreenshotConverter extends BaseVideoConverter implements Converter {
050
051    public static final Log log = LogFactory.getLog(ScreenshotConverter.class);
052
053    public static final String FFMPEG_SCREENSHOT_COMMAND = "ffmpeg-screenshot";
054
055    @Override
056    public void init(ConverterDescriptor descriptor) {
057    }
058
059    @Override
060    public BlobHolder convert(BlobHolder blobHolder, Map<String, Serializable> parameters) throws ConversionException {
061        Blob blob = blobHolder.getBlob();
062        if (blob == null) {
063            throw new ConversionException("conversion failed (null blob)");
064        }
065        try (CloseableFile source = blob.getCloseableFile("." + FilenameUtils.getExtension(blob.getFilename()))) {
066            Blob outBlob = Blobs.createBlobWithExtension(".jpeg");
067
068            CommandLineExecutorService cles = Framework.getLocalService(CommandLineExecutorService.class);
069            CmdParameters params = cles.getDefaultCmdParameters();
070            params.addNamedParameter("inFilePath", source.getFile().getAbsolutePath());
071            params.addNamedParameter("outFilePath", outBlob.getFile().getAbsolutePath());
072            Double position = 0.0;
073            if (parameters != null) {
074                position = (Double) parameters.get(POSITION_PARAMETER);
075                if (position == null) {
076                    position = 0.0;
077                }
078            }
079            long positionParam = Math.round(position);
080            params.addNamedParameter(POSITION_PARAMETER, String.valueOf(positionParam));
081            ExecResult res = cles.execCommand(FFMPEG_SCREENSHOT_COMMAND, params);
082            if (!res.isSuccessful()) {
083                throw res.getError();
084            }
085
086            outBlob.setMimeType("image/jpeg");
087            outBlob.setFilename(String.format("video-screenshot-%05d.000.jpeg", positionParam));
088            return new SimpleCachableBlobHolder(outBlob);
089        } catch (CommandNotAvailable | IOException | CommandException e) {
090            throw new ConversionException("error extracting screenshot from '" + blob.getFilename() + "'", e);
091        }
092    }
093
094}