/* * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Frédéric Vadon */ package org.nuxeo.labs.video.mediainfo; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.io.FilenameUtils; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters; import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService; import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult; import org.nuxeo.runtime.api.Framework; public class MediaInfoHelper { public static final String MEDIAINFO_INFO_COMMAND_LINE = "mediainfo-info"; // Utility class. private MediaInfoHelper() { } // Calls media info on the input video and returns the output processed in a // map of maps (following mediaInfo output pattern). public static Map<String, Map<String, String>> getProcessedMediaInfo(Blob video) throws NuxeoException { return processMediaInfo(getRawMediaInfo(video)); } /* * Get one specific information on the input blob video using mediaInfo. a call to * getSpecificMediaInfo("Video","Width",MyVideo) will get something like 512 pixels */ public static String getSpecificMediaInfo(String key1, String key2, Blob video) throws NuxeoException { return getProcessedMediaInfo(video).get(key1).get(key2); } // Get the String List from mediainfo without any processing public static List<String> getRawMediaInfo(Blob video) throws NuxeoException { if (video == null) { return null; } File file = null; try { CommandLineExecutorService cleService = Framework.getLocalService(CommandLineExecutorService.class); file = File.createTempFile("mediainfoInfo", "." + FilenameUtils.getExtension(video.getFilename())); video.transferTo(file); CmdParameters params = new CmdParameters(); params.addNamedParameter("inFilePath", file.getAbsolutePath()); // read the duration with a first command to adjust the best rate: ExecResult result = cleService.execCommand(MEDIAINFO_INFO_COMMAND_LINE, params); return result.getOutput(); } catch (Exception e) { throw new NuxeoException(e); } finally { if (file != null) { file.delete(); } } } /* * Processes the raw String List from media info and returns a map of maps. Result of media info is a list of String * that follows a specific pattern: The result of mediainfo looks like : General Format : AVI Codec ID : ISOM Video * FORMAT/INFO : AVC Codexc ID : avc1 This method returns a map of maps that follow this pattern for example General * is the first Key and references a map with Format as a key and AVI as a value. */ public static Map<String, Map<String, String>> processMediaInfo(List<String> input) { Map<String, Map<String, String>> output = new HashMap<String, Map<String, String>>(); int nextIndex = input.indexOf(""); List<String> remainingList = input; List<String> subList; while (nextIndex != -1 && !remainingList.get(0).equals("")) { subList = remainingList.subList(1, nextIndex); output.put(remainingList.get(0), processSubList(subList)); if (nextIndex == remainingList.size() - 1) break; remainingList = remainingList.subList(nextIndex + 1, remainingList.size()); nextIndex = remainingList.indexOf(""); } return output; } // Returns a map from a String List containing a key and a value in each // line separated by a ":" protected static Map<String, String> processSubList(List<String> subList) { Map<String, String> subMap = new HashMap<String, String>(); Iterator<String> subListIterator = subList.iterator(); String singleInfoLine; while (subListIterator.hasNext()) { singleInfoLine = subListIterator.next(); subMap.put(getSingleInfoKey(singleInfoLine), getSingleInfoValue(singleInfoLine)); } return subMap; } // get the first part of a single entry line from the output String list : // before ":". Removes useless white spaces protected static String getSingleInfoKey(String input) { return input.substring(0, input.indexOf(":")).trim(); } // get the second part of a single entry line from the output String list : // after ":" Removes useless white spaces protected static String getSingleInfoValue(String input) { return input.substring(input.indexOf(":") + 1).trim(); } }