forked from j62/ctbrec
Implement proper handling of the orignal and pp files
If a copy is created, the original file is not touched anymore. Otherwise the original file is used and the post-processing process is not repeatable anymore, or at least the results might get unpredictable
This commit is contained in:
parent
90192d9b8f
commit
bf39d9a639
|
@ -0,0 +1,24 @@
|
||||||
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
import ctbrec.recorder.postprocessing.Move;
|
||||||
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
|
import ctbrec.ui.settings.api.Category;
|
||||||
|
import ctbrec.ui.settings.api.Preferences;
|
||||||
|
import ctbrec.ui.settings.api.Setting;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
|
||||||
|
public class MoverPaneFactory extends AbstractPostProcessingPaneFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
||||||
|
SimpleStringProperty pathTemplate = new SimpleStringProperty(null, Move.PATH_TEMPLATE, pp.getConfig().getOrDefault(Move.PATH_TEMPLATE, Move.DEFAULT));
|
||||||
|
properties.add(pathTemplate);
|
||||||
|
|
||||||
|
return Preferences.of(new MapPreferencesStorage(),
|
||||||
|
Category.of(pp.getName(),
|
||||||
|
Setting.of("Directory", pathTemplate)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,9 +7,10 @@ import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
import ctbrec.recorder.postprocessing.Move;
|
||||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
import ctbrec.recorder.postprocessing.Remuxer;
|
import ctbrec.recorder.postprocessing.Remux;
|
||||||
import ctbrec.recorder.postprocessing.Renamer;
|
import ctbrec.recorder.postprocessing.Rename;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.settings.api.Preferences;
|
import ctbrec.ui.settings.api.Preferences;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
@ -20,8 +21,9 @@ public class PostProcessingDialogFactory {
|
||||||
|
|
||||||
static Map<Class<?>, Class<?>> ppToDialogMap = new HashMap<>();
|
static Map<Class<?>, Class<?>> ppToDialogMap = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
ppToDialogMap.put(Remuxer.class, RemuxerPaneFactory.class);
|
ppToDialogMap.put(Remux.class, RemuxerPaneFactory.class);
|
||||||
ppToDialogMap.put(Renamer.class, RenamerPaneFactory.class);
|
ppToDialogMap.put(Rename.class, RenamerPaneFactory.class);
|
||||||
|
ppToDialogMap.put(Move.class, MoverPaneFactory.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PostProcessingDialogFactory() {
|
private PostProcessingDialogFactory() {
|
||||||
|
|
|
@ -7,9 +7,11 @@ import java.util.Optional;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.recorder.postprocessing.Copy;
|
import ctbrec.recorder.postprocessing.Copy;
|
||||||
|
import ctbrec.recorder.postprocessing.DeleteOriginal;
|
||||||
|
import ctbrec.recorder.postprocessing.Move;
|
||||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
import ctbrec.recorder.postprocessing.Remuxer;
|
import ctbrec.recorder.postprocessing.Remux;
|
||||||
import ctbrec.recorder.postprocessing.Renamer;
|
import ctbrec.recorder.postprocessing.Rename;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
|
@ -28,7 +30,14 @@ public class PostProcessingStepPanel extends GridPane {
|
||||||
|
|
||||||
private Config config;
|
private Config config;
|
||||||
|
|
||||||
private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[] { Copy.class, Remuxer.class, Renamer.class };
|
|
||||||
|
private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[] { // @formatter: off
|
||||||
|
Copy.class,
|
||||||
|
Remux.class,
|
||||||
|
Rename.class,
|
||||||
|
Move.class,
|
||||||
|
DeleteOriginal.class
|
||||||
|
}; // @formatter: on
|
||||||
|
|
||||||
ListView<PostProcessor> stepListView;
|
ListView<PostProcessor> stepListView;
|
||||||
ObservableList<PostProcessor> stepList;
|
ObservableList<PostProcessor> stepList;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
import ctbrec.recorder.postprocessing.Remuxer;
|
import ctbrec.recorder.postprocessing.Remux;
|
||||||
import ctbrec.ui.settings.api.Category;
|
import ctbrec.ui.settings.api.Category;
|
||||||
import ctbrec.ui.settings.api.Preferences;
|
import ctbrec.ui.settings.api.Preferences;
|
||||||
import ctbrec.ui.settings.api.Setting;
|
import ctbrec.ui.settings.api.Setting;
|
||||||
|
@ -11,8 +11,8 @@ public class RemuxerPaneFactory extends AbstractPostProcessingPaneFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
||||||
SimpleStringProperty ffmpegParams = new SimpleStringProperty(null, Remuxer.FFMPEG_ARGS, pp.getConfig().getOrDefault(Remuxer.FFMPEG_ARGS, "-c:v copy -c:a copy -movflags faststart -y -f mp4"));
|
SimpleStringProperty ffmpegParams = new SimpleStringProperty(null, Remux.FFMPEG_ARGS, pp.getConfig().getOrDefault(Remux.FFMPEG_ARGS, "-c:v copy -c:a copy -movflags faststart -y -f mp4"));
|
||||||
SimpleStringProperty fileExt = new SimpleStringProperty(null, Remuxer.FILE_EXT, pp.getConfig().getOrDefault(Remuxer.FILE_EXT, "mp4"));
|
SimpleStringProperty fileExt = new SimpleStringProperty(null, Remux.FILE_EXT, pp.getConfig().getOrDefault(Remux.FILE_EXT, "mp4"));
|
||||||
properties.add(ffmpegParams);
|
properties.add(ffmpegParams);
|
||||||
properties.add(fileExt);
|
properties.add(fileExt);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
import ctbrec.recorder.postprocessing.Renamer;
|
import ctbrec.recorder.postprocessing.Rename;
|
||||||
import ctbrec.ui.settings.api.Category;
|
import ctbrec.ui.settings.api.Category;
|
||||||
import ctbrec.ui.settings.api.Preferences;
|
import ctbrec.ui.settings.api.Preferences;
|
||||||
import ctbrec.ui.settings.api.Setting;
|
import ctbrec.ui.settings.api.Setting;
|
||||||
|
@ -11,7 +11,7 @@ public class RenamerPaneFactory extends AbstractPostProcessingPaneFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
||||||
SimpleStringProperty fileTemplate = new SimpleStringProperty(null, Renamer.FILE_NAME_TEMPLATE, pp.getConfig().getOrDefault(Renamer.FILE_NAME_TEMPLATE, Renamer.DEFAULT));
|
SimpleStringProperty fileTemplate = new SimpleStringProperty(null, Rename.FILE_NAME_TEMPLATE, pp.getConfig().getOrDefault(Rename.FILE_NAME_TEMPLATE, Rename.DEFAULT));
|
||||||
properties.add(fileTemplate);
|
properties.add(fileTemplate);
|
||||||
|
|
||||||
return Preferences.of(new MapPreferencesStorage(),
|
return Preferences.of(new MapPreferencesStorage(),
|
||||||
|
|
|
@ -228,7 +228,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get() {
|
public String get() {
|
||||||
String modelNotes = Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), "");
|
String modelNotes = Config.getInstance().getModelNotes(m);
|
||||||
return modelNotes;
|
return modelNotes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -193,4 +193,8 @@ public class Config {
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getModelNotes(Model m) {
|
||||||
|
return Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ctbrec.io;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
|
||||||
|
public class IoUtils {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(IoUtils.class);
|
||||||
|
|
||||||
|
private IoUtils() {}
|
||||||
|
|
||||||
|
public static void deleteEmptyParents(File parent) throws IOException {
|
||||||
|
File recDir = new File(Config.getInstance().getSettings().recordingsDir);
|
||||||
|
while (parent != null && parent.list() != null && parent.list().length == 0) {
|
||||||
|
if (parent.equals(recDir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG.debug("Deleting empty directory {}", parent.getAbsolutePath());
|
||||||
|
Files.delete(parent.toPath());
|
||||||
|
parent = parent.getParentFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteDirectory(File directory) throws IOException {
|
||||||
|
if (!directory.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = directory.listFiles();
|
||||||
|
boolean deletedAllFiles = true;
|
||||||
|
for (File file : files) {
|
||||||
|
try {
|
||||||
|
LOG.trace("Deleting {}", file.getAbsolutePath());
|
||||||
|
Files.delete(file.toPath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
deletedAllFiles = false;
|
||||||
|
LOG.debug("Couldn't delete {}", file, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deletedAllFiles) {
|
||||||
|
throw new IOException("Couldn't delete all files in " + directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -164,6 +164,7 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
recording.postprocess();
|
recording.postprocess();
|
||||||
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());
|
||||||
postProcessor.postprocess(recording);
|
postProcessor.postprocess(recording);
|
||||||
}
|
}
|
||||||
setRecordingStatus(recording, State.FINISHED);
|
setRecordingStatus(recording, State.FINISHED);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ctbrec.recorder;
|
package ctbrec.recorder;
|
||||||
|
|
||||||
import static ctbrec.Recording.State.*;
|
import static ctbrec.Recording.State.*;
|
||||||
|
import static ctbrec.io.IoUtils.*;
|
||||||
import static java.nio.charset.StandardCharsets.*;
|
import static java.nio.charset.StandardCharsets.*;
|
||||||
import static java.nio.file.StandardOpenOption.*;
|
import static java.nio.file.StandardOpenOption.*;
|
||||||
|
|
||||||
|
@ -142,8 +143,10 @@ public class RecordingManager {
|
||||||
File f = new File(associated);
|
File f = new File(associated);
|
||||||
if (f.isFile()) {
|
if (f.isFile()) {
|
||||||
Files.delete(f.toPath());
|
Files.delete(f.toPath());
|
||||||
|
deleteEmptyParents(f.getParentFile());
|
||||||
} else {
|
} else {
|
||||||
deleteDirectory(f);
|
deleteDirectory(f);
|
||||||
|
deleteEmptyParents(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,40 +205,6 @@ public class RecordingManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteEmptyParents(File parent) throws IOException {
|
|
||||||
File recDir = new File(Config.getInstance().getSettings().recordingsDir);
|
|
||||||
while (parent != null && parent.list() != null && parent.list().length == 0) {
|
|
||||||
if (parent.equals(recDir)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG.debug("Deleting empty directory {}", parent.getAbsolutePath());
|
|
||||||
Files.delete(parent.toPath());
|
|
||||||
parent = parent.getParentFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteDirectory(File directory) throws IOException {
|
|
||||||
if (!directory.exists()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File[] files = directory.listFiles();
|
|
||||||
boolean deletedAllFiles = true;
|
|
||||||
for (File file : files) {
|
|
||||||
try {
|
|
||||||
LOG.trace("Deleting {}", file.getAbsolutePath());
|
|
||||||
Files.delete(file.toPath());
|
|
||||||
} catch (Exception e) {
|
|
||||||
deletedAllFiles = false;
|
|
||||||
LOG.debug("Couldn't delete {}", file, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deletedAllFiles) {
|
|
||||||
throw new IOException("Couldn't delete all files in " + directory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pin(Recording recording) throws IOException {
|
public void pin(Recording recording) throws IOException {
|
||||||
recordingsLock.lock();
|
recordingsLock.lock();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
import static java.util.Optional.*;
|
import static java.util.Optional.*;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
@ -10,18 +9,10 @@ import java.util.Locale;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import ctbrec.Config;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
|
||||||
public class Renamer extends AbstractPostProcessor {
|
public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Renamer.class);
|
|
||||||
public static final String FILE_NAME_TEMPLATE = "filename.template";
|
|
||||||
public static final String DEFAULT = "${modelSanitizedName}_${localDateTime}.${fileSuffix}";
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private String[] placeHolders = {
|
private String[] placeHolders = {
|
||||||
|
@ -34,18 +25,13 @@ public class Renamer extends AbstractPostProcessor {
|
||||||
"${localDateTime}",
|
"${localDateTime}",
|
||||||
"${epochSecond}",
|
"${epochSecond}",
|
||||||
"${fileSuffix}",
|
"${fileSuffix}",
|
||||||
"${modelNotes}"
|
"${modelNotes}",
|
||||||
|
"${recordingsDir}"
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
public String fillInPlaceHolders(String input, Recording rec) {
|
||||||
public String getName() {
|
// @formatter:off
|
||||||
return "rename";
|
String output = input
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postprocess(Recording rec) throws IOException {
|
|
||||||
String filenameTemplate = getConfig().getOrDefault(FILE_NAME_TEMPLATE, DEFAULT);
|
|
||||||
String filename = filenameTemplate
|
|
||||||
.replace("${modelName}", ofNullable(rec.getModel().getName()).orElse("modelName"))
|
.replace("${modelName}", ofNullable(rec.getModel().getName()).orElse("modelName"))
|
||||||
.replace("${modelDisplayName}", ofNullable(rec.getModel().getDisplayName()).orElse("displayName"))
|
.replace("${modelDisplayName}", ofNullable(rec.getModel().getDisplayName()).orElse("displayName"))
|
||||||
.replace("${modelSanitizedName}", ofNullable(rec.getModel().getSanitizedNamed()).orElse("sanitizedName"))
|
.replace("${modelSanitizedName}", ofNullable(rec.getModel().getSanitizedNamed()).orElse("sanitizedName"))
|
||||||
|
@ -53,17 +39,15 @@ public class Renamer extends AbstractPostProcessor {
|
||||||
.replace("${siteSanitizedName}", getSanitizedSiteName(rec))
|
.replace("${siteSanitizedName}", getSanitizedSiteName(rec))
|
||||||
.replace("${fileSuffix}", getFileSuffix(rec))
|
.replace("${fileSuffix}", getFileSuffix(rec))
|
||||||
.replace("${epochSecond}", Long.toString(rec.getStartDate().getEpochSecond()))
|
.replace("${epochSecond}", Long.toString(rec.getStartDate().getEpochSecond()))
|
||||||
|
.replace("${modelNotes}", Config.getInstance().getModelNotes(rec.getModel()))
|
||||||
|
.replace("${recordingsDir}", Config.getInstance().getSettings().recordingsDir)
|
||||||
;
|
;
|
||||||
|
|
||||||
filename = replaceUtcDateTime(rec, filename);
|
output = replaceUtcDateTime(rec, output);
|
||||||
filename = replaceLocalDateTime(rec, filename);
|
output = replaceLocalDateTime(rec, output);
|
||||||
|
|
||||||
File src = rec.getPostProcessedFile();
|
return output;
|
||||||
File target = new File(src.getParentFile(), filename);
|
// @formatter:on
|
||||||
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
|
||||||
Files.move(rec.getPostProcessedFile(), target);
|
|
||||||
rec.setPostProcessedFile(target);
|
|
||||||
rec.getAssociatedFiles().add(target.getAbsolutePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replaceUtcDateTime(Recording rec, String filename) {
|
private String replaceUtcDateTime(Recording rec, String filename) {
|
||||||
|
@ -99,17 +83,8 @@ public class Renamer extends AbstractPostProcessor {
|
||||||
return filename.substring(filename.lastIndexOf('.') + 1);
|
return filename.substring(filename.lastIndexOf('.') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private CharSequence getSanitizedSiteName(Recording rec) {
|
private CharSequence getSanitizedSiteName(Recording rec) {
|
||||||
return rec.getModel().getSite().getName().replace(' ', '_').replace('\\', '_').replace('/', '_');
|
return rec.getModel().getSite().getName().replace(' ', '_').replace('\\', '_').replace('/', '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String s = getName();
|
|
||||||
if (getConfig().containsKey(FILE_NAME_TEMPLATE)) {
|
|
||||||
s += " [" + getConfig().get(FILE_NAME_TEMPLATE) + ']';
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@ public class Copy extends AbstractPostProcessor {
|
||||||
LOG.info("Creating a copy {}", copy);
|
LOG.info("Creating a copy {}", copy);
|
||||||
Files.copy(rec.getPostProcessedFile(), copy);
|
Files.copy(rec.getPostProcessedFile(), copy);
|
||||||
rec.setPostProcessedFile(copy);
|
rec.setPostProcessedFile(copy);
|
||||||
rec.getAssociatedFiles().add(copy.getAbsolutePath());
|
rec.getAssociatedFiles().add(copy.getCanonicalPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFilenameForCopy(File orig) {
|
private String getFilenameForCopy(File orig) {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
import static ctbrec.io.IoUtils.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import ctbrec.Recording;
|
||||||
|
|
||||||
|
public class DeleteOriginal extends AbstractPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "delete original";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postprocess(Recording rec) throws IOException, InterruptedException {
|
||||||
|
if (rec.getAbsoluteFile().isFile()) {
|
||||||
|
Files.deleteIfExists(rec.getAbsoluteFile().toPath());
|
||||||
|
deleteEmptyParents(rec.getAbsoluteFile().getParentFile());
|
||||||
|
} else {
|
||||||
|
deleteDirectory(rec.getAbsoluteFile());
|
||||||
|
deleteEmptyParents(rec.getAbsoluteFile());
|
||||||
|
}
|
||||||
|
rec.setAbsoluteFile(rec.getPostProcessedFile());
|
||||||
|
rec.getAssociatedFiles().remove(rec.getAbsoluteFile().getCanonicalPath());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package ctbrec.recorder.postprocessing;
|
||||||
|
import static ctbrec.io.IoUtils.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
import ctbrec.Recording;
|
||||||
|
|
||||||
|
public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(Rename.class);
|
||||||
|
public static final String PATH_TEMPLATE = "path.template";
|
||||||
|
public static final String DEFAULT = "${modelSanitizedName}" + File.separatorChar + "${localDateTime}";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "move";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postprocess(Recording rec) throws IOException {
|
||||||
|
String pathTemplate = getConfig().getOrDefault(PATH_TEMPLATE, DEFAULT);
|
||||||
|
String path = fillInPlaceHolders(pathTemplate, rec);
|
||||||
|
File src = rec.getPostProcessedFile();
|
||||||
|
File target = new File(path, src.getName());
|
||||||
|
LOG.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
||||||
|
Files.createParentDirs(target);
|
||||||
|
Files.move(rec.getPostProcessedFile(), target);
|
||||||
|
rec.setPostProcessedFile(target);
|
||||||
|
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
||||||
|
rec.setAbsoluteFile(target);
|
||||||
|
}
|
||||||
|
rec.getAssociatedFiles().remove(src.getCanonicalPath());
|
||||||
|
rec.getAssociatedFiles().add(target.getCanonicalPath());
|
||||||
|
|
||||||
|
if (src.isFile()) {
|
||||||
|
deleteEmptyParents(src.getParentFile());
|
||||||
|
} else {
|
||||||
|
deleteEmptyParents(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String s = getName();
|
||||||
|
if (getConfig().containsKey(PATH_TEMPLATE)) {
|
||||||
|
s += " [" + getConfig().get(PATH_TEMPLATE) + ']';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,9 +14,9 @@ import ctbrec.Recording;
|
||||||
import ctbrec.io.StreamRedirectThread;
|
import ctbrec.io.StreamRedirectThread;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
|
|
||||||
public class Remuxer extends AbstractPostProcessor {
|
public class Remux extends AbstractPostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Remuxer.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Remux.class);
|
||||||
|
|
||||||
public static final String FFMPEG_ARGS = "ffmpeg.args";
|
public static final String FFMPEG_ARGS = "ffmpeg.args";
|
||||||
public static final String FILE_EXT = "file.ext";
|
public static final String FILE_EXT = "file.ext";
|
||||||
|
@ -35,6 +35,7 @@ public class Remuxer extends AbstractPostProcessor {
|
||||||
argsPlusFile[i++] = "-i";
|
argsPlusFile[i++] = "-i";
|
||||||
argsPlusFile[i++] = rec.getPostProcessedFile().getAbsolutePath();
|
argsPlusFile[i++] = rec.getPostProcessedFile().getAbsolutePath();
|
||||||
System.arraycopy(args, 0, argsPlusFile, i, args.length);
|
System.arraycopy(args, 0, argsPlusFile, i, args.length);
|
||||||
|
File inputFile = rec.getPostProcessedFile();
|
||||||
File remuxedFile = new File(rec.getPostProcessedFile().getAbsolutePath() + '.' + fileExt);
|
File remuxedFile = new File(rec.getPostProcessedFile().getAbsolutePath() + '.' + fileExt);
|
||||||
argsPlusFile[argsPlusFile.length - 1] = remuxedFile.getAbsolutePath();
|
argsPlusFile[argsPlusFile.length - 1] = remuxedFile.getAbsolutePath();
|
||||||
String[] cmdline = OS.getFFmpegCommand(argsPlusFile);
|
String[] cmdline = OS.getFFmpegCommand(argsPlusFile);
|
||||||
|
@ -42,7 +43,10 @@ public class Remuxer extends AbstractPostProcessor {
|
||||||
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], rec.getPostProcessedFile().getParentFile());
|
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], rec.getPostProcessedFile().getParentFile());
|
||||||
setupLogging(ffmpeg, rec);
|
setupLogging(ffmpeg, rec);
|
||||||
rec.setPostProcessedFile(remuxedFile);
|
rec.setPostProcessedFile(remuxedFile);
|
||||||
rec.getAssociatedFiles().add(remuxedFile.getAbsolutePath());
|
rec.setAbsoluteFile(remuxedFile);
|
||||||
|
Files.deleteIfExists(inputFile.toPath());
|
||||||
|
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
||||||
|
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupLogging(Process ffmpeg, Recording rec) throws IOException, InterruptedException {
|
private void setupLogging(Process ffmpeg, Recording rec) throws IOException, InterruptedException {
|
|
@ -0,0 +1,48 @@
|
||||||
|
package ctbrec.recorder.postprocessing;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
import ctbrec.Recording;
|
||||||
|
|
||||||
|
public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(Rename.class);
|
||||||
|
public static final String FILE_NAME_TEMPLATE = "filename.template";
|
||||||
|
public static final String DEFAULT = "${modelSanitizedName}_${localDateTime}.${fileSuffix}";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "rename";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postprocess(Recording rec) throws IOException {
|
||||||
|
String filenameTemplate = getConfig().getOrDefault(FILE_NAME_TEMPLATE, DEFAULT);
|
||||||
|
String filename = fillInPlaceHolders(filenameTemplate, rec);
|
||||||
|
File src = rec.getPostProcessedFile();
|
||||||
|
File target = new File(src.getParentFile(), filename);
|
||||||
|
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
||||||
|
Files.move(rec.getPostProcessedFile(), target);
|
||||||
|
rec.setPostProcessedFile(target);
|
||||||
|
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
||||||
|
rec.setAbsoluteFile(target);
|
||||||
|
}
|
||||||
|
rec.getAssociatedFiles().remove(src.getCanonicalPath());
|
||||||
|
rec.getAssociatedFiles().add(target.getCanonicalPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String s = getName();
|
||||||
|
if (getConfig().containsKey(FILE_NAME_TEMPLATE)) {
|
||||||
|
s += " [" + getConfig().get(FILE_NAME_TEMPLATE) + ']';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue