ca.phon.media.FFMpegMediaExporter.java Source code

Java tutorial

Introduction

Here is the source code for ca.phon.media.FFMpegMediaExporter.java

Source

/*
 * Phon - An open source tool for research in phonology.
 * Copyright (C) 2005 - 2015, Gregory Hedlund <ghedlund@mun.ca> and Yvan Rose <yrose@mun.ca>
 * Dept of Linguistics, Memorial University <https://phon.ca>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package ca.phon.media;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang3.StringUtils;

import ca.phon.util.OSInfo;
import ca.phon.worker.PhonTask;

/**
 * Uses the redistributed copy of ffmpeg-static
 * to extract segments of a given media file.
 */
public class FFMpegMediaExporter extends PhonTask {

    private final static Logger LOGGER = Logger.getLogger(FFMpegMediaExporter.class.getName());

    /* ffmpeg options */
    private String inputFile;

    private String outputFile;

    private long startTime = -1L;

    private long duration = -1L;

    private boolean includeVideo = true;

    private String videoCodec = "copy";

    private boolean includeAudio = true;

    private String audioCodec = "copy";

    private String additionalArgs = "";

    /**
     * Constructor
     */
    public FFMpegMediaExporter() {
        super("ffmpeg");
    }

    public String getOtherArgs() {
        return this.additionalArgs;
    }

    public void setOtherArgs(String args) {
        this.additionalArgs = args;

    }

    public boolean isIncludeVideo() {
        return this.includeVideo;
    }

    public void setIncludeVideo(boolean v) {
        this.includeVideo = v;
    }

    public String getVideoCodec() {
        return this.videoCodec;
    }

    public void setVideoCodec(String codec) {
        this.videoCodec = codec;
    }

    public boolean isIncludeAudio() {
        return this.includeAudio;
    }

    public void setIncludeAudio(boolean v) {
        this.includeAudio = v;
    }

    public String getAudioCodec() {
        return this.audioCodec;
    }

    public void setAudioCodec(String audioCodec) {
        this.audioCodec = audioCodec;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public String getInputFile() {
        return inputFile;
    }

    public void setInputFile(String inputFile) {
        this.inputFile = inputFile;
    }

    public String getOutputFile() {
        return outputFile;
    }

    public void setOutputFile(String outputFile) {
        this.outputFile = outputFile;
    }

    @Override
    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    private String getFFMpegBinary() {
        String retVal = null;

        if (OSInfo.isMacOs()) {
            retVal = "data/bin/macos/ffmpeg-static";
        } else if (OSInfo.isWindows()) {
            retVal = "data/bin/windows/ffmpeg-static.exe";
        } else if (OSInfo.isNix()) {
            // use default install location for ubuntu 10.10
            retVal = "/usr/bin/ffmpeg";
        }

        return retVal;
    }

    private List<String> getCmdLine() {
        List<String> cmdLine = new ArrayList<String>();
        cmdLine.add(getFFMpegBinary());

        // setup options
        cmdLine.add("-i");
        cmdLine.add(inputFile);

        if (startTime >= 0L) {
            cmdLine.add("-ss");
            cmdLine.add("" + (startTime / 1000.0f));
        }
        if (duration > 0L) {
            cmdLine.add("-t");
            cmdLine.add("" + (duration / 1000.0f));
        }
        if (isIncludeAudio()) {
            String ac = getAudioCodec();
            if (ac.equalsIgnoreCase("wav") || ac.equalsIgnoreCase("raw")) {
                ac = "pcm_s16le";
            }

            cmdLine.add("-acodec");
            cmdLine.add(ac);

        } else {
            cmdLine.add("-an");
        }

        if (isIncludeVideo()) {
            cmdLine.add("-vcodec");
            cmdLine.add(getAudioCodec());
        } else {
            cmdLine.add("-vn");
        }

        if (StringUtils.strip(additionalArgs).length() > 0) {
            BufferedReader argsReader = new BufferedReader(
                    new InputStreamReader(new ByteArrayInputStream(additionalArgs.getBytes())));
            String line = null;
            try {
                while ((line = argsReader.readLine()) != null) {
                    if (StringUtils.strip(line).length() == 0 || line.matches("^#.*")) {
                        continue;
                    }
                    // allow for a single pair of arguments to be added
                    // for example -ac 1
                    // otherwise it's one argument per line
                    int spaceIdx = line.indexOf(" ");
                    if (spaceIdx > 0) {
                        String arg1 = line.substring(0, spaceIdx);
                        String arg2 = line.substring(spaceIdx + 1);
                        cmdLine.add(arg1);
                        cmdLine.add(arg2);
                    } else
                        cmdLine.add(StringUtils.strip(line));
                }

                argsReader.close();
            } catch (IOException ex) {
                LOGGER.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
            }
        }

        cmdLine.add("-y");
        cmdLine.add(outputFile);

        return cmdLine;
    }

    @Override
    public void performTask() {
        super.setStatus(TaskStatus.RUNNING);

        // check options
        if (inputFile != null) {
            File f = new File(inputFile);
            if (!f.exists()) {
                IOException ex = new IOException("File not found");
                super.err = ex;
                super.setStatus(TaskStatus.ERROR);
                return;
            }
        } else {
            IllegalArgumentException ex = new IllegalArgumentException("Input file cannot be null");
            super.err = ex;
            super.setStatus(TaskStatus.ERROR);
            return;
        }

        if (outputFile != null) {
            File f = new File(outputFile);
            File pf = f.getParentFile();

            if (!pf.exists()) {
                // try to create directories
                if (!pf.mkdirs()) {
                    IOException ex = new IOException("Could not create output directory");
                    super.err = ex;
                    super.setStatus(TaskStatus.ERROR);
                    return;
                }
            } else {
                if (!pf.isDirectory()) {
                    IOException ex = new IOException(pf.getAbsolutePath() + " exists but is not a directory");
                    super.err = ex;
                    super.setStatus(TaskStatus.ERROR);
                    return;
                }
            }
        } else {
            IllegalArgumentException ex = new IllegalArgumentException("Ouput file cannot be null");
            super.err = ex;
            super.setStatus(TaskStatus.ERROR);
            return;
        }

        List<String> cmdLine = getCmdLine();

        // setup process builder
        ProcessBuilder processBuilder = new ProcessBuilder(cmdLine);
        processBuilder.redirectErrorStream(true);
        try {
            // create process
            Process process = processBuilder.start();

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                LOGGER.info(line);
            }
            reader.close();

            super.setStatus(TaskStatus.FINISHED);
        } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
            super.err = ex;
            super.setStatus(TaskStatus.ERROR);
        }

    }

}