/**
* FFmpeg.java
* Author: Francesco Gallo (gallo@eurix.it)
* Contributors: Philip Kahle (philip.kahle@uibk.ac.at)
*
* This file is part of PrestoPRIME Preservation Platform (P4).
*
* Copyright (C) 2009-2012 EURIX Srl, Torino, Italy
*
* 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 eu.prestoprime.plugin.p4.tools;
import it.eurix.archtools.tool.AbstractTool;
import it.eurix.archtools.tool.ToolException;
import java.io.File;
import eu.prestoprime.conf.Constants;
import eu.prestoprime.tools.P4ToolManager;
public class FFmpeg extends AbstractTool<FFmpeg.AttributeType> {
public static enum AttributeType {
}
public FFmpeg() {
super(P4ToolManager.getInstance().getToolDescriptor(Constants.FFMPEG_NAME));
}
public void encode(String inputFile, String outputFile) throws ToolException {
execute("-i", inputFile, outputFile);
}
/**
* Single-threaded transcoding to WebM. Parameters tested with uibk mp4
* material only. </br> Produces VBR compressed, deinterlaced files with
* target bitrate of 1200k/sec. </br> Compression factor of 1/4 for the
* tested mp4 files.</br> About 14fps on Core2Quad Q9400 @ 2,66Ghz.</br>
* </br> Example: ffmpeg -i inFile.mp4 -vcodec libvpx -acodec libvorbis
* -qmin 2 -qmax 42 -vb 1200k -filter:v yadif -f webm outFile.webm</br>
* </br> Thus, mimeTypes other than mp4 are ignored and no processing takes
* place.</br>
*
* @param inputFile
* @param outputFile
* @param mimeType
* @throws ToolException
*/
public void transcodeToWebM(String inputFile, String outputFile, String mimeType) throws ToolException {
if (mimeType.equalsIgnoreCase("video/mp4")) {
execute("-i", inputFile, "-vcodec", "libvpx", "-acodec", "libvorbis", "-qmin", "2", "-qmax", "42", "-vb", "1200k", "-filter:v", "yadif", "-f", "webm", outputFile);
} else {
// TODO Only tested for uibk mp4 files. Test command manually and
// alter if-clause or add commands here.
}
}
/**
* Transcode to WebM with a minimum set of parameters. Allows to pass custom
* parameters from the executing plugin.</br> </br> Default parameters are:
* </br> -vcodec libvpx : vp8 video</br> -acodec libvorbis : vorbis
* audio</br> -f webm : force format webm</br> </br> Reasonable parameters
* to pass in params:</br> -qmin 2 : range minumum for quantizers :
* "-qmin","2"</br> -qmax 42 : range maximum for quantizers :
* "-qmax","42"</br> -vb 1200k: target bitrate for video stream :
* "-vb","1200k"</br> -ar 44100: downsample audio rate :
* ,"-ar","44100",</br> -filter:v yadif : deinterlace filter is needed for
* vhs material : "-filter:v","yadif"</br> -metadata title="title" : force
* title in metadata : ,"-metadata title=\""+outputFile+"\"",</br> -threads
* x: use x cpu cores : "-threads","2"</br> </br>
*
* @param inputFile
* @param outputFile
* @param mimeType
* @param params
* a custom parameter array. If null, then quality settings will
* depend on the used version of FFMpeg. Resulting files may be
* too large for streaming though.
* @throws ToolException
*/
public void transcodeToWebM(String inputFile, String outputFile, String mimeType, String... params) throws ToolException {
if (params == null) { // default fallback
params = new String[] {};
}
String[] execParams = new String[params.length + 9];
execParams[0] = "-i";
execParams[1] = inputFile;
execParams[2] = "-vcodec";
execParams[3] = "libvpx";
execParams[4] = "-acodec";
execParams[5] = "libvorbis";
execParams[6] = "-f";
execParams[7] = "webm";
execParams[execParams.length - 1] = outputFile; // outputFile as last
// parameter
for (int i = 0; i < params.length; i++) { // fill params in between
execParams[i + 8] = params[i];
}
execute(execParams);
}
public void extractFrames(String inputFile, String outputFolder, int duration, int fps, int sampling) throws ToolException {
if (sampling > fps)
sampling = fps;
File outputDir = new File(outputFolder);
if (!outputDir.isDirectory() || !outputDir.canWrite())
throw new ToolException("Error reading or creating output dir " + outputDir);
String outputName = outputFolder + File.separator + "%d.jpg";
execute("-i", inputFile, "-an", "-r", "1/" + Integer.toString(sampling), outputName);
logger.info("Extracted frames: " + outputDir.list().length + " Folder: " + outputFolder);
for (File frameFile : outputDir.listFiles()) {
int frameNum = Integer.parseInt(frameFile.getName().split(".jpg")[0]);
if (frameNum == 1 || frameNum == outputDir.length())
frameNum = frameNum - 1;
else
frameNum = frameNum - 2;
int frame = fps * sampling * frameNum;
frameFile.renameTo(new File(outputDir, frame + "F" + fps + ".jpg"));
}
}
/**
* Same as extractFrames but scales keyframes to a given height in pixels,
* preserving aspect ratio. For use in web applications in low bandwidth
* environments.
*
* @param inputFile
* @param outputFolder
* @param fps
* @param sampling
* @param height
* in pixels
* @throws ToolException
*/
public void extractRescaledFrames(String inputFile, String outputFolder, int fps, int sampling, int height) throws ToolException {
if (sampling > fps)
sampling = fps;
File outputDir = new File(outputFolder);
if (!outputDir.isDirectory() || !outputDir.canWrite())
throw new ToolException("Error reading or creating output dir " + outputDir);
String outputName = outputFolder + File.separator + "%d.jpg";
execute("-i", inputFile, "-an", "-r", "1/" + Integer.toString(sampling), "-vf", "scale=-1:" + height, outputName);
logger.info("Extracted frames: " + outputDir.list().length + " Folder: " + outputFolder);
for (File frameFile : outputDir.listFiles()) {
int frameNum = Integer.parseInt(frameFile.getName().split(".jpg")[0]);
if (frameNum == 1 || frameNum == outputDir.length())
frameNum = frameNum - 1;
else
frameNum = frameNum - 2;
int frame = fps * sampling * frameNum;
frameFile.renameTo(new File(outputDir, frame + "F" + fps + ".jpg"));
}
}
/**
* @param inputFile
* @param thumbFile
* @param time
* String format like: "00:00:05"
* @throws ToolException
*/
public void extractThumb(String inputFile, String thumbFile, String time) throws ToolException {
execute("-i", inputFile, "-an", "-ss", time, "-vframes", "1", thumbFile);
}
public void extractThumb(String inputFile, String thumbFile) throws ToolException {
execute("-i", inputFile, "-an", "-ss", "00:00:05", "-vframes", "1", thumbFile);
}
public void setCustomFFmpeg(String ffmpegPath) {
setCustomExecutable(ffmpegPath);
}
public void encodeToRawVideo(String inputFile, String outputFile) throws ToolException {
execute("-i", inputFile, "-pix_fmt", "yuvj422p", "-an", "-vcodec", "rawvideo", "-y", outputFile);
}
public void encodeToRawAudio(String inputFile, String outputFile) throws ToolException {
execute("-i", inputFile, "-vn", "-f", "s16le", "-acodec", "pcm_s16le", "-y", outputFile);
}
}