/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.googlecode.eckoit.audio; import com.github.couchapptakeout.events.ExitApplicationMessage; import com.googlecode.eckoit.events.ConversionFinishedEvent; import com.googlecode.eckoit.events.RecordingSplitEvent; import com.googlecode.eckoit.events.StreamReadyEvent; import com.googlecode.eckoit.util.Slugger; import java.io.File; import java.io.IOException; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; import org.bushe.swing.event.EventBus; import org.bushe.swing.event.EventSubscriber; /** * Scans a source directory for any new files, converts them and copies them into the * destination directory * @author ryan */ public class ContinousAudioConvereter extends Thread implements EventSubscriber<RecordingSplitEvent> { private File destDir; private boolean running = true; private LinkedBlockingQueue<RecordingSplitEvent> completedRecordings; private String ffmpegcmd; private SplitAudioRecorderConfiguration config; public ContinousAudioConvereter(String ffmpegcmd, File destDir, SplitAudioRecorderConfiguration config) { this.destDir = destDir; this.ffmpegcmd = ffmpegcmd; this.config = config; this.completedRecordings = new LinkedBlockingQueue<RecordingSplitEvent>(); EventBus.subscribeStrongly(RecordingSplitEvent.class, this); EventBus.subscribeStrongly(ExitApplicationMessage.class, new EventSubscriber<ExitApplicationMessage>() { @Override public void onEvent(ExitApplicationMessage t) { running = false; completedRecordings.add(new RecordingSplitEvent(null, null, 0)); } }); } @Override public void run() { while (running) { try { RecordingSplitEvent recordingFinished = completedRecordings.take(); File wav = recordingFinished.getFinishedFile(); if (wav != null) { if (tooFresh(wav)) { completedRecordings.add(recordingFinished); } else { Logger.getLogger(ContinousAudioConvereter.class.getName()).log(Level.INFO, "converting wav: " + wav.getAbsolutePath()); doConversion(recordingFinished.getRecordingID(), wav, recordingFinished.getStartTime()); } } } catch (InterruptedException ex) { Logger.getLogger(ContinousAudioConvereter.class.getName()).log(Level.SEVERE, null, ex); } sleep(); } System.out.println("Continous Audio Converter Shutdown"); } protected void doConversion(String recordingID, File wav, long sectionStartTime) { File mp3 = null; File ogg = null; try { mp3 = convertToMP3(recordingID, wav); if (config.isStream()) { File ts = convertToTs(recordingID, mp3); StreamReadyEvent sre = new StreamReadyEvent(mp3, "video/MP2T", sectionStartTime); sre.setAvailableToStream(ts); sre.setStreamDuration((int) (SplitAudioRecorder.getSplitTime() / 1000)); sre.setSegmentCount(getSegmentCount(wav)); EventBus.publish(sre); } ogg = convertToOGG(recordingID, wav); } catch (Exception ex) { Logger.getLogger(ContinousAudioConvereter.class.getName()).log(Level.SEVERE, null, ex); } if (ogg != null && ogg.exists() && mp3 != null && mp3.exists()) { ConversionFinishedEvent finished = new ConversionFinishedEvent(wav); EventBus.publish(finished); } } /** * If the file is too fresh, we dont want to begin conversion * @param wav * @return */ private boolean tooFresh(File wav) { long now = System.currentTimeMillis(); long timestamp = wav.lastModified(); if ((now - timestamp) < 2000) return true; else return false; } private synchronized File convertToMP3(String recordingID, File wav) throws InterruptedException, IOException { File mp3 = getFileForDocument(recordingID, wav, ".mp3"); if (mp3.exists()) return mp3; long bitrate = config.getMp3Bitrate(); long frequency = config.getMp3Frequency(); File mp3Temp = getFileForDocument(recordingID, wav, ".mp3.tmp"); FFMpegConverter converter = new FFMpegConverter(getFfmpegcmd(), FFMpegConverter.ENCODER_MP3); //System.out.println("Converting to mp3"); converter.convert(wav, bitrate, frequency, mp3Temp, true); //System.out.println("Renaming"); mp3Temp.renameTo(mp3); return mp3; } private synchronized File convertToOGG(String recordingID, File wav) throws InterruptedException, IOException { File ogg = getFileForDocument(recordingID, wav, ".ogg"); if (ogg.exists()) return ogg; long bitrate = config.getOggBitrate(); long frequency = config.getOggFrequency(); File oggTemp = getFileForDocument(recordingID, wav, "tmp.ogg"); FFMpegConverter converter = new FFMpegConverter(getFfmpegcmd(), FFMpegConverter.ENCODER_VORBIS); converter.convert(wav, bitrate, frequency, oggTemp, true); oggTemp.renameTo(ogg); return ogg; } private File convertToTs(String recordingID, File mp3) throws InterruptedException, IOException { FFMpegConverter converter = new FFMpegConverter(getFfmpegcmd(), FFMpegConverter.ENCODER_MP3); File ts = getFileForDocument(recordingID, mp3, ".ts"); converter.makeTS(mp3, ts); return ts; } private File getFileForDocument(String recordingID, File wav, String suffix) { // just do sibblings String count = getSegmentCount(wav); String safeId = Slugger.generateSlug(recordingID); File parent = new File(destDir, safeId); parent.mkdirs(); return new File(parent, count + suffix); } private String getSegmentCount(File wav) { return wav.getName().substring(0, wav.getName().lastIndexOf('.')); } private void sleep() { try { sleep(2000); } catch (InterruptedException ex) { Logger.getLogger(ContinousAudioConvereter.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void onEvent(RecordingSplitEvent recordingSplit) { completedRecordings.add(recordingSplit); } /** * @param config the config to set */ public void setConfig(SplitAudioRecorderConfiguration config) { this.config = config; } /** * @return the ffmpegcmd */ public String getFfmpegcmd() { return ffmpegcmd; } }