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

ws.schild.jave.ScreenExtractor Maven / Gradle / Ivy

Go to download

The JAVE (Java Audio Video Encoder) library is Java wrapper on the ffmpeg project. Developers can take take advantage of JAVE2 to transcode audio and video files from a format to another. In example you can transcode an AVI file to a MPEG one, you can change a DivX video stream into a (youtube like) Flash FLV one, you can convert a WAV audio file to a MP3 or a Ogg Vorbis one, you can separate and transcode audio and video tracks, you can resize videos, changing their sizes and proportions and so on. Many other formats, containers and operations are supported by JAVE2.

There is a newer version: 3.5.0
Show newest version
package ws.schild.jave;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

public class ScreenExtractor {

    private final static Log LOG = LogFactory.getLog(ScreenExtractor.class);

    /**
     * The locator of the ffmpeg executable used by this extractor.
     */
    private final FFMPEGLocator locator;
    private int numberOfScreens;

    /**
     * It builds an extractor using a {@link DefaultFFMPEGLocator} instance to
     * locate the ffmpeg executable to use.
     */
    public ScreenExtractor() {
        this.locator = new DefaultFFMPEGLocator();
    }

    /**
     *
     * @return The number of screens found
     */
    public int getNumberOfScreens() {
        return numberOfScreens;
    }

    /**
     * It builds an extractor with a custom {@link FFMPEGLocator}.
     *
     * @param locator The locator picking up the ffmpeg executable used by the
     * extractor.
     */
    public ScreenExtractor(FFMPEGLocator locator) {
        this.locator = locator;
    }

    /**
     * Generates screenshots from source video.
     *
     * @param multimediaObject Source MultimediaObject @see MultimediaObject
     * @param width Output width
     * @param height Output height
     * @param seconds Interval in seconds between screens
     * @param outputDir Destination of output images
     * @param fileNamePrefix Name all thumbnails will start with
     * @param extension Image extension for output (jpg, png, etc)
     * @param quality The range is between 1-31 with 31 being the worst quality
     * @throws InputFormatException If the source multimedia file cannot be
     * decoded.
     * @throws EncoderException If a problems occurs during the encoding
     * process.
     */
    public void render(MultimediaObject multimediaObject, int width, int height, int seconds, File outputDir,
            String fileNamePrefix, String extension, int quality)
            throws InputFormatException, EncoderException {
        File inputFile = multimediaObject.getFile();
        try
        {
            if (!outputDir.exists())
            {
                if (!outputDir.mkdirs())
                {
                    LOG.debug("Failed to create destination folder");
                    throw new SecurityException();
                }
            }
            if (!inputFile.canRead())
            {
                LOG.debug("Failed to open input file");
                throw new SecurityException();
            }
        } catch (SecurityException e)
        {
            LOG.debug("Access denied checking destination folder" + e);
        }

        MultimediaInfo multimediaInfo = multimediaObject.getInfo();
        numberOfScreens = (int) Math.ceil((multimediaInfo.getDuration() * .001) / seconds + 1);

        FFMPEGExecutor ffmpeg = this.locator.createExecutor();
        ffmpeg.addArgument("-i");
        ffmpeg.addArgument(inputFile.getAbsolutePath());
        ffmpeg.addArgument("-f");
        ffmpeg.addArgument("image2");
        ffmpeg.addArgument("-vf");
        ffmpeg.addArgument(String.format("fps=fps=1/%s", String.valueOf(seconds)));
        ffmpeg.addArgument("-s");
        ffmpeg.addArgument(String.format("%sx%s", String.valueOf(width), String.valueOf(height)));
        ffmpeg.addArgument("-qscale");
        ffmpeg.addArgument(String.valueOf(quality));
        ffmpeg.addArgument(String.format("%s%s%s-%%04d.%s",
                outputDir.getAbsolutePath(), File.separator, fileNamePrefix, extension));

        try
        {
            ffmpeg.execute();
        } catch (IOException e)
        {
            throw new EncoderException(e);
        }
        try
        {
            RBufferedReader reader = new RBufferedReader(
                    new InputStreamReader(ffmpeg.getErrorStream()));
            int step = 0;
            int lineNR = 0;
            String line;
            while ((line = reader.readLine()) != null)
            {
                lineNR++;
                LOG.debug("Input Line (" + lineNR + "): " + line);
                // TODO: Implement additional input stream parsing
            }
        } catch (IOException e)
        {
            throw new EncoderException(e);
        } finally
        {
            ffmpeg.destroy();
        }

    }

    /**
     * Generate a single screenshot from source video.
     *
     * @param multimediaObject Source MultimediaObject @see MultimediaObject
     * @param width Output width
     * @param height Output height
     * @param seconds Interval in seconds between screens
     * @param target Destination of output image
     * @param quality The range is between 1-31 with 31 being the worst quality
     * @throws InputFormatException If the source multimedia file cannot be
     * decoded.
     * @throws EncoderException If a problems occurs during the encoding
     * process.
     */
    public void render(MultimediaObject multimediaObject, int width, int height, int seconds, File target, int quality)
            throws EncoderException {
        File inputFile = multimediaObject.getFile();
        target = target.getAbsoluteFile();
        target.getParentFile().mkdirs();
        try
        {
            if (!inputFile.canRead())
            {
                LOG.debug("Failed to open input file");
                throw new SecurityException();
            }
        } catch (SecurityException e)
        {
            LOG.debug("Access denied checking destination folder" + e);
        }

        MultimediaInfo multimediaInfo = multimediaObject.getInfo();
        int duration = (int) (multimediaInfo.getDuration() * .001);
        numberOfScreens = seconds <= duration ? 1 : 0;

        FFMPEGExecutor ffmpeg = this.locator.createExecutor();
        ffmpeg.addArgument("-i");
        ffmpeg.addArgument(inputFile.getAbsolutePath());
        ffmpeg.addArgument("-f");
        ffmpeg.addArgument("image2");
        ffmpeg.addArgument("-vframes");
        ffmpeg.addArgument("1");
        ffmpeg.addArgument("-ss");
        ffmpeg.addArgument(String.valueOf(seconds));
        ffmpeg.addArgument("-s");
        ffmpeg.addArgument(String.format("%sx%s", String.valueOf(width), String.valueOf(height)));
        ffmpeg.addArgument("-qscale");
        ffmpeg.addArgument(String.valueOf(quality));
        ffmpeg.addArgument(target.getAbsolutePath());

        try
        {
            ffmpeg.execute();
        } catch (IOException e)
        {
            throw new EncoderException(e);
        }
        try
        {
            RBufferedReader reader = new RBufferedReader(
                    new InputStreamReader(ffmpeg.getErrorStream()));
            int step = 0;
            int lineNR = 0;
            String line;
            while ((line = reader.readLine()) != null)
            {
                lineNR++;
                LOG.debug("Input Line (" + lineNR + "): " + line);
                // TODO: Implement additional input stream parsing
            }
        } catch (IOException e)
        {
            throw new EncoderException(e);
        } finally
        {
            ffmpeg.destroy();
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy