From 8dfc4c775f77565293333b80b297da579c8f1a62 Mon Sep 17 00:00:00 2001 From: 0xboobface <0xboobface@gmail.com> Date: Tue, 24 Dec 2019 17:46:29 +0100 Subject: [PATCH] Add post-processing support to the DashDownload --- .../recorder/download/AbstractDownload.java | 59 +++++++++++++++++++ .../recorder/download/dash/DashDownload.java | 36 ++++++----- .../download/hls/AbstractHlsDownload.java | 50 +--------------- 3 files changed, 82 insertions(+), 63 deletions(-) create mode 100644 common/src/main/java/ctbrec/recorder/download/AbstractDownload.java diff --git a/common/src/main/java/ctbrec/recorder/download/AbstractDownload.java b/common/src/main/java/ctbrec/recorder/download/AbstractDownload.java new file mode 100644 index 00000000..a0ab8a56 --- /dev/null +++ b/common/src/main/java/ctbrec/recorder/download/AbstractDownload.java @@ -0,0 +1,59 @@ +package ctbrec.recorder.download; + +import java.io.File; +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ctbrec.Config; +import ctbrec.OS; +import ctbrec.Recording; +import ctbrec.io.StreamRedirectThread; +import ctbrec.recorder.download.hls.AbstractHlsDownload; + +public abstract class AbstractDownload implements Download { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractHlsDownload.class); + + @Override + public void postprocess(Recording recording) { + runPostProcessingScript(recording); + } + + private void runPostProcessingScript(Recording recording) { + String postProcessing = Config.getInstance().getSettings().postProcessing; + if (postProcessing != null && !postProcessing.isEmpty()) { + File target = recording.getAbsoluteFile(); + Runtime rt = Runtime.getRuntime(); + try { + String[] args = new String[] { + postProcessing, + target.getParentFile().getAbsolutePath(), + target.getAbsolutePath(), + getModel().getName(), + getModel().getSite().getName(), + Long.toString(recording.getStartDate().getEpochSecond()) + }; + if(LOG.isDebugEnabled()) { + LOG.debug("Running {}", Arrays.toString(args)); + } + Process process = rt.exec(args, OS.getEnvironment()); + // TODO maybe write these to a separate log file, e.g. recname.ts.pp.log + Thread std = new Thread(new StreamRedirectThread(process.getInputStream(), System.out)); + std.setName("Process stdout pipe"); + std.setDaemon(true); + std.start(); + Thread err = new Thread(new StreamRedirectThread(process.getErrorStream(), System.err)); + err.setName("Process stderr pipe"); + err.setDaemon(true); + err.start(); + + process.waitFor(); + LOG.debug("Process finished."); + } catch (Exception e) { + LOG.error("Error in process thread", e); + } + } + } +} diff --git a/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java b/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java index 46c14cbd..8f455844 100644 --- a/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java @@ -1,5 +1,7 @@ package ctbrec.recorder.download.dash; +import static ctbrec.Recording.State.POST_PROCESSING; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; @@ -32,12 +34,12 @@ import ctbrec.Model; import ctbrec.Recording; import ctbrec.Recording.State; import ctbrec.io.HttpClient; -import ctbrec.recorder.download.Download; +import ctbrec.recorder.download.AbstractDownload; import ctbrec.recorder.download.dash.SegmentTimelineType.S; import okhttp3.Request; import okhttp3.Response; -public class DashDownload implements Download { +public class DashDownload extends AbstractDownload { private static final Logger LOG = LoggerFactory.getLogger(DashDownload.class); private int audioCounter = 0; @@ -339,20 +341,22 @@ public class DashDownload implements Download { return Duration.between(startTime, Optional.ofNullable(endTime).orElse(Instant.now())); } - @Override - public void postprocess(Recording recording) { - try { - String path = recording.getPath(); - File dir = new File(Config.getInstance().getSettings().recordingsDir, path); - File file = new File(dir.getParentFile(), dir.getName().substring(0, dir.getName().length() - 5)); - new FfmpegMuxer(dir, file); - targetFile = file; - recording.setPath(path.substring(0, path.length() - 5)); - } catch (IOException e) { - LOG.error("Error while merging dash segments", e); - recording.setStatus(State.FAILED); - } - } + @Override + public void postprocess(Recording recording) { + try { + recording.setStatus(POST_PROCESSING); + String path = recording.getPath(); + File dir = new File(Config.getInstance().getSettings().recordingsDir, path); + File file = new File(dir.getParentFile(), dir.getName().substring(0, dir.getName().length() - 5)); + new FfmpegMuxer(dir, file); + targetFile = file; + recording.setPath(path.substring(0, path.length() - 5)); + super.postprocess(recording); + } catch (IOException e) { + LOG.error("Error while merging dash segments", e); + recording.setStatus(State.FAILED); + } + } @Override public File getTarget() { diff --git a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java index 7754ebad..c5f57f62 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java @@ -1,13 +1,11 @@ package ctbrec.recorder.download.hls; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.time.Instant; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -37,19 +35,16 @@ import com.iheartradio.m3u8.data.TrackData; import ctbrec.Config; import ctbrec.Model; -import ctbrec.OS; -import ctbrec.Recording; import ctbrec.Recording.State; import ctbrec.UnknownModel; import ctbrec.io.HttpClient; import ctbrec.io.HttpException; -import ctbrec.io.StreamRedirectThread; -import ctbrec.recorder.download.Download; +import ctbrec.recorder.download.AbstractDownload; import ctbrec.recorder.download.StreamSource; import okhttp3.Request; import okhttp3.Response; -public abstract class AbstractHlsDownload implements Download { +public abstract class AbstractHlsDownload extends AbstractDownload { private static final Logger LOG = LoggerFactory.getLogger(AbstractHlsDownload.class); private static int threadCounter = 0; @@ -195,46 +190,7 @@ public abstract class AbstractHlsDownload implements Download { return model; } - @Override - public void postprocess(Recording recording) { - runPostProcessingScript(recording); - } - - private void runPostProcessingScript(Recording recording) { - String postProcessing = Config.getInstance().getSettings().postProcessing; - if (postProcessing != null && !postProcessing.isEmpty()) { - File target = recording.getAbsoluteFile(); - Runtime rt = Runtime.getRuntime(); - try { - String[] args = new String[] { - postProcessing, - target.getParentFile().getAbsolutePath(), - target.getAbsolutePath(), - getModel().getName(), - getModel().getSite().getName(), - Long.toString(recording.getStartDate().getEpochSecond()) - }; - if(LOG.isDebugEnabled()) { - LOG.debug("Running {}", Arrays.toString(args)); - } - Process process = rt.exec(args, OS.getEnvironment()); - // TODO maybe write these to a separate log file, e.g. recname.ts.pp.log - Thread std = new Thread(new StreamRedirectThread(process.getInputStream(), System.out)); - std.setName("Process stdout pipe"); - std.setDaemon(true); - std.start(); - Thread err = new Thread(new StreamRedirectThread(process.getErrorStream(), System.err)); - err.setName("Process stderr pipe"); - err.setDaemon(true); - err.start(); - - process.waitFor(); - LOG.debug("Process finished."); - } catch (Exception e) { - LOG.error("Error in process thread", e); - } - } - } + public static class SegmentPlaylist { public String url;