/** * TranscodeTasks.java * Author: Francesco Rosso (rosso@eurix.it) * * 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; import it.eurix.archtools.data.DataException; import it.eurix.archtools.data.model.AIP; import it.eurix.archtools.data.model.IPException; import it.eurix.archtools.data.model.SIP; import it.eurix.archtools.tool.ToolException; import it.eurix.archtools.tool.ToolOutput; import it.eurix.archtools.tool.impl.MessageDigestExtractor; import it.eurix.archtools.workflow.exceptions.TaskExecutionFailedException; import it.eurix.archtools.workflow.plugin.WfPlugin; import it.eurix.archtools.workflow.plugin.WfPlugin.WfService; import java.io.File; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import eu.prestoprime.datamanagement.P4DataManager; import eu.prestoprime.plugin.p4.tools.FFmbc; import eu.prestoprime.plugin.p4.tools.FFmpeg; import eu.prestoprime.plugin.p4.tools.FFmpeg2theora; @WfPlugin(name = "P4Plugin") public class TranscodeTasks { private static final Logger logger = LoggerFactory.getLogger(TranscodeTasks.class); @WfService(name = "transcode2webm", version = "2.2.0") public void transcodeToWebM(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamsFile) throws TaskExecutionFailedException { // get sipID String sipID = dParamsString.get("sipID"); // get SIP SIP sip = null; try { sip = P4DataManager.getInstance().getSIPByID(sipID); // get MQ file String videoFile = null; String[] formats = sParams.get("MQformats").split(","); for (String format : formats) { List<String> videoFileList = sip.getAVMaterial(format, "FILE"); if (videoFileList.size() > 0) { videoFile = videoFileList.get(0); // get inputVideo String inputVideo = videoFile; // get outputVideo String outputVideoName = inputVideo.substring(inputVideo.lastIndexOf(File.separator) + 1, inputVideo.lastIndexOf(".")) + ".webm"; String outputVideo = dParamsString.get("videosFolder") + File.separator + outputVideoName; // transcode String mapping = null; if (Boolean.parseBoolean(dParamsString.get("isD10"))) mapping = "D10"; logger.debug("Transcoding to WebM file: " + inputVideo + " format: " + format); new FFmbc().transcodeToWebM(inputVideo, outputVideo, format, mapping, null); // MD5 MessageDigestExtractor mde = new MessageDigestExtractor(); ToolOutput<MessageDigestExtractor.AttributeType> output = mde.extract(outputVideo); String md5sum = output.getAttribute(MessageDigestExtractor.AttributeType.MD5); // update SIP sip.addFile("video/webm", "FILE", outputVideo, md5sum, new File(outputVideo).length()); dParamsFile.put("webm", new File(outputVideo)); return; } } if (videoFile == null) { throw new TaskExecutionFailedException("Unable to find supported MQ format..."); } } catch (DataException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to retrieve SIP..."); } catch (IPException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to find MQ file..."); } catch (ToolException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to transcode video file..."); } finally { P4DataManager.getInstance().releaseIP(sip); } } @WfService(name = "transcode2ogv", version = "0.3.0") public void transcode2OGV(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamFile) throws TaskExecutionFailedException { // get sipID String sipID = dParamsString.get("sipID"); // get SIP SIP sip = null; try { sip = P4DataManager.getInstance().getSIPByID(sipID); // get MQ file String videoFile = null; String[] formats = sParams.get("MQformats").split(","); for (String format : formats) { List<String> videoFileList = sip.getAVMaterial(format, "FILE"); if (videoFileList.size() > 0) { videoFile = videoFileList.get(0); // get inputVideo String inputVideo = videoFile; // get outputVideo String outputVideoName = inputVideo.substring(inputVideo.lastIndexOf(File.separator) + 1, inputVideo.lastIndexOf(".")) + ".ogv"; String outputVideo = dParamsString.get("videosFolder") + File.separator + outputVideoName; // transcode new FFmpeg2theora().transcode(inputVideo, outputVideo); // MD5 MessageDigestExtractor mde = new MessageDigestExtractor(); ToolOutput<MessageDigestExtractor.AttributeType> output = mde.extract(outputVideo); String md5sum = output.getAttribute(MessageDigestExtractor.AttributeType.MD5); // update SIP sip.addFile("video/ogg", "FILE", outputVideo, md5sum, new File(outputVideo).length()); return; } } if (videoFile == null) { throw new TaskExecutionFailedException("Unable to find supported MQ format..."); } } catch (DataException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to retrieve SIP..."); } catch (IPException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to find MQ file..."); } catch (ToolException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to transcode video file..."); } finally { P4DataManager.getInstance().releaseIP(sip); } } @WfService(name = "frames_extraction", version = "2.0.0") public void extractFrames(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamsFile) throws TaskExecutionFailedException { // get sipID String sipID = dParamsString.get("sipID"); // get SIP SIP sip = null; try { sip = P4DataManager.getInstance().getSIPByID(sipID); // get LQ file File lqFile = dParamsFile.get("webm"); String inputVideo = lqFile.getAbsolutePath(); // get outputThumb String outputThumbName = inputVideo.substring(inputVideo.lastIndexOf(File.separator) + 1, inputVideo.lastIndexOf(".")) + ".jpg"; String outputThumb = dParamsString.get("videosFolder") + File.separator + outputThumbName; // get thumb new FFmpeg().extractThumb(inputVideo, outputThumb); // get outputFrames String outputFrames = dParamsString.get("framesFolder"); // get duration & fps int duration = Integer.parseInt(dParamsString.get("duration")); int fps = Integer.parseInt(dParamsString.get("fps")); // get frames new FFmpeg().extractFrames(inputVideo, outputFrames, duration, fps, 5); } catch (DataException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to retrieve SIP..."); } catch (ToolException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to extract thumb or frames..."); } finally { P4DataManager.getInstance().releaseIP(sip); } } @WfService(name = "uncompressed_format_migration", version = "1.0.0") public void migrateToUncompressed(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamFile) throws TaskExecutionFailedException { // retrieve dynamic parameters String aipID = dParamsString.get("aipID"); String outputFolder = dParamsString.get("videosFolder"); AIP aip = null; try { aip = P4DataManager.getInstance().getAIPByID(aipID); List<String> videoFiles = aip.getAVMaterial("video/x-raw-yuv", "FILE"); // check if already migrated if (videoFiles == null || videoFiles.size() == 0) { // only compressed, migrate String[] MQFormats = sParams.get("MQformats").split(","); for (String MQFormat : MQFormats) { List<String> compressedVideoFiles = aip.getAVMaterial(MQFormat, "FILE"); if (compressedVideoFiles.size() != 0) { String MQFile = compressedVideoFiles.get(0); String MQFileName = MQFile.substring(MQFile.lastIndexOf(File.separator), MQFile.lastIndexOf(".")); FFmpeg ffmpeg = new FFmpeg(); MessageDigestExtractor mde = new MessageDigestExtractor(); // encode raw video String outputVideoName = MQFileName + ".avi"; File outputVideo = new File(outputFolder, outputVideoName); ffmpeg.encodeToRawVideo(MQFile, outputVideo.getAbsolutePath()); ToolOutput<MessageDigestExtractor.AttributeType> output = mde.extract(outputVideo.getAbsolutePath()); String outputVideoMD5 = output.getAttribute(MessageDigestExtractor.AttributeType.MD5); // encode raw audio String outputAudioName = MQFileName + ".pcm"; File outputAudio = new File(outputFolder, outputAudioName); ffmpeg.encodeToRawAudio(MQFile, outputAudio.getAbsolutePath()); output = mde.extract(outputAudio.getAbsolutePath()); String outputAudioMD5 = output.getAttribute(MessageDigestExtractor.AttributeType.MD5); // add both video and audio to AIP aip.addFile("video/x-raw-yuv", "FILE", outputVideo.getAbsolutePath(), outputVideoMD5, outputVideo.length()); aip.addFile("audio/x-raw-int", "FILE", outputAudio.getAbsolutePath(), outputAudioMD5, outputAudio.length()); aip.addPreservationEvent("FORMAT_MIGRATION", "mimetype=" + MQFormat + ";to=uncompressed;loctype=FILE;"); break; } } } } catch (DataException e) { throw new TaskExecutionFailedException("Unable to find DIP..."); } catch (IPException e) { throw new TaskExecutionFailedException(""); } catch (ToolException e) { throw new TaskExecutionFailedException("Unable to encode to raw audio or raw video..."); } finally { P4DataManager.getInstance().releaseIP(aip); } } }