Improve handling of the orignal and pp files
This commit is contained in:
parent
fbf1c8ac16
commit
e1bce0acf5
|
@ -157,6 +157,7 @@ public class JavaFxRecording extends Recording {
|
|||
setStatus(updated.getStatus());
|
||||
setProgress(updated.getProgress());
|
||||
setSizeInByte(updated.getSizeInByte());
|
||||
setSingleFile(updated.isSingleFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,6 +189,11 @@ public class JavaFxRecording extends Recording {
|
|||
return delegate.isSingleFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleFile(boolean singleFile) {
|
||||
delegate.setSingleFile(singleFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPinned() {
|
||||
return delegate.isPinned();
|
||||
|
|
|
@ -559,7 +559,6 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private void onOpenDirectory(JavaFxRecording first) {
|
||||
String recordingsDir = Config.getInstance().getSettings().recordingsDir;
|
||||
File tsFile = first.getAbsoluteFile();
|
||||
new Thread(() -> DesktopIntegration.open(tsFile.getParent())).start();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
|
|
|
@ -3,7 +3,7 @@ package ctbrec;
|
|||
public class NotImplementedExcetion extends RuntimeException {
|
||||
|
||||
public NotImplementedExcetion() {
|
||||
super();
|
||||
super("Not implemented");
|
||||
}
|
||||
|
||||
public NotImplementedExcetion(String mesg) {
|
||||
|
|
|
@ -17,12 +17,14 @@ public class 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) {
|
||||
while (parent != null && (parent.list() != null && parent.list().length == 0 || !parent.exists()) ) {
|
||||
if (parent.equals(recDir)) {
|
||||
return;
|
||||
}
|
||||
if(parent.exists()) {
|
||||
LOG.debug("Deleting empty directory {}", parent.getAbsolutePath());
|
||||
Files.delete(parent.toPath());
|
||||
}
|
||||
parent = parent.getParentFile();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
List<PostProcessor> postProcessors = config.getSettings().postProcessors;
|
||||
for (PostProcessor postProcessor : postProcessors) {
|
||||
LOG.debug("Running post-processor: {}", postProcessor.getName());
|
||||
postProcessor.postprocess(recording);
|
||||
postProcessor.postprocess(recording, config);
|
||||
}
|
||||
setRecordingStatus(recording, State.FINISHED);
|
||||
recordingManager.saveRecording(recording);
|
||||
|
@ -652,6 +652,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
Download download = other.getModel().createDownload();
|
||||
download.init(Config.getInstance(), other.getModel(), other.getStartDate());
|
||||
other.setDownload(download);
|
||||
other.setPostProcessedFile(null);
|
||||
submitPostProcessingJob(other);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
|
|||
"${recordingsDir}"
|
||||
};
|
||||
|
||||
public String fillInPlaceHolders(String input, Recording rec) {
|
||||
public String fillInPlaceHolders(String input, Recording rec, Config config) {
|
||||
// @formatter:off
|
||||
String output = input
|
||||
.replace("${modelName}", ofNullable(rec.getModel().getName()).orElse("modelName"))
|
||||
|
@ -39,8 +39,8 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
|
|||
.replace("${siteSanitizedName}", getSanitizedSiteName(rec))
|
||||
.replace("${fileSuffix}", getFileSuffix(rec))
|
||||
.replace("${epochSecond}", Long.toString(rec.getStartDate().getEpochSecond()))
|
||||
.replace("${modelNotes}", Config.getInstance().getModelNotes(rec.getModel()))
|
||||
.replace("${recordingsDir}", Config.getInstance().getSettings().recordingsDir)
|
||||
.replace("${modelNotes}", config.getModelNotes(rec.getModel()))
|
||||
.replace("${recordingsDir}", config.getSettings().recordingsDir)
|
||||
;
|
||||
|
||||
output = replaceUtcDateTime(rec, output);
|
||||
|
|
|
@ -2,12 +2,13 @@ package ctbrec.recorder.postprocessing;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class Copy extends AbstractPostProcessor {
|
||||
|
@ -20,20 +21,28 @@ public class Copy extends AbstractPostProcessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec) throws IOException, InterruptedException {
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
File orig = rec.getPostProcessedFile();
|
||||
String copyFilename = getFilenameForCopy(orig);
|
||||
File copy = new File(orig.getParentFile(), copyFilename);
|
||||
LOG.info("Creating a copy {}", copy);
|
||||
Files.copy(rec.getPostProcessedFile(), copy);
|
||||
if (orig.isFile()) {
|
||||
Files.copy(rec.getPostProcessedFile().toPath(), copy.toPath());
|
||||
} else {
|
||||
FileUtils.copyDirectory(orig, copy, true);
|
||||
}
|
||||
rec.setPostProcessedFile(copy);
|
||||
rec.getAssociatedFiles().add(copy.getCanonicalPath());
|
||||
}
|
||||
|
||||
private String getFilenameForCopy(File orig) {
|
||||
String filename = orig.getName();
|
||||
if (orig.isFile()) {
|
||||
String name = filename.substring(0, filename.lastIndexOf('.'));
|
||||
String ext = filename.substring(filename.lastIndexOf('.') + 1);
|
||||
return name + "_copy." + ext;
|
||||
} else {
|
||||
return filename + "_copy";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.NotImplementedExcetion;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "create contact sheet";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
throw new NotImplementedExcetion();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.NotImplementedExcetion;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class CreateTimelineThumbs extends AbstractPlaceholderAwarePostProcessor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "create timeline thumbnails";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
throw new NotImplementedExcetion();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import static ctbrec.io.IoUtils.*;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class DeleteOriginal extends AbstractPostProcessor {
|
||||
|
@ -15,7 +16,7 @@ public class DeleteOriginal extends AbstractPostProcessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec) throws IOException, InterruptedException {
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
if (rec.getAbsoluteFile().isFile()) {
|
||||
Files.deleteIfExists(rec.getAbsoluteFile().toPath());
|
||||
deleteEmptyParents(rec.getAbsoluteFile().getParentFile());
|
||||
|
|
|
@ -3,13 +3,13 @@ import static ctbrec.io.IoUtils.*;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||
|
@ -24,17 +24,17 @@ public class Move extends AbstractPlaceholderAwarePostProcessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec) throws IOException {
|
||||
public void postprocess(Recording rec, Config config) throws IOException {
|
||||
String pathTemplate = getConfig().getOrDefault(PATH_TEMPLATE, DEFAULT);
|
||||
String path = fillInPlaceHolders(pathTemplate, rec);
|
||||
String path = fillInPlaceHolders(pathTemplate, rec, config);
|
||||
File src = rec.getPostProcessedFile();
|
||||
File target = new File(path, src.getName());
|
||||
if (Objects.equals(src, target)) {
|
||||
return;
|
||||
}
|
||||
LOG.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
||||
Files.createParentDirs(target);
|
||||
Files.move(rec.getPostProcessedFile(), target);
|
||||
Files.createDirectories(target.getParentFile().toPath());
|
||||
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
||||
rec.setPostProcessedFile(target);
|
||||
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
||||
rec.setAbsoluteFile(target);
|
||||
|
|
|
@ -4,12 +4,13 @@ import java.io.IOException;
|
|||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public interface PostProcessor extends Serializable {
|
||||
String getName();
|
||||
|
||||
void postprocess(Recording rec) throws IOException, InterruptedException;
|
||||
void postprocess(Recording rec, Config config) throws IOException, InterruptedException;
|
||||
|
||||
Map<String, String> getConfig();
|
||||
void setConfig(Map<String, String> conf);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.NotImplementedExcetion;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class RemoveKeepFile extends AbstractPostProcessor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "remove recording, but keep the files";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
throw new NotImplementedExcetion();
|
||||
}
|
||||
}
|
|
@ -5,12 +5,15 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.OS;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.io.IoUtils;
|
||||
import ctbrec.io.StreamRedirectThread;
|
||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||
|
||||
|
@ -27,15 +30,18 @@ public class Remux extends AbstractPostProcessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec) throws IOException, InterruptedException {
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
String fileExt = getConfig().get(FILE_EXT);
|
||||
String[] args = getConfig().get(FFMPEG_ARGS).split(" ");
|
||||
String[] argsPlusFile = new String[args.length + 3];
|
||||
File inputFile = rec.getPostProcessedFile();
|
||||
if (inputFile.isDirectory()) {
|
||||
inputFile = new File(inputFile, "playlist.m3u8");
|
||||
}
|
||||
int i = 0;
|
||||
argsPlusFile[i++] = "-i";
|
||||
argsPlusFile[i++] = rec.getPostProcessedFile().getAbsolutePath();
|
||||
argsPlusFile[i++] = inputFile.getCanonicalPath();
|
||||
System.arraycopy(args, 0, argsPlusFile, i, args.length);
|
||||
File inputFile = rec.getPostProcessedFile();
|
||||
File remuxedFile = new File(rec.getPostProcessedFile().getAbsolutePath() + '.' + fileExt);
|
||||
argsPlusFile[argsPlusFile.length - 1] = remuxedFile.getAbsolutePath();
|
||||
String[] cmdline = OS.getFFmpegCommand(argsPlusFile);
|
||||
|
@ -43,16 +49,29 @@ public class Remux extends AbstractPostProcessor {
|
|||
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], rec.getPostProcessedFile().getParentFile());
|
||||
setupLogging(ffmpeg, rec);
|
||||
rec.setPostProcessedFile(remuxedFile);
|
||||
if (inputFile.getName().equals("playlist.m3u8")) {
|
||||
IoUtils.deleteDirectory(inputFile.getParentFile());
|
||||
if (Objects.equals(inputFile.getParentFile(), rec.getAbsoluteFile())) {
|
||||
rec.setAbsoluteFile(remuxedFile);
|
||||
}
|
||||
} else {
|
||||
Files.deleteIfExists(inputFile.toPath());
|
||||
if (Objects.equals(inputFile, rec.getAbsoluteFile())) {
|
||||
rec.setAbsoluteFile(remuxedFile);
|
||||
}
|
||||
}
|
||||
IoUtils.deleteEmptyParents(inputFile.getParentFile());
|
||||
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
||||
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
||||
rec.setSingleFile(true);
|
||||
rec.setSizeInByte(remuxedFile.length());
|
||||
}
|
||||
|
||||
private void setupLogging(Process ffmpeg, Recording rec) throws IOException, InterruptedException {
|
||||
int exitCode = 1;
|
||||
File video = rec.getPostProcessedFile();
|
||||
File ffmpegLog = new File(video.getParentFile(), video.getName() + ".ffmpeg.log");
|
||||
rec.getAssociatedFiles().add(ffmpegLog.getCanonicalPath());
|
||||
try (FileOutputStream mergeLogStream = new FileOutputStream(ffmpegLog)) {
|
||||
Thread stdout = new Thread(new StreamRedirectThread(ffmpeg.getInputStream(), mergeLogStream));
|
||||
Thread stderr = new Thread(new StreamRedirectThread(ffmpeg.getErrorStream(), mergeLogStream));
|
||||
|
@ -67,6 +86,7 @@ public class Remux extends AbstractPostProcessor {
|
|||
if (exitCode != 1) {
|
||||
if (ffmpegLog.exists()) {
|
||||
Files.delete(ffmpegLog.toPath());
|
||||
rec.getAssociatedFiles().remove(ffmpegLog.getCanonicalPath());
|
||||
}
|
||||
} else {
|
||||
rec.getAssociatedFiles().add(ffmpegLog.getAbsolutePath());
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||
|
@ -22,16 +22,16 @@ public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec) throws IOException {
|
||||
public void postprocess(Recording rec, Config config) throws IOException {
|
||||
String filenameTemplate = getConfig().getOrDefault(FILE_NAME_TEMPLATE, DEFAULT);
|
||||
String filename = fillInPlaceHolders(filenameTemplate, rec);
|
||||
String filename = fillInPlaceHolders(filenameTemplate, rec, config);
|
||||
File src = rec.getPostProcessedFile();
|
||||
File target = new File(src.getParentFile(), filename);
|
||||
if (Objects.equals(src, target)) {
|
||||
return;
|
||||
}
|
||||
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
||||
Files.move(rec.getPostProcessedFile(), target);
|
||||
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
||||
rec.setPostProcessedFile(target);
|
||||
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
||||
rec.setAbsoluteFile(target);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.NotImplementedExcetion;
|
||||
import ctbrec.Recording;
|
||||
|
||||
public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "execute script";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess(Recording rec, Config config) throws IOException, InterruptedException {
|
||||
// TODO make it possible to choose, which placeholders to pass to the script
|
||||
throw new NotImplementedExcetion();
|
||||
}
|
||||
}
|
|
@ -103,6 +103,11 @@
|
|||
<artifactId>guava</artifactId>
|
||||
<version>17.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -40,8 +40,6 @@ public class HlsServlet extends AbstractCtbrecServlet {
|
|||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
|
||||
String contextPath = getServletContext().getContextPath();
|
||||
String request = req.getRequestURI().substring(contextPath.length() + 5);
|
||||
Path recordingsDirPath = Paths.get(config.getSettings().recordingsDir).toAbsolutePath().normalize();
|
||||
|
@ -68,7 +66,10 @@ public class HlsServlet extends AbstractCtbrecServlet {
|
|||
String id = request.split("/")[0];
|
||||
Optional<Recording> rec = getRecordingById(id);
|
||||
if (rec.isPresent()) {
|
||||
File file = rec.get().getAbsoluteFile();
|
||||
File path = rec.get().getAbsoluteFile();
|
||||
if (!path.isFile()) {
|
||||
path = new File(path, requestedFile.getName());
|
||||
}
|
||||
if (LOG.isTraceEnabled()) {
|
||||
Enumeration<String> headerNames = req.getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
|
@ -76,7 +77,7 @@ public class HlsServlet extends AbstractCtbrecServlet {
|
|||
LOG.trace("{}: {}", header, req.getHeader(header));
|
||||
}
|
||||
}
|
||||
serveSegment(req, resp, file);
|
||||
serveSegment(req, resp, path);
|
||||
} else {
|
||||
error404(req, resp);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue