Change post-process return value to boolean
This commit is contained in:
parent
4823c603a7
commit
99b21845ab
|
@ -1,11 +1,15 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
import ctbrec.recorder.download.Download;
|
||||||
import javafx.beans.property.LongProperty;
|
import javafx.beans.property.LongProperty;
|
||||||
import javafx.beans.property.SimpleLongProperty;
|
import javafx.beans.property.SimpleLongProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
@ -158,6 +162,8 @@ public class JavaFxRecording extends Recording {
|
||||||
setProgress(updated.getProgress());
|
setProgress(updated.getProgress());
|
||||||
setSizeInByte(updated.getSizeInByte());
|
setSizeInByte(updated.getSizeInByte());
|
||||||
setSingleFile(updated.isSingleFile());
|
setSingleFile(updated.isSingleFile());
|
||||||
|
getAssociatedFiles().clear();
|
||||||
|
getAssociatedFiles().addAll(updated.getAssociatedFiles());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -246,5 +252,59 @@ public class JavaFxRecording extends Recording {
|
||||||
delegate.setId(id);
|
delegate.setId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStatusWithEvent(State status) {
|
||||||
|
delegate.setStatusWithEvent(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getPostProcessedFile() {
|
||||||
|
return delegate.getPostProcessedFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPostProcessedFile(File postProcessedFile) {
|
||||||
|
delegate.setPostProcessedFile(postProcessedFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Download getDownload() {
|
||||||
|
return delegate.getDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDownload(Download download) {
|
||||||
|
delegate.setDownload(download);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Duration getLength() {
|
||||||
|
return delegate.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refresh() {
|
||||||
|
delegate.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBePostProcessed() {
|
||||||
|
return delegate.canBePostProcessed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAssociatedFiles() {
|
||||||
|
return delegate.getAssociatedFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasContactSheet() {
|
||||||
|
return delegate.hasContactSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<File> getContactSheet() {
|
||||||
|
return delegate.getContactSheet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -23,11 +22,11 @@ import com.iheartradio.m3u8.ParseException;
|
||||||
import com.iheartradio.m3u8.PlaylistException;
|
import com.iheartradio.m3u8.PlaylistException;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Hmac;
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.io.StreamRedirectThread;
|
import ctbrec.io.StreamRedirectThread;
|
||||||
|
import ctbrec.io.UrlUtil;
|
||||||
import ctbrec.recorder.download.StreamSource;
|
import ctbrec.recorder.download.StreamSource;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
@ -208,14 +207,7 @@ public class Player {
|
||||||
String hlsBase = Config.getInstance().getServerUrl() + "/hls";
|
String hlsBase = Config.getInstance().getServerUrl() + "/hls";
|
||||||
String recUrl = hlsBase + '/' + rec.getId() + (rec.isSingleFile() ? "" : "/playlist.m3u8");
|
String recUrl = hlsBase + '/' + rec.getId() + (rec.isSingleFile() ? "" : "/playlist.m3u8");
|
||||||
if (cfg.getSettings().requireAuthentication) {
|
if (cfg.getSettings().requireAuthentication) {
|
||||||
URL u = new URL(recUrl);
|
recUrl = UrlUtil.addHmac(recUrl, cfg);
|
||||||
String path = u.getPath();
|
|
||||||
if (!cfg.getContextPath().isEmpty()) {
|
|
||||||
path = path.substring(cfg.getContextPath().length());
|
|
||||||
}
|
|
||||||
byte[] key = cfg.getSettings().key;
|
|
||||||
String hmac = Hmac.calculate(path, key);
|
|
||||||
recUrl = recUrl + "?hmac=" + hmac;
|
|
||||||
}
|
}
|
||||||
return recUrl;
|
return recUrl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ public class DownloadPostprocessor extends AbstractPlaceholderAwarePostProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
// nothing really to do in here, we just inherit from AbstractPlaceholderAwarePostProcessor to use fillInPlaceHolders
|
// nothing really to do in here, we just inherit from AbstractPlaceholderAwarePostProcessor to use fillInPlaceHolders
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import ctbrec.Recording.State;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
import ctbrec.event.RecordingStateChangedEvent;
|
import ctbrec.event.RecordingStateChangedEvent;
|
||||||
|
import ctbrec.io.UrlUtil;
|
||||||
import ctbrec.recorder.ProgressListener;
|
import ctbrec.recorder.ProgressListener;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.recorder.RecordingPinnedException;
|
import ctbrec.recorder.RecordingPinnedException;
|
||||||
|
@ -386,11 +387,16 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
|
||||||
|
|
||||||
JavaFxRecording first = recordings.get(0);
|
JavaFxRecording first = recordings.get(0);
|
||||||
MenuItem openInPlayer = new MenuItem("Open in Player");
|
MenuItem openInPlayer = new MenuItem("Open in Player");
|
||||||
openInPlayer.setOnAction(e -> play(recordings.get(0)));
|
openInPlayer.setOnAction(e -> play(first));
|
||||||
if(first.getStatus() == FINISHED || Config.getInstance().getSettings().localRecording) {
|
if(first.getStatus() == FINISHED || Config.getInstance().getSettings().localRecording) {
|
||||||
contextMenu.getItems().add(openInPlayer);
|
contextMenu.getItems().add(openInPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MenuItem openContactSheet = new MenuItem("Open contact sheet");
|
||||||
|
openContactSheet.setOnAction(e -> openContactSheet(first));
|
||||||
|
openContactSheet.setDisable(!first.hasContactSheet());
|
||||||
|
contextMenu.getItems().add(openContactSheet);
|
||||||
|
|
||||||
// TODO find a way to reenable this
|
// TODO find a way to reenable this
|
||||||
// MenuItem stopRecording = new MenuItem("Stop recording");
|
// MenuItem stopRecording = new MenuItem("Stop recording");
|
||||||
// stopRecording.setOnAction((e) -> {
|
// stopRecording.setOnAction((e) -> {
|
||||||
|
@ -451,6 +457,32 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openContactSheet(JavaFxRecording recording) {
|
||||||
|
if (config.getSettings().localRecording) {
|
||||||
|
recording.getContactSheet().ifPresent(f -> new Thread(() -> DesktopIntegration.open(f)).start());
|
||||||
|
} else {
|
||||||
|
recording.getContactSheet().ifPresent(f -> new Thread(() -> {
|
||||||
|
File target;
|
||||||
|
try {
|
||||||
|
target = File.createTempFile("cs_", ".jpg");
|
||||||
|
target.deleteOnExit();
|
||||||
|
FileDownload download = new FileDownload(CamrecApplication.httpClient, (p) -> {
|
||||||
|
if (p == 100) {
|
||||||
|
DesktopIntegration.open(target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
String url = config.getServerUrl() + "/hls/" + recording.getId() + "/contactsheet.jpg";
|
||||||
|
if (config.getSettings().requireAuthentication) {
|
||||||
|
url = UrlUtil.addHmac(url, config);
|
||||||
|
}
|
||||||
|
download.start(new URL(url), target);
|
||||||
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
|
Dialogs.showError(getTabPane().getScene(), "Download Error", "An error occurred while downloading the contact sheet", e);
|
||||||
|
}
|
||||||
|
}).start());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notes(JavaFxRecording recording) {
|
private void notes(JavaFxRecording recording) {
|
||||||
Node source = getTabPane();
|
Node source = getTabPane();
|
||||||
String notes = recording.getNote();
|
String notes = recording.getNote();
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -312,4 +313,15 @@ public class Recording implements Serializable {
|
||||||
public Set<String> getAssociatedFiles() {
|
public Set<String> getAssociatedFiles() {
|
||||||
return associatedFiles;
|
return associatedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasContactSheet() {
|
||||||
|
return getAssociatedFiles().stream().anyMatch(path -> path.endsWith("contactsheet.jpg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<File> getContactSheet() {
|
||||||
|
return getAssociatedFiles().stream()
|
||||||
|
.filter(path -> path.endsWith("contactsheet.jpg"))
|
||||||
|
.findFirst()
|
||||||
|
.map(File::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package ctbrec.io;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Hmac;
|
||||||
|
|
||||||
|
public class UrlUtil {
|
||||||
|
|
||||||
|
private UrlUtil() {}
|
||||||
|
|
||||||
|
public static String addHmac(String url, Config config) throws MalformedURLException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {
|
||||||
|
URL u = new URL(url);
|
||||||
|
String path = u.getPath();
|
||||||
|
if (!config.getContextPath().isEmpty()) {
|
||||||
|
path = path.substring(config.getContextPath().length());
|
||||||
|
}
|
||||||
|
byte[] key = config.getSettings().key;
|
||||||
|
String hmac = Hmac.calculate(path, key);
|
||||||
|
url = url + "?hmac=" + hmac;
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -164,7 +164,10 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
List<PostProcessor> postProcessors = config.getSettings().postProcessors;
|
List<PostProcessor> postProcessors = config.getSettings().postProcessors;
|
||||||
for (PostProcessor postProcessor : postProcessors) {
|
for (PostProcessor postProcessor : postProcessors) {
|
||||||
LOG.debug("Running post-processor: {}", postProcessor.getName());
|
LOG.debug("Running post-processor: {}", postProcessor.getName());
|
||||||
postProcessor.postprocess(recording, recordingManager, config);
|
boolean continuePP = postProcessor.postprocess(recording, recordingManager, config);
|
||||||
|
if (!continuePP) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setRecordingStatus(recording, State.FINISHED);
|
setRecordingStatus(recording, State.FINISHED);
|
||||||
recordingManager.saveRecording(recording);
|
recordingManager.saveRecording(recording);
|
||||||
|
@ -632,6 +635,7 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
download.init(Config.getInstance(), other.getModel(), other.getStartDate());
|
download.init(Config.getInstance(), other.getModel(), other.getStartDate());
|
||||||
other.setDownload(download);
|
other.setDownload(download);
|
||||||
other.setPostProcessedFile(null);
|
other.setPostProcessedFile(null);
|
||||||
|
other.setStatus(State.WAITING);
|
||||||
submitPostProcessingJob(other);
|
submitPostProcessingJob(other);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class Copy extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
File orig = rec.getPostProcessedFile();
|
File orig = rec.getPostProcessedFile();
|
||||||
String copyFilename = getFilenameForCopy(orig);
|
String copyFilename = getFilenameForCopy(orig);
|
||||||
File copy = new File(orig.getParentFile(), copyFilename);
|
File copy = new File(orig.getParentFile(), copyFilename);
|
||||||
|
@ -34,6 +34,7 @@ public class Copy extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
rec.setPostProcessedFile(copy);
|
rec.setPostProcessedFile(copy);
|
||||||
rec.getAssociatedFiles().add(copy.getCanonicalPath());
|
rec.getAssociatedFiles().add(copy.getCanonicalPath());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFilenameForCopy(File orig) {
|
private String getFilenameForCopy(File orig) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
int totalWidth = Integer.parseInt(getConfig().getOrDefault(TOTAL_SIZE, "1920"));
|
int totalWidth = Integer.parseInt(getConfig().getOrDefault(TOTAL_SIZE, "1920"));
|
||||||
int padding = Integer.parseInt(getConfig().getOrDefault(PADDING, "4"));
|
int padding = Integer.parseInt(getConfig().getOrDefault(PADDING, "4"));
|
||||||
int cols = Integer.parseInt(getConfig().getOrDefault(COLS, "8"));
|
int cols = Integer.parseInt(getConfig().getOrDefault(COLS, "8"));
|
||||||
|
@ -73,13 +73,16 @@ public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
"0",
|
"0",
|
||||||
"-qscale:v",
|
"-qscale:v",
|
||||||
"3",
|
"3",
|
||||||
|
"-y",
|
||||||
|
"-frames:v",
|
||||||
|
"1",
|
||||||
output.getCanonicalPath()
|
output.getCanonicalPath()
|
||||||
};
|
};
|
||||||
String[] cmdline = OS.getFFmpegCommand(args);
|
String[] cmdline = OS.getFFmpegCommand(args);
|
||||||
LOG.info("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
LOG.info("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
||||||
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], executionDir);
|
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], executionDir);
|
||||||
int exitCode = 1;
|
int exitCode = 1;
|
||||||
File ffmpegLog = File.createTempFile("create_contact_sheet_" + input.getName(), ".log");
|
File ffmpegLog = File.createTempFile("create_contact_sheet_" + rec.getId() + '_', ".log");
|
||||||
try (FileOutputStream mergeLogStream = new FileOutputStream(ffmpegLog)) {
|
try (FileOutputStream mergeLogStream = new FileOutputStream(ffmpegLog)) {
|
||||||
Thread stdout = new Thread(new StreamRedirectThread(ffmpeg.getInputStream(), mergeLogStream));
|
Thread stdout = new Thread(new StreamRedirectThread(ffmpeg.getInputStream(), mergeLogStream));
|
||||||
Thread stderr = new Thread(new StreamRedirectThread(ffmpeg.getErrorStream(), mergeLogStream));
|
Thread stderr = new Thread(new StreamRedirectThread(ffmpeg.getErrorStream(), mergeLogStream));
|
||||||
|
@ -91,12 +94,13 @@ public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
stderr.join();
|
stderr.join();
|
||||||
mergeLogStream.flush();
|
mergeLogStream.flush();
|
||||||
}
|
}
|
||||||
|
rec.getAssociatedFiles().add(output.getCanonicalPath());
|
||||||
if (exitCode != 1) {
|
if (exitCode != 1) {
|
||||||
rec.getAssociatedFiles().add(output.getCanonicalPath());
|
|
||||||
if (ffmpegLog.exists()) {
|
if (ffmpegLog.exists()) {
|
||||||
Files.delete(ffmpegLog.toPath());
|
Files.delete(ffmpegLog.toPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getInputFile(Recording rec) {
|
private File getInputFile(Recording rec) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ public class CreateTimelineThumbs extends AbstractPlaceholderAwarePostProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
|
// create 1 thumb every second with a width of 360 pixels and save it as jpeg with a 5-digit sequence number
|
||||||
|
// ffmpeg -i <file> -vf 'fps=1,scale=360:-1' thumbs/out%05d.jpg
|
||||||
throw new NotImplementedExcetion();
|
throw new NotImplementedExcetion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class DeleteOriginal extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
if (rec.getAbsoluteFile().isFile()) {
|
if (rec.getAbsoluteFile().isFile()) {
|
||||||
Files.deleteIfExists(rec.getAbsoluteFile().toPath());
|
Files.deleteIfExists(rec.getAbsoluteFile().toPath());
|
||||||
deleteEmptyParents(rec.getAbsoluteFile().getParentFile());
|
deleteEmptyParents(rec.getAbsoluteFile().getParentFile());
|
||||||
|
@ -27,5 +27,6 @@ public class DeleteOriginal extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
rec.setAbsoluteFile(rec.getPostProcessedFile());
|
rec.setAbsoluteFile(rec.getPostProcessedFile());
|
||||||
rec.getAssociatedFiles().remove(rec.getAbsoluteFile().getCanonicalPath());
|
rec.getAssociatedFiles().remove(rec.getAbsoluteFile().getCanonicalPath());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,16 @@ public class DeleteTooShort extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
||||||
Duration minimumLengthInSeconds = Duration.ofSeconds(Integer.parseInt(getConfig().getOrDefault(MIN_LEN_IN_SECS, "0")));
|
Duration minimumLengthInSeconds = Duration.ofSeconds(Integer.parseInt(getConfig().getOrDefault(MIN_LEN_IN_SECS, "0")));
|
||||||
if (minimumLengthInSeconds.getSeconds() > 0) {
|
if (minimumLengthInSeconds.getSeconds() > 0) {
|
||||||
Duration recordingLength = rec.getLength();
|
Duration recordingLength = rec.getLength();
|
||||||
if (!(recordingLength.isNegative() || recordingLength.isZero()) && recordingLength.compareTo(minimumLengthInSeconds) < 0) {
|
if (!(recordingLength.isNegative() || recordingLength.isZero()) && recordingLength.compareTo(minimumLengthInSeconds) < 0) {
|
||||||
LOG.info("Deleting too short recording {} [{} < {}]", rec, recordingLength, minimumLengthInSeconds);
|
LOG.info("Deleting too short recording {} [{} < {}]", rec, recordingLength, minimumLengthInSeconds);
|
||||||
recordingManager.delete(rec);
|
recordingManager.delete(rec);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,14 @@ public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
||||||
String pathTemplate = getConfig().getOrDefault(PATH_TEMPLATE, DEFAULT);
|
String pathTemplate = getConfig().getOrDefault(PATH_TEMPLATE, DEFAULT);
|
||||||
String path = fillInPlaceHolders(pathTemplate, rec, config);
|
String path = fillInPlaceHolders(pathTemplate, rec, config);
|
||||||
File src = rec.getPostProcessedFile();
|
File src = rec.getPostProcessedFile();
|
||||||
boolean isFile = src.isFile();
|
boolean isFile = src.isFile();
|
||||||
File target = new File(path, src.getName());
|
File target = new File(path, src.getName());
|
||||||
if (Objects.equals(src, target)) {
|
if (Objects.equals(src, target)) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
LOG.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
LOG.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
||||||
Files.createDirectories(target.getParentFile().toPath());
|
Files.createDirectories(target.getParentFile().toPath());
|
||||||
|
@ -48,6 +48,7 @@ public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||||
} else {
|
} else {
|
||||||
deleteEmptyParents(src);
|
deleteEmptyParents(src);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,7 +11,16 @@ import ctbrec.recorder.RecordingManager;
|
||||||
public interface PostProcessor extends Serializable {
|
public interface PostProcessor extends Serializable {
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException;
|
/**
|
||||||
|
* Runs the post-processing code on the given recording
|
||||||
|
* @param rec the recording to post-process
|
||||||
|
* @param recordingManager
|
||||||
|
* @param config
|
||||||
|
* @return false to stop futher post-processing, true to continue
|
||||||
|
* @throws IOException
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException;
|
||||||
|
|
||||||
Map<String, String> getConfig();
|
Map<String, String> getConfig();
|
||||||
void setConfig(Map<String, String> conf);
|
void setConfig(Map<String, String> conf);
|
||||||
|
|
|
@ -14,8 +14,9 @@ public class RemoveKeepFile extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
recordingManager.remove(rec);
|
recordingManager.remove(rec);
|
||||||
rec.setMetaDataFile(null);
|
rec.setMetaDataFile(null);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class Remux extends AbstractPostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
String fileExt = getConfig().get(FILE_EXT);
|
String fileExt = getConfig().get(FILE_EXT);
|
||||||
String[] args = getConfig().get(FFMPEG_ARGS).split(" ");
|
String[] args = getConfig().get(FFMPEG_ARGS).split(" ");
|
||||||
String[] argsPlusFile = new String[args.length + 3];
|
String[] argsPlusFile = new String[args.length + 3];
|
||||||
|
@ -67,6 +67,7 @@ public class Remux extends AbstractPostProcessor {
|
||||||
IoUtils.deleteEmptyParents(inputFile.getParentFile());
|
IoUtils.deleteEmptyParents(inputFile.getParentFile());
|
||||||
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
||||||
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupLogging(Process ffmpeg, Recording rec) throws IOException, InterruptedException {
|
private void setupLogging(Process ffmpeg, Recording rec) throws IOException, InterruptedException {
|
||||||
|
|
|
@ -24,14 +24,14 @@ public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException {
|
||||||
String defaultTemplate = rec.isSingleFile() ? DEFAULT : DEFAULT_DIR;
|
String defaultTemplate = rec.isSingleFile() ? DEFAULT : DEFAULT_DIR;
|
||||||
String filenameTemplate = getConfig().getOrDefault(FILE_NAME_TEMPLATE, defaultTemplate);
|
String filenameTemplate = getConfig().getOrDefault(FILE_NAME_TEMPLATE, defaultTemplate);
|
||||||
String filename = fillInPlaceHolders(filenameTemplate, rec, config);
|
String filename = fillInPlaceHolders(filenameTemplate, rec, config);
|
||||||
File src = rec.getPostProcessedFile();
|
File src = rec.getPostProcessedFile();
|
||||||
File target = new File(src.getParentFile(), filename);
|
File target = new File(src.getParentFile(), filename);
|
||||||
if (Objects.equals(src, target)) {
|
if (Objects.equals(src, target)) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
||||||
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
||||||
|
@ -41,6 +41,7 @@ public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
rec.getAssociatedFiles().remove(src.getCanonicalPath());
|
rec.getAssociatedFiles().remove(src.getCanonicalPath());
|
||||||
rec.getAssociatedFiles().add(target.getCanonicalPath());
|
rec.getAssociatedFiles().add(target.getCanonicalPath());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
List<String> cmdline = buildCommandLine(rec, config);
|
List<String> cmdline = buildCommandLine(rec, config);
|
||||||
Runtime rt = Runtime.getRuntime();
|
Runtime rt = Runtime.getRuntime();
|
||||||
String[] args = cmdline.toArray(new String[0]);
|
String[] args = cmdline.toArray(new String[0]);
|
||||||
|
@ -41,6 +41,7 @@ public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
throw new ProcessExitedUncleanException("Script finished with exit code " + exitCode);
|
throw new ProcessExitedUncleanException("Script finished with exit code " + exitCode);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> buildCommandLine(Recording rec, Config config) throws IOException {
|
private List<String> buildCommandLine(Recording rec, Config config) throws IOException {
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class Webhook extends AbstractPlaceholderAwarePostProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
public boolean postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
|
||||||
throw new NotImplementedExcetion();
|
throw new NotImplementedExcetion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue