Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.openmeetings.app.data.flvrecord.converter; import java.io.File; import java.util.HashMap; import java.util.List; import org.openmeetings.app.OpenmeetingsVariables; import org.openmeetings.app.data.basic.Configurationmanagement; import org.openmeetings.app.data.flvrecord.FlvRecordingMetaDataDaoImpl; import org.openmeetings.app.data.flvrecord.FlvRecordingMetaDeltaDaoImpl; import org.openmeetings.app.documents.GenerateSWF; import org.openmeetings.app.persistence.beans.flvrecord.FlvRecording; import org.openmeetings.app.persistence.beans.flvrecord.FlvRecordingMetaData; import org.openmeetings.app.persistence.beans.flvrecord.FlvRecordingMetaDelta; import org.openmeetings.app.remote.red5.ScopeApplicationAdapter; import org.openmeetings.utils.ProcessHelper; import org.red5.logging.Red5LoggerFactory; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; public abstract class BaseConverter { private static final Logger log = Red5LoggerFactory.getLogger(BaseConverter.class, OpenmeetingsVariables.webAppRootKey); @Autowired private Configurationmanagement configurationmanagement; @Autowired private FlvRecordingMetaDataDaoImpl flvRecordingMetaDataDaoImpl; @Autowired private FlvRecordingMetaDeltaDaoImpl flvRecordingMetaDeltaDaoImpl; protected String getPathToFFMPEG() { String pathToFFMPEG = configurationmanagement.getConfKey(3, "ffmpeg_path").getConf_value(); if (!pathToFFMPEG.equals("") && !pathToFFMPEG.endsWith(File.separator)) { pathToFFMPEG += File.separator; } pathToFFMPEG += "ffmpeg"; return pathToFFMPEG; } protected String getPathToSoX() { String pathToSoX = configurationmanagement.getConfKey(3, "sox_path").getConf_value(); if (!pathToSoX.equals("") && !pathToSoX.endsWith(File.separator)) { pathToSoX += File.separator; } pathToSoX += "sox"; return pathToSoX; } protected String getPathToImageMagick() { String pathToImageMagick = this.configurationmanagement.getConfKey(3, "imagemagick_path").getConf_value(); if (!pathToImageMagick.equals("") && !pathToImageMagick.endsWith(File.separator)) { pathToImageMagick += File.separator; } pathToImageMagick += "convert" + GenerateSWF.execExt; return pathToImageMagick; } protected boolean isUseOldStyleFfmpegMap() { return "1" .equals(configurationmanagement.getConfValue("use.old.style.ffmpeg.map.option", String.class, "0")); } protected String getStreamFolderName() { return getStreamFolderName("hibernate"); } protected String getStreamFolderName(FlvRecording flvRecording) { return getStreamFolderName("" + flvRecording.getRoom_id()); } protected String getStreamFolderName(String name) { String streamFolderName = ScopeApplicationAdapter.webAppPath + File.separatorChar + OpenmeetingsVariables.STREAMS_DIR + File.separatorChar + name + File.separatorChar; log.debug("###################################################"); log.debug("### streamFolderName - " + streamFolderName); File sf = new File(streamFolderName); if (!sf.exists()) { log.debug("### streamFolderName is NOT exists"); if (!sf.mkdir()) { log.error("### streamFolderName: Failed to create folder"); } } return streamFolderName; } protected void deleteFileIfExists(String name) { File f = new File(name); if (f.exists()) { f.delete(); } } protected String[] mergeAudioToWaves(List<String> listOfFullWaveFiles, String outputFullWav) throws Exception { String[] argv_full_sox = new String[listOfFullWaveFiles.size() + 3]; log.debug(" listOfFullWaveFiles " + listOfFullWaveFiles.size() + " argv_full_sox LENGTH " + argv_full_sox.length); argv_full_sox[0] = getPathToSoX(); argv_full_sox[1] = "-m"; int i = 0; for (; i < listOfFullWaveFiles.size(); i++) { log.debug(" i " + i + " = " + listOfFullWaveFiles.get(i)); argv_full_sox[2 + i] = listOfFullWaveFiles.get(i); } log.debug(" i + 2 " + (i + 2) + " " + outputFullWav); argv_full_sox[i + 2] = outputFullWav; return argv_full_sox; } protected void stripAudioFirstPass(FlvRecording flvRecording, List<HashMap<String, String>> returnLog, List<String> listOfFullWaveFiles, String streamFolderName) throws Exception { List<FlvRecordingMetaData> metaDataList = flvRecordingMetaDataDaoImpl .getFlvRecordingMetaDataAudioFlvsByRecording(flvRecording.getFlvRecordingId()); stripAudioFirstPass(flvRecording, returnLog, listOfFullWaveFiles, streamFolderName, metaDataList); } protected void stripAudioFirstPass(FlvRecording flvRecording, List<HashMap<String, String>> returnLog, List<String> listOfFullWaveFiles, String streamFolderName, List<FlvRecordingMetaData> metaDataList) { try { // Init variables log.debug("### meta Data Number - " + metaDataList.size()); log.debug("###################################################"); for (FlvRecordingMetaData flvRecordingMetaData : metaDataList) { if (flvRecordingMetaData.getStreamReaderThreadComplete() == null) { throw new IllegalStateException("StreamReaderThreadComplete Bit is NULL, error in recording"); } if (!flvRecordingMetaData.getStreamReaderThreadComplete()) { log.debug("### meta Stream not yet written to disk" + flvRecordingMetaData.getFlvRecordingMetaDataId()); boolean doStop = true; while (doStop) { log.debug("### Stream not yet written Thread Sleep - " + flvRecordingMetaData.getFlvRecordingMetaDataId()); flvRecordingMetaData = flvRecordingMetaDataDaoImpl .getFlvRecordingMetaDataById(flvRecordingMetaData.getFlvRecordingMetaDataId()); if (flvRecordingMetaData.getStreamReaderThreadComplete()) { log.debug("### Stream now written Thread continue - "); doStop = false; } Thread.sleep(100L); } } String inputFlv = streamFolderName + flvRecordingMetaData.getStreamName() + ".flv"; String hashFileName = flvRecordingMetaData.getStreamName() + "_WAVE.wav"; String outputWav = streamFolderName + hashFileName; flvRecordingMetaData.setWavAudioData(hashFileName); File inputFlvFile = new File(inputFlv); log.debug("FLV File Name: {} Length: {} ", inputFlvFile.getName(), inputFlvFile.length()); if (inputFlvFile.exists()) { String[] argv = new String[] { this.getPathToFFMPEG(), "-async", "1", "-i", inputFlv, outputWav }; log.debug("START stripAudioFromFLVs ################# "); for (int i = 0; i < argv.length; i++) { log.debug(" i " + i + " argv-i " + argv[i]); } log.debug("END stripAudioFromFLVs ################# "); returnLog.add(ProcessHelper.executeScript("generateFFMPEG", argv)); // check if the resulting Audio is valid File output_wav = new File(outputWav); if (!output_wav.exists()) { flvRecordingMetaData.setAudioIsValid(false); } else { if (output_wav.length() == 0) { flvRecordingMetaData.setAudioIsValid(false); } else { flvRecordingMetaData.setAudioIsValid(true); } } } else { flvRecordingMetaData.setAudioIsValid(false); } if (flvRecordingMetaData.getAudioIsValid()) { // Strip Wave to Full Length String outputGapFullWav = outputWav; // Fix Start/End in Audio List<FlvRecordingMetaDelta> flvRecordingMetaDeltas = flvRecordingMetaDeltaDaoImpl .getFlvRecordingMetaDeltaByMetaId(flvRecordingMetaData.getFlvRecordingMetaDataId()); int counter = 0; for (FlvRecordingMetaDelta flvRecordingMetaDelta : flvRecordingMetaDeltas) { String inputFile = outputGapFullWav; // Strip Wave to Full Length String hashFileGapsFullName = flvRecordingMetaData.getStreamName() + "_GAP_FULL_WAVE_" + counter + ".wav"; outputGapFullWav = streamFolderName + hashFileGapsFullName; flvRecordingMetaDelta.setWaveOutPutName(hashFileGapsFullName); String[] argv_sox = null; if (flvRecordingMetaDelta.getIsStartPadding() != null && flvRecordingMetaDelta.getIsStartPadding()) { double gapSeconds = Double.valueOf(flvRecordingMetaDelta.getDeltaTime().toString()) .doubleValue() / 1000; Double.valueOf(flvRecordingMetaDelta.getDeltaTime().toString()).doubleValue(); if (gapSeconds > 0) { // Add the item at the beginning argv_sox = new String[] { this.getPathToSoX(), inputFile, outputGapFullWav, "pad", String.valueOf(gapSeconds).toString(), "0" }; } } else if (flvRecordingMetaDelta.getIsEndPadding() != null && flvRecordingMetaDelta.getIsEndPadding()) { double gapSeconds = Double.valueOf(flvRecordingMetaDelta.getDeltaTime().toString()) .doubleValue() / 1000; if (gapSeconds > 0) { // Add the item at the end argv_sox = new String[] { this.getPathToSoX(), inputFile, outputGapFullWav, "pad", "0", String.valueOf(gapSeconds).toString() }; } } if (argv_sox != null) { log.debug("START addGapAudioToWaves ################# "); log.debug("START addGapAudioToWaves ################# Delta-ID :: " + flvRecordingMetaDelta.getFlvRecordingMetaDeltaId()); String commandHelper = " "; for (int i = 0; i < argv_sox.length; i++) { commandHelper += " " + argv_sox[i]; } log.debug(" commandHelper " + commandHelper); log.debug("END addGapAudioToWaves ################# "); returnLog.add(ProcessHelper.executeScript("fillGap", argv_sox)); this.flvRecordingMetaDeltaDaoImpl.updateFlvRecordingMetaDelta(flvRecordingMetaDelta); counter++; } else { outputGapFullWav = inputFile; } } // Strip Wave to Full Length String hashFileFullName = flvRecordingMetaData.getStreamName() + "_FULL_WAVE.wav"; String outputFullWav = streamFolderName + hashFileFullName; // Calculate delta at beginning Long deltaTimeStartMilliSeconds = flvRecordingMetaData.getRecordStart().getTime() - flvRecording.getRecordStart().getTime(); Float startPadding = Float.parseFloat(deltaTimeStartMilliSeconds.toString()) / 1000; // Calculate delta at ending Long deltaTimeEndMilliSeconds = flvRecording.getRecordEnd().getTime() - flvRecordingMetaData.getRecordEnd().getTime(); Float endPadding = Float.parseFloat(deltaTimeEndMilliSeconds.toString()) / 1000; String[] argv_sox = new String[] { this.getPathToSoX(), outputGapFullWav, outputFullWav, "pad", startPadding.toString(), endPadding.toString() }; log.debug("START addAudioToWaves ################# "); String padString = ""; for (int i = 0; i < argv_sox.length; i++) { padString += " " + argv_sox[i]; } log.debug("padString :: " + padString); log.debug("END addAudioToWaves ################# "); returnLog.add(ProcessHelper.executeScript("addStartEndToAudio", argv_sox)); // Fix for Audio Length - Invalid Audio Length in Recorded // Files // Audio must match 100% the Video log.debug("############################################"); log.debug("Trim Audio to Full Length -- Start"); File aFile = new File(outputFullWav); if (!aFile.exists()) { throw new Exception("Audio File does not exist , could not extract the Audio correctly"); } flvRecordingMetaData.setFullWavAudioData(hashFileFullName); // Finally add it to the row! listOfFullWaveFiles.add(outputFullWav); } flvRecordingMetaDataDaoImpl.updateFlvRecordingMetaData(flvRecordingMetaData); } } catch (Exception err) { log.error("[stripAudioFromFLVs]", err); } } }