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();
LOG.debug("Downloading with {}", download.getClass().getSimpleName());
recordingProcesses.put(model, download);
new Thread() {
@Override
public void run() {
try {
download.start(model, config);
} catch (IOException e) {
LOG.error("Download for {} failed. Download alive: {}", model.getName(), download.isAlive(), e);
}
Thread downloadThread = new Thread(() -> {
try {
download.start(model, config);
} 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() {
@ -226,39 +225,6 @@ public class LocalRecorder implements Recorder {
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
public boolean isTracked(Model model) {
lock.lock();
@ -779,7 +745,7 @@ public class LocalRecorder implements Recorder {
boolean deleted = deleteIfTooShort(download);
if(!deleted) {
fireRecordingStateChanged(download.getTarget(), POST_PROCESSING, download.getModel(), download.getStartTime());
download.postprocess();
download.postprocess(download.getTarget());
}
fireRecordingStateChanged(download.getTarget(), FINISHED, download.getModel(), download.getStartTime());
};

View File

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

View File

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

View File

@ -220,21 +220,16 @@ public class MergedHlsDownload extends AbstractHlsDownload {
break;
}
} catch(HttpException e) {
String modelName = model != null ? model.getName() : "n/a";
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) {
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 {
LOG.info("Unexpected error while downloading {}", modelName, e);
LOG.info("Unexpected error while downloading {}", model, e);
}
running = false;
} catch(Exception e) {
if(model != null) {
LOG.info("Unexpected error while downloading {}", model.getName(), e);
} else {
LOG.info("Unexpected error while downloading", e);
}
LOG.info("Unexpected error while downloading {}", model, e);
running = false;
}
}
@ -330,13 +325,22 @@ public class MergedHlsDownload extends AbstractHlsDownload {
long seconds = recordingDuration.getSeconds();
if(seconds >= config.getSettings().splitRecordings) {
try {
File lastTargetFile = targetFile;
// switch to the next file
targetFile = Config.getInstance().getFileForRecording(model);
LOG.debug("Switching to file {}", targetFile.getAbsolutePath());
fileChannel = FileChannel.open(targetFile.toPath(), CREATE, WRITE);
MTSSink sink = ByteChannelSink.builder().setByteChannel(fileChannel).build();
streamer.switchSink(sink);
super.startTime = Instant.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) {
LOG.error("Error while splitting recording", e);
running = false;
@ -425,11 +429,7 @@ public class MergedHlsDownload extends AbstractHlsDownload {
closeFile(fileChannel);
}
});
if(model != null) {
t.setName("Segment Merger Thread [" + model.getName() + "]");
} else {
t.setName("Segment Merger Thread");
}
t.setName("Segment Merger Thread [" + model.getName() + "]");
t.setDaemon(true);
return t;
}

View File

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

View File

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