Fix: Post-Processing for split recordings

This commit is contained in:
0xboobface 2019-04-20 22:01:53 +02:00
parent c1bbce7bcd
commit 0b7eeca5f7
6 changed files with 35 additions and 71 deletions

View File

@ -197,16 +197,15 @@ public class LocalRecorder implements Recorder {
Download download = model.createDownload(); Download download = model.createDownload();
LOG.debug("Downloading with {}", download.getClass().getSimpleName()); LOG.debug("Downloading with {}", download.getClass().getSimpleName());
recordingProcesses.put(model, download); recordingProcesses.put(model, download);
new Thread() { Thread downloadThread = new Thread(() -> {
@Override try {
public void run() { download.start(model, config);
try { } catch (IOException e) {
download.start(model, config); LOG.error("Download for {} failed. Download alive: {}", model.getName(), download.isAlive(), e);
} catch (IOException e) {
LOG.error("Download for {} failed. Download alive: {}", model.getName(), download.isAlive(), e);
}
} }
}.start(); });
downloadThread.setName("Download " + model.getName());
downloadThread.start();
} }
private boolean downloadSlotAvailable() { private boolean downloadSlotAvailable() {
@ -226,39 +225,6 @@ public class LocalRecorder implements Recorder {
ppThreadPool.submit(stopAndThePostProcess); ppThreadPool.submit(stopAndThePostProcess);
} }
// private void postprocess(Download download) {
// String postProcessing = Config.getInstance().getSettings().postProcessing;
// if (postProcessing != null && !postProcessing.isEmpty()) {
// Runtime rt = Runtime.getRuntime();
// try {
// String[] args = new String[] {
// postProcessing,
// download.getTarget().getParentFile().getAbsolutePath(),
// download.getTarget().getAbsolutePath(),
// download.getModel().getName(),
// download.getModel().getSite().getName(),
// Long.toString(download.getStartTime().getEpochSecond())
// };
// 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);
// }
// }
// }
@Override @Override
public boolean isTracked(Model model) { public boolean isTracked(Model model) {
lock.lock(); lock.lock();
@ -779,7 +745,7 @@ public class LocalRecorder implements Recorder {
boolean deleted = deleteIfTooShort(download); boolean deleted = deleteIfTooShort(download);
if(!deleted) { if(!deleted) {
fireRecordingStateChanged(download.getTarget(), POST_PROCESSING, download.getModel(), download.getStartTime()); fireRecordingStateChanged(download.getTarget(), POST_PROCESSING, download.getModel(), download.getStartTime());
download.postprocess(); download.postprocess(download.getTarget());
} }
fireRecordingStateChanged(download.getTarget(), FINISHED, download.getModel(), download.getStartTime()); fireRecordingStateChanged(download.getTarget(), FINISHED, download.getModel(), download.getStartTime());
}; };

View File

@ -1,6 +1,7 @@
package ctbrec.recorder.download; package ctbrec.recorder.download;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
@ -34,6 +35,7 @@ import com.iheartradio.m3u8.data.TrackData;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.UnknownModel;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.io.StreamRedirectThread; import ctbrec.io.StreamRedirectThread;
@ -48,7 +50,7 @@ public abstract class AbstractHlsDownload implements Download {
protected volatile boolean running = false; protected volatile boolean running = false;
protected volatile boolean alive = true; protected volatile boolean alive = true;
protected Instant startTime; protected Instant startTime;
protected Model model; protected Model model = new UnknownModel();
protected BlockingQueue<Runnable> downloadQueue = new LinkedBlockingQueue<>(50); protected BlockingQueue<Runnable> downloadQueue = new LinkedBlockingQueue<>(50);
protected ExecutorService downloadThreadPool = new ThreadPoolExecutor(5, 5, 2, TimeUnit.MINUTES, downloadQueue); protected ExecutorService downloadThreadPool = new ThreadPoolExecutor(5, 5, 2, TimeUnit.MINUTES, downloadQueue);
@ -162,19 +164,19 @@ public abstract class AbstractHlsDownload implements Download {
} }
@Override @Override
public void postprocess() { public void postprocess(File target) {
runPostProcessingScript(); runPostProcessingScript(target);
} }
private void runPostProcessingScript() { private void runPostProcessingScript(File target) {
String postProcessing = Config.getInstance().getSettings().postProcessing; String postProcessing = Config.getInstance().getSettings().postProcessing;
if (postProcessing != null && !postProcessing.isEmpty()) { if (postProcessing != null && !postProcessing.isEmpty()) {
Runtime rt = Runtime.getRuntime(); Runtime rt = Runtime.getRuntime();
try { try {
String[] args = new String[] { String[] args = new String[] {
postProcessing, postProcessing,
getTarget().getParentFile().getAbsolutePath(), target.getParentFile().getAbsolutePath(),
getTarget().getAbsolutePath(), target.getAbsolutePath(),
getModel().getName(), getModel().getName(),
getModel().getSite().getName(), getModel().getSite().getName(),
Long.toString(getStartTime().getEpochSecond()) Long.toString(getStartTime().getEpochSecond())

View File

@ -14,5 +14,5 @@ public interface Download {
public File getTarget(); public File getTarget();
public Model getModel(); public Model getModel();
public Instant getStartTime(); public Instant getStartTime();
public void postprocess(); public void postprocess(File target);
} }

View File

@ -220,21 +220,16 @@ public class MergedHlsDownload extends AbstractHlsDownload {
break; break;
} }
} catch(HttpException e) { } catch(HttpException e) {
String modelName = model != null ? model.getName() : "n/a";
if(e.getResponseCode() == 404) { if(e.getResponseCode() == 404) {
LOG.debug("Playlist not found (404). Model {} probably went offline", modelName); LOG.debug("Playlist not found (404). Model {} probably went offline", model);
} else if(e.getResponseCode() == 403) { } else if(e.getResponseCode() == 403) {
LOG.debug("Playlist access forbidden (403). Model {} probably went private or offline", modelName); LOG.debug("Playlist access forbidden (403). Model {} probably went private or offline", model);
} else { } else {
LOG.info("Unexpected error while downloading {}", modelName, e); LOG.info("Unexpected error while downloading {}", model, e);
} }
running = false; running = false;
} catch(Exception e) { } catch(Exception e) {
if(model != null) { LOG.info("Unexpected error while downloading {}", model, e);
LOG.info("Unexpected error while downloading {}", model.getName(), e);
} else {
LOG.info("Unexpected error while downloading", e);
}
running = false; running = false;
} }
} }
@ -330,13 +325,22 @@ public class MergedHlsDownload extends AbstractHlsDownload {
long seconds = recordingDuration.getSeconds(); long seconds = recordingDuration.getSeconds();
if(seconds >= config.getSettings().splitRecordings) { if(seconds >= config.getSettings().splitRecordings) {
try { try {
File lastTargetFile = targetFile;
// switch to the next file
targetFile = Config.getInstance().getFileForRecording(model); targetFile = Config.getInstance().getFileForRecording(model);
LOG.debug("Switching to file {}", targetFile.getAbsolutePath()); LOG.debug("Switching to file {}", targetFile.getAbsolutePath());
fileChannel = FileChannel.open(targetFile.toPath(), CREATE, WRITE); fileChannel = FileChannel.open(targetFile.toPath(), CREATE, WRITE);
MTSSink sink = ByteChannelSink.builder().setByteChannel(fileChannel).build(); MTSSink sink = ByteChannelSink.builder().setByteChannel(fileChannel).build();
streamer.switchSink(sink); streamer.switchSink(sink);
super.startTime = Instant.now();
splitRecStartTime = ZonedDateTime.now(); splitRecStartTime = ZonedDateTime.now();
// TODO pp
// post-process current recording
Thread pp = new Thread(() -> postprocess(lastTargetFile));
pp.setName("Post-Processing split recording");
pp.setPriority(Thread.MIN_PRIORITY);
pp.start();
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error while splitting recording", e); LOG.error("Error while splitting recording", e);
running = false; running = false;
@ -425,11 +429,7 @@ public class MergedHlsDownload extends AbstractHlsDownload {
closeFile(fileChannel); closeFile(fileChannel);
} }
}); });
if(model != null) { t.setName("Segment Merger Thread [" + model.getName() + "]");
t.setName("Segment Merger Thread [" + model.getName() + "]");
} else {
t.setName("Segment Merger Thread");
}
t.setDaemon(true); t.setDaemon(true);
return t; return t;
} }

View File

@ -292,8 +292,6 @@ public class LiveJasminChunkedHttpDownload implements Download {
} }
@Override @Override
public void postprocess() { public void postprocess(File target) {
// TODO Auto-generated method stub
} }
} }

View File

@ -358,8 +358,6 @@ public class LiveJasminWebSocketDownload implements Download {
} }
@Override @Override
public void postprocess() { public void postprocess(File target) {
// TODO Auto-generated method stub
} }
} }