org.openmeetings.app.data.flvrecord.converter.BaseConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.openmeetings.app.data.flvrecord.converter.BaseConverter.java

Source

/*
 * 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);
        }
    }
}