Fix: Post-Processing for split recordings
This commit is contained in:
parent
c1bbce7bcd
commit
0b7eeca5f7
|
@ -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());
|
||||||
};
|
};
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,8 +292,6 @@ public class LiveJasminChunkedHttpDownload implements Download {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess() {
|
public void postprocess(File target) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,8 +358,6 @@ public class LiveJasminWebSocketDownload implements Download {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess() {
|
public void postprocess(File target) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue